;; rucksack has 2 compartments ;; items have types ;; for each type there's 1 compartment where the item must go ;; elf put exactly 1 item into wrong compartment for each rucksack ;; item type is identified by letters a .. z A .. Z case sensitive ;; first half exactly is items in first compartment, second half of chars - items in second compartment ;;; find item type that appears in both compartments for each rucksack ;; translate then item type into priority a .. z -> 1 .. 26 ; A .. Z -> 27 .. 52 ;; return sum of all priorities ;;; ok. how to start solving that? (setq test-line "jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL") ;; i need to find char that appears in the first half and in the second half. ;; i could split the line in two, convert to list and use set diff function (setq half-length (/ (length test-line) 2)) (intersection (coerce (subseq test-line 0 half-length) 'list) (coerce (subseq test-line half-length) 'list)) ;; and now char to int, (- (char-int #\a) (- (char-int #\a) 1)) (- (char-int #\z) (- (char-int #\a) 1)) (- (char-int #\A) (- (char-int #\A) 27)) (- (char-int #\Z) (- (char-int #\A) 27)) (lower-case-p #\z) (lower-case-p #\A) (defun get-char-priority (ch) (if (lower-case-p ch) (- (char-int ch) (- (char-int #\a) 1)) (- (char-int ch) (- (char-int #\A) 27)))) (get-char-priority #\a) (get-char-priority #\z) (get-char-priority #\A) (get-char-priority #\L) (get-char-priority #\Z) (let* ((test-line "jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL") (first-compartment (coerce (subseq test-line 0 half-length) 'list)) (second-compartment (coerce (subseq test-line half-length) 'list)) (the-misplaced-item-type (intersection first-compartment second-compartment))) (get-char-priority (car the-misplaced-item-type))) ; in real life I'd need more defensiveness here, CAR woudn't be guaranteed (defun get-rucksack-misplaced-item-priority (rucksack-as-string) (let* ((test-line rucksack-as-string) (half-length (/ (length test-line) 2)) (first-compartment (coerce (subseq test-line 0 half-length) 'list)) (second-compartment (coerce (subseq test-line half-length) 'list)) (the-misplaced-item-type (intersection first-compartment second-compartment))) (get-char-priority (car the-misplaced-item-type))) ; in real life I'd need more defensiveness here, CAR woudn't be guaranteed ) (get-rucksack-misplaced-item-priority "jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL") (get-rucksack-misplaced-item-priority "PmmdzqPrVvPwwTWBwg") ;; again I'm making mistakes by referring to the globally visible symbols inside of the functions. so bad. ;; maybe i'd want to use something like "make-symbol" as recommended in the part on macro? ;; now the funciton seems to work, need to iterate over input file, call it for each line and sum (defun count-priories-in-file (filename) (let ((running-sum 0)) (with-open-file (in filename) (loop for line = (read-line in nil nil) while line do (incf running-sum (get-rucksack-misplaced-item-priority line)) finally (return running-sum))))) (count-priories-in-file "day3-input.txt") (count-priories-in-file "day3-test-input.txt") ;;; so, now different task for same input: ;; considering lines in groups of 3, what is their common char (group identification badge) ;; then map to priorities and sum ;; that should be a very similar program. ;; but how can i configure loop to give me 3 lines at a time? (defun get-three-rucksacks-id-badge (r1 r2 r3) (let* ((r1 (coerce r1 'list)) (r2 (coerce r2 'list)) (r3 (coerce r3 'list)) (badge-type-char (intersection (intersection r1 r2) r3))) (get-char-priority (car badge-type-char))) ; in real life I'd need more defensiveness here, CAR woudn't be guaranteed ) (get-three-rucksacks-id-badge "vJrwpWtwJgWrhcsFMMfFFhFp" "jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL" "PmmdzqPrVvPwwTWBwg") (defun count-id-badges-in-file (filename) (let ((running-sum 0)) (with-open-file (in filename) (loop for line1 = (read-line in nil nil) for line2 = (read-line in nil nil) for line3 = (read-line in nil nil) while line1 do (incf running-sum (get-three-rucksacks-id-badge line1 line2 line3)) finally (return running-sum))))) (count-id-badges-in-file "day3-test-input.txt") (count-id-badges-in-file "day3-input.txt") ;; surely there's a better way to use loop? ;; or maybe a good introduction into how to use it? ;; the documentation site doesn't give examples =C