180 lines
5.7 KiB
Common Lisp
180 lines
5.7 KiB
Common Lisp
;; 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)
|
|
|