;; https://adventofcode.com/2022/day/13 ;; so, generally i need to implement calculation of ordering on the nested structures ;; each packet is a list, containst lists or integers ;; rules for comparison: ;; - if both are integers : lowest input is with lowest int ;; - if both are lists : compare lists in order by elements. if one runs out of items - it's lower ;; - if one is list and another is int : convert integer to list of one element and compare. i.e compare with head of list, and equal only if other list is of size 1 ;; i'd really like to just read in Sexps (with-open-file (in "day13-test.txt") (read in)) ;; ok, i have list of the lists \ packets ;; now i'd want to compare them pairwise. what would be process? (defun nest-< (left right) (cond ((and (numberp left) (numberp right)) (< left right)) ((numberp left) (nest-< (list left) right)) ((numberp right) (nest-< left (list right))) ((and (listp left) (listp right)) (cond ((and (not left) (not right)) nil) ; both equal and empty ((not left) t) ; only left empty, left is smaller ((not right) nil) ; only right is empty, left is bigger (t (if (equal (first left) (first right)) (nest-< (rest left) (rest right)) (nest-< (first left) (first right)))))) (t 'default))) (nest-< 4 3) (nest-< 3 4) (listp '(1 234)) (listp '()) (listp nil) (nest-< '(1 (2 (3 (4 (5 6 7)))) 8 9) '(1 (2 (3 (4 (5 6 0)))) 8 9)) (nest-< '(9) '((8 7 6))) (nest-< '((1) (2 3 4)) '((1) 4)) ;; ok, this seems to work ;; how do i order input? hashmap would be nice? ;; if to wrap into list pairwise - should do so programmatically (defparameter *day13-all-list* nil) (setq *day13-all-list* (with-open-file (in "day13-test.txt") (read in))) ;; or i could break them into two lists? and map pairwise? ;; maybe with DO ? (defparameter *day13-lefts* nil) (defparameter *day13-rights* nil) (loop for i from 0 below (length *day13-all-list*) when (= 0 (mod i 2)) do (push (nth i *day13-all-list*) *day13-lefts*) when (= 1 (mod i 2)) do (push (nth i *day13-all-list*) *day13-rights*)) (setq *day13-lefts* (reverse *day13-lefts*)) (setq *day13-rights* (reverse *day13-rights*)) nil (mapcar #'nest-< *day13-lefts* *day13-rights*) (defparameter *day13-indices* nil) (setq *day13-indices* (loop for i from 0 below (length *day13-lefts*) when (nest-< (nth i *day13-lefts*) (nth i *day13-rights*)) collect (1+ i))) (apply #'+ *day13-indices*) (length *day13-lefts*) (length *day13-rights*) *day13-indices* ;; well, how should this compare: ;; [[9]] ;; [[[[8,9],[2],7,3,7]],[[],[[8],[],[3,4,4,2],2,5],2],[3,6,10]] ;; first is bigger, right? (apply #'+ '( 2 2 2 2)) (apply #'+ *day13-indices*) ; 5739 , but not correct answer. why =C (defparameter *day13-artem-indices* (list 1 7 11 16 18 19 20 23 26 27 28 30 33 35 37 38 39 42 43 44 45 47 50 51 52 54 55 60 61 63 66 67 70 71 74 75 78 79 81 82 83 85 86 87 88 89 91 95 97 98 99 101 103 105 108 110 111 112 113 114 115 120 122 123 127 134 136 139 140 142 144 145 146 149 150)) (ql:quickload 'fset) (fset:set *day13-indices*) (fset:set-difference (fset:convert 'fset:set *day13-artem-indices*) (fset:convert 'fset:set *day13-indices*)) (print *day13-indices*) (print *day13-artem-indices*) ;; 86, is in Artems and not in mine ;; Comparing: (nest-< '(NIL (6 (7 (7 6 4 10 10) NIL 0 NIL) (1) ((1 4 5 9 8) 6 (6 4 2) (5 3 7) 10)) (6 (2 3 10 (0 6 9 10)) (0) ((10 2) 4)) ((NIL 1 0 NIL 7) ((0 4) 5 (9 3 7 10 1) 2) 0 4 4)) '((0 10 8) ((8 9 (1 10 9 3) 2 1)))) (length *day13-lefts*) (numberp nil) (not '(1)) (not '()) (print (nth 85 *day13-lefts*)) (print (nth 85 *day13-rights*)) (nest-< (nth 85 *day13-lefts*) (nth 85 *day13-rights*)) ;; ((2) (((3 4) 2 (9) (5 8 8 0 2))) (5) (1)) ;; ((((2) 7) NIL)) ;; ;; oh. i shouldn't just compare (list left) ;; i need to pass in rest. in what way? ;; so, comparing of the rest is required (nest-< '(2) '((2) 7)) ; here it is... ;; so in case it IS equal in (nest-< (first left) (first right)) ;; need to check tails ;; so, i need to return -1 0 and 1 i guess now ;; negative is less than (defun nest-2-< (left right) (cond ((and (numberp left) (numberp right)) (- left right)) ((numberp left) (nest-2-< (list left) right)) ((numberp right) (nest-2-< left (list right))) ((and (listp left) (listp right)) (cond ((and (not left) (not right)) 0) ; both equal and empty ((not left) -1) ; only left empty, left is smaller ((not right) 1) ; only right is empty, left is bigger (t (if (equal (first left) (first right)) (nest-2-< (rest left) (rest right)) (let ((head-comparison (nest-2-< (first left) (first right)))) (if (= 0 head-comparison) (nest-2-< (rest left) (rest right)) head-comparison)))))) (t 'default))) (nest-2-< '(2) '((2) 7)) ; here it is... ;;; PART 2 ;; now working with the whole list - i need to sort it with that function (let ((sorted (sort (copy-list *day13-all-list*) (lambda (left right) (< (nest-2-< left right) 0))))) (* (1+ (position '((2)) sorted :test #'equal)) (1+ (position '((6)) sorted :test #'equal)))) (sort '(5 1 432 2 14) #'>) (sort '(5 1 432 2 14) #'<) (< 1 2) (find '(1 2) '(1 (1 3) (1 2)) :test #'equal) (position '(1 2) '(1 (1 3) (1 2)) :test #'equal)