258 lines
8.3 KiB
Common Lisp
258 lines
8.3 KiB
Common Lisp
;; https://adventofcode.com/2022/day/20
|
|
|
|
(in-package :day-20)
|
|
|
|
;; so. how would i do moves in a list?
|
|
;; and are there duplicate numbers?
|
|
;; it's possible but not sure.
|
|
;; also in the input numbers are 4k 5k.
|
|
;; i guess on during the moving it would be best to figure out their index?
|
|
;; could i insert into list at index?
|
|
;; it could be nice to use just cycled list. but.
|
|
;; maybe use array?
|
|
|
|
'(1 2 -3 3 -2 0 4)
|
|
;; calculating index and then modifying array. is it easy to do shifts on array?
|
|
;; and i'd sometimes need to
|
|
;; and how multiple passes work with going over self?
|
|
;; let's take a break
|
|
;; i guess i could copy part of array with the offset arrays
|
|
;;
|
|
;; the stupid version seems to be 4 cases :
|
|
;; - to right inside of array
|
|
;; - to right over with overflow
|
|
;; - to left inside of array
|
|
;; - to left over with overflow
|
|
;; but when overflow - could stop to the left or to the right of self.
|
|
|
|
(defparameter *my-arr*
|
|
(aops:linspace 0 9 10))
|
|
|
|
;; imagine i'm displacing 345 by 1 to right
|
|
;; ( that would mean 6 moving 3 to the left)
|
|
(setq *my-arr* (aops:linspace 0 9 10))
|
|
(let ((to-be-moved (make-array 3 :displaced-to *my-arr* :displaced-index-offset 3))
|
|
(into-these-move (make-array 3 :displaced-to *my-arr* :displaced-index-offset 4)))
|
|
(loop
|
|
for i from 2 downto 0
|
|
do (setf (aref into-these-move i) (aref to-be-moved i))))
|
|
|
|
*my-arr*
|
|
|
|
;; now displacing 345 by 1 to left
|
|
(setq *my-arr* (aops:linspace 0 9 10))
|
|
(let ((to-be-moved (make-array 3 :displaced-to *my-arr* :displaced-index-offset 3))
|
|
(into-these-move (make-array 3 :displaced-to *my-arr* :displaced-index-offset 2)))
|
|
(loop
|
|
for i from 0 below 3
|
|
do (setf (aref into-these-move i) (aref to-be-moved i))))
|
|
*my-arr*
|
|
|
|
;; now let's also remember "moved" element and put it to the "freed up space"
|
|
;; moving 6 by 3 to the left
|
|
(setq *my-arr* (aops:linspace 0 9 10))
|
|
(let* ((index-of-moved 6)
|
|
(moved-value (aref *my-arr* index-of-moved))
|
|
(move-by -3)
|
|
(to-be-moved (make-array 3 :displaced-to *my-arr*
|
|
:displaced-index-offset (+ index-of-moved move-by)))
|
|
(into-these-move (make-array 3 :displaced-to *my-arr*
|
|
:displaced-index-offset (+ index-of-moved move-by 1))))
|
|
(loop
|
|
for i from 2 downto 0
|
|
do (setf (aref into-these-move i) (aref to-be-moved i)))
|
|
(setf (aref *my-arr* (+ index-of-moved move-by)) moved-value))
|
|
*my-arr*
|
|
|
|
;; ok. but these 2 downto 0 || 0 to 2 dependent on -3 +3 and that's ugh
|
|
|
|
|
|
|
|
;; moving 2 by 3 to the right (now displacing 345 by 1 to left)
|
|
(setq *my-arr* (aops:linspace 0 9 10))
|
|
(let* ((index-of-moved 2)
|
|
(moved-value (aref *my-arr* index-of-moved))
|
|
(move-by 3)
|
|
(to-be-moved (make-array 3 :displaced-to *my-arr*
|
|
:displaced-index-offset (+ index-of-moved 1)))
|
|
(into-these-move (make-array 3 :displaced-to *my-arr*
|
|
:displaced-index-offset index-of-moved)))
|
|
(loop
|
|
for i from 0 to 2
|
|
do (setf (aref into-these-move i) (aref to-be-moved i)))
|
|
(setf (aref *my-arr* (+ index-of-moved move-by)) moved-value))
|
|
*my-arr*
|
|
|
|
;; so also difference in displaced indexes.
|
|
;; shift to LEFT (move item left):
|
|
;;
|
|
;; shift to RIGHT (move item right):
|
|
|
|
;; well, i could just save this code as two separate functions
|
|
;; would be nice to immediately start doing the repeatable tests
|
|
|
|
(move-item-to-left (aops:linspace 0 9 10) 6 6)
|
|
|
|
;; and a separate function for swithing to the right?
|
|
|
|
(move-item-to-right (aops:linspace 0 9 10) 6 1)
|
|
(move-item-to-right (aops:linspace 0 9 10) 6 2)
|
|
(move-item-to-right (aops:linspace 0 9 10) 6 3)
|
|
|
|
;; next what? calculation of the target index through modulo
|
|
'(1 2 3 4 5 6 7 8 9)
|
|
;; if we're moving 2 by -2 how does that work?
|
|
;; we have starting index 1, we have length 9.
|
|
;; my guess is that take MOD by 9-1
|
|
;; how many swaps to the right until the element returns to its original place?
|
|
'(1 2 3 4 5 6 7 8 9)
|
|
'(2 1 3 4 5 6 7 8 9)
|
|
'(1 3 4 5 6 7 8 9 2)
|
|
'(1 3 4 5 6 7 8 2 9)
|
|
'(1 3 4 5 6 7 2 8 9)
|
|
'(1 3 4 5 6 2 7 8 9)
|
|
'(1 3 4 5 2 6 7 8 9)
|
|
'(1 3 4 2 5 6 7 8 9)
|
|
'(1 3 2 4 5 6 7 8 9)
|
|
'(1 2 3 4 5 6 7 8 9)
|
|
;; so, if moving by 9. hm
|
|
|
|
;; then moving by 12 is 9 + 3
|
|
(mod 9 3)
|
|
(mod 10 3)
|
|
(length (make-array 7))
|
|
|
|
(move-item-to-left (aops:linspace 0 9 10) 6 9)
|
|
|
|
;; ok, now join into one function that moves the element by it's value?
|
|
|
|
(find 4 '(1 4 3 2 9))
|
|
(position 4 '(1 4 3 2 9))
|
|
|
|
(defparameter *test-array* (make-array 7 :initial-contents '(1 2 -3 3 -2 0 4)))
|
|
*test-array*
|
|
|
|
(move-elem-by-itself *test-array* -2)
|
|
|
|
|
|
;; whelp. my movements are ugh.
|
|
;; so. "i'd want additional move on top of my move-left and move-right"?
|
|
(mod -1 3)
|
|
|
|
(move-item *test-array* 3 3)
|
|
(move-item *test-array* 3 4)
|
|
|
|
(defparameter *test-array* (make-array 7 :initial-contents '(1 2 -3 3 -2 0 4)))
|
|
*test-array*
|
|
|
|
(move-elem-by-itself *test-array* -2)
|
|
;; this seems to work.
|
|
;; now back to the loop?
|
|
|
|
(defparameter *test-array* (make-array 7 :initial-contents '(1 2 -3 3 -2 0 4)))
|
|
(mixing-array *test-array*)
|
|
;; after moving 2, arr: #(1 -3 2 3 -2 0 4)
|
|
;; after moving -3, arr: #(1 2 3 -2 0 -3 4)
|
|
;; -3 move wasn't correct
|
|
|
|
(loop for elem across *test-array*
|
|
do (print elem))
|
|
|
|
(defparameter *test-array* (make-array 7 :initial-contents '(1 -3 2 3 -2 0 4)))
|
|
(move-elem-by-itself *test-array* -3)
|
|
;; 0 -> 0
|
|
;; -1 -> (len - 1)
|
|
;; -2 -> (len - 2)
|
|
(mod -1 7)
|
|
;; so, just hack it? when we move to the left, we add one more?
|
|
;; so, ugh and when moving to positive, but going over the what
|
|
;; the number is not "switched" with the neighbor, it's jumping over the neighbor...
|
|
;; so, if we go to 0 or to len-1 then we jump to the other side?
|
|
|
|
(defparameter *test-array* (make-array 7 :initial-contents '(1 -3 3 -2 2 0 4)))
|
|
(move-elem-by-itself *test-array* 2)
|
|
|
|
(defparameter *test-array* (make-array 7 :initial-contents '(1 -3 3 -2 2 4 0)))
|
|
(move-elem-by-itself *test-array* 4)
|
|
|
|
(defparameter *test-array* (make-array 7 :initial-contents '(1 2 -3 0 3 4 -2)))
|
|
(move-item *test-array* 5 4)
|
|
(move-elem-by-itself *test-array* 4)
|
|
|
|
;; now this incorrect:
|
|
;; after moving 3, arr: #(1 2 -2 -3 0 3 4)
|
|
;; after moving -2, arr: #(-2 1 2 -3 0 3 4)
|
|
;; -2 should have went instead of to 0 straight to the end. so
|
|
;;
|
|
|
|
;; and now it works
|
|
;; god i also need to take 1000th value with overbound. ugh.
|
|
|
|
|
|
(get-ugh-nth (mixing-array *test-array*) 1000)
|
|
(get-ugh-nth (mixing-array *test-array*) 2000)
|
|
(get-ugh-nth (mixing-array *test-array*) 3000)
|
|
;; uh. after the value 0...
|
|
;; so first find index of 0
|
|
|
|
(let* ((nums (mapcar #'parse-integer (uiop:read-file-lines "day20-input.txt")))
|
|
(input-arr (make-array (length nums) :initial-contents nums))
|
|
(mixed (mixing-array input-arr)))
|
|
(+ (get-ugh-nth (mixing-array mixed) 1000)
|
|
(get-ugh-nth (mixing-array mixed) 2000)
|
|
(get-ugh-nth (mixing-array mixed) 3000)))
|
|
;; 1797 is too low,
|
|
|
|
|
|
|
|
(part-1-ans "day20-test.txt")
|
|
(part-1-ans "day20-input.txt")
|
|
|
|
;; well, do we have duplicates?
|
|
|
|
(ql:quickload :fset)
|
|
(fset:set 1 2 3)
|
|
(fset:set '(1 2 3))
|
|
(print (let* ((nums (mapcar #'parse-integer (uiop:read-file-lines "day20-input.txt")))
|
|
(input-arr (make-array (length nums) :initial-contents nums))
|
|
(input-set (fset:convert 'fset:set nums))
|
|
)
|
|
(list 'arr (length input-arr) 'set (fset:size input-set))
|
|
))
|
|
;; (ARR 5000 SET 3613)
|
|
;; well, yupikayey
|
|
;; how should i be doint that?
|
|
;; AND i should have checked that from the start.
|
|
;; so. there are duplicates.
|
|
|
|
(fset:convert 'fset:bag '(1 2 3 2 4 5))
|
|
;; what should i do about the duplicates?
|
|
;; i'd need to store elements with their initial indexes i suppose
|
|
;; and then what? iterate not over initial collection, but just over "initial" indexes
|
|
|
|
;; so, how'd i do that?
|
|
;; #'move-item works with index and move-by
|
|
;; so shouldn't depent on type of elements
|
|
;; so just #'move-elem-by-itself should take in "original index"
|
|
;; then find position in the array by the index.
|
|
;; and array would be (index value)
|
|
|
|
(zip-with-index '(2 14 1 3 5))
|
|
|
|
(input-arr "day20-test.txt")
|
|
|
|
(mixing-array (input-arr "day20-test.txt"))
|
|
;; and it works, now.
|
|
;;
|
|
;; next - extract the values from the 1000th etc
|
|
|
|
;; wait what. why did i do the mixing again. ugh
|
|
;; was that the problem, not the duplicates? will revert after getting to the answer,
|
|
;; but yikes
|
|
|
|
;; oh, i need to find 0 by value in new array
|
|
(part-1-ans "day20-test.txt")
|
|
(part-1-ans "day20-input.txt")
|
|
;; and i get a gold star.
|
|
;; let's commit and try with revert?
|