day 20 kicking me with duplicates

This commit is contained in:
efim 2022-12-25 09:10:19 +00:00
parent 2eb4b5c0a5
commit 974cc4993d
4 changed files with 5360 additions and 0 deletions

5000
day20-input.txt Normal file

File diff suppressed because it is too large Load Diff

241
day20-scratch.lisp Normal file
View File

@ -0,0 +1,241 @@
;; 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.
(defun get-ugh-nth (arr n)
(let* ((zero-ind (position 0 arr))
(unsafe-index (+ zero-ind n))
(safe-n (mod unsafe-index (length arr))))
(aref arr safe-n)))
(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,
(defun part-1-ans (filename)
(let* ((nums (mapcar #'parse-integer (uiop:read-file-lines filename)))
(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))))
(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

7
day20-test.txt Normal file
View File

@ -0,0 +1,7 @@
1
2
-3
3
-2
0
4

112
day20.lisp Normal file
View File

@ -0,0 +1,112 @@
;; https://adventofcode.com/2022/day/20
(defpackage :day-20
(:use :cl))
(in-package :day-20)
(ql:quickload :array-operations)
(ql:quickload "fiveam")
(ql:quickload 'alexandria)
(5am:def-suite day20-tests)
;; and shift some slice 1 to right
(defun move-item-to-left (array moved-index move-size)
(declare (optimize (debug 3)))
(let* ((move-size (mod move-size (1- (length array))))
(moved-value (aref array moved-index))
(move-by (- (mod move-size (length array))))
(moving-slice-size move-size)
(to-be-moved (make-array moving-slice-size :displaced-to array
:displaced-index-offset (+ moved-index move-by)))
(into-these-move (make-array moving-slice-size :displaced-to array
:displaced-index-offset (+ moved-index move-by 1))))
(loop
for i from (1- move-size) downto 0
do (setf (aref into-these-move i)
(aref to-be-moved i)))
(setf (aref array (+ moved-index move-by)) moved-value)
array))
(5am:def-test move-left-inside-of-array (:suite day20-tests)
(5am:is (equalp (make-array 10 :initial-contents '(0 1 2 6 3 4 5 7 8 9))
(move-item-to-left (aops:linspace 0 9 10) 6 3))))
(5am:def-test move-left-to-edge (:suite day20-tests)
(5am:is (equalp (make-array 10 :initial-contents '(6 0 1 2 3 4 5 7 8 9))
(move-item-to-left (aops:linspace 0 9 10) 6 6))))
(5am:def-test move-by-arr-size-leaves-intact (:suite day20-tests)
(5am:is (equalp (make-array 10 :initial-contents '(0 1 2 3 4 5 6 7 8 9))
(move-item-to-left (aops:linspace 0 9 10) 6 9))))
(5am:def-test move-by-more-than-arr-size (:suite day20-tests)
(5am:is (equalp (make-array 10 :initial-contents '(0 1 2 6 3 4 5 7 8 9))
(move-item-to-left (aops:linspace 0 9 10) 6 12))))
(defun move-item-to-right (array moved-index move-by)
(declare (optimize (debug 3)))
(let* ((move-by (mod move-by (1- (length array))))
(moved-value (aref array moved-index))
(moving-slice-size move-by)
(to-be-moved (make-array moving-slice-size
:displaced-to array
:displaced-index-offset (+ moved-index 1)))
(into-these-move (make-array moving-slice-size
:displaced-to array
:displaced-index-offset moved-index)))
(loop
for i from 0 below move-by
do (setf (aref into-these-move i)
(aref to-be-moved i)))
(setf (aref array (+ moved-index move-by)) moved-value)
array))
(5am:def-test move-right-inside-of-array (:suite day20-tests)
(5am:is (equalp (make-array 10 :initial-contents '(0 1 2 3 4 5 7 6 8 9))
(move-item-to-right (aops:linspace 0 9 10) 6 1))))
(5am:def-test move-right-to-edge (:suite day20-tests)
(5am:is (equalp (make-array 10 :initial-contents '(0 1 2 3 4 5 7 8 9 6))
(move-item-to-right (aops:linspace 0 9 10) 6 3))))
(5am:def-test move-right-by-arr-size-leaves-intact (:suite day20-tests)
(5am:is (equalp (make-array 10 :initial-contents '(0 1 2 3 4 5 6 7 8 9))
(move-item-to-right (aops:linspace 0 9 10) 6 9))))
(5am:def-test move-right-by-more-than-arr-size (:suite day20-tests)
(5am:is (equalp (make-array 10 :initial-contents '(0 1 2 3 4 5 7 8 9 6))
(move-item-to-right (aops:linspace 0 9 10) 6 12))))
(defun move-item (array move-index move-by)
(let* ((raw-target-index (if (>= move-by 0)
(+ move-index move-by)
(+ move-index move-by)))
(in-array-target-index (mod raw-target-index (1- (length array))))
(in-array-target-index (if (= 0 in-array-target-index)
(1- (length array))
in-array-target-index ; a hack
))
(safe-move-by (- in-array-target-index move-index)))
;; (list move-index move-by
;; 'raw-target raw-target-index
;; 'in-array-target in-array-target-index
;; 'safe-move-by safe-move-by)
(if (> safe-move-by 0)
(move-item-to-right array move-index safe-move-by)
(move-item-to-left array move-index (- safe-move-by)))
))
;; we know the element value, but not it's place
(defun move-elem-by-itself (array element)
(declare (optimize (debug 3)))
(let ((i (position element array)))
(move-item array i element)))
(defun mixing-array (arr)
(let ((to-be-modified (alexandria:copy-array arr)))
(loop
for elem across arr
do (progn (move-elem-by-itself to-be-modified elem)
(format t "after moving ~a, arr: ~a~%" elem to-be-modified)
))
to-be-modified))
(5am:run! 'day20-tests)