;;;; https://adventofcode.com/2022/day/2 ;; input is lines [A B C] [X Y Z] ;; meaning a-b-c what opponent will play ;; and x y z what i should play in rock-paper-scissors ;; ;; score is calculated as: ;; 1 for Rock X ;; 2 for Paper Y ;; 3 for Scissors Z ;; ;; 0 if Lost ;; 3 if Tie ;; 6 if Win ;; ;; Win if ;; (A Y) (B Z) (C X) (setq MY-WIN-COMBINATIONS '((A Y) (B Z) (C X))) ;; ;; Loss if ;; (X B) (Y C) (Z A) (setq MY-LOSS-COMBINATIONS '((B X) (C Y) (A Z))) ;; ;; otherwise it's a tie (setq TIE-COMBINATIONS '((A X) (B Y) (C Z))) ;; now i'd also like to get symbol from the string... (equal (intern "a") (intern "A")) ; not exactly what i means, but yeah this is it ;; now i'd like to get list of two symbols from string of two symbols (setq my-test-line "A Z") ;; https://stackoverflow.com/questions/59516459/split-string-by-delimiter-and-include-delimiter-common-lisp (require 'cl-ppcre) (cl-ppcre:split "(\\.)" "a.bc.def.com" :with-registers-p t) (cl-ppcre:split "(\\.)" "a.bc.def.com" :with-registers-p nil) (setq my-test-line-list (mapcar #'intern (cl-ppcre:split "(\\ )" my-test-line :with-registers-p nil))) ;; yay ;;; now write scoring function over the lists of chars, for tie-win-loose match and for "my-selection-match" ;; sum the scores of the two parts of scoring ;; and iterate over input ;; would be cool to use pattern matching... ;; that's something like CASE in my (case 1 ((:in :in2) :lala) ((2 3) :numBig) ((1 -1) :numOne)) (case (list 1 2) ((:in :in2) :just-sym) ((list 1 2) :a-list)) ;; this doesn't work with lists. ;; COND is similar to CASE, except it is more general. It accepts arbitrary (find my-test-line-list my-win-combinations :TEST #'equal) (find my-test-line-list my-loss-combinations :TEST #'equal) (cond ((find my-test-line-list my-win-combinations :TEST #'equal) :WIN) ((find my-test-line-list my-loss-combinations :TEST #'equal) :LOSS) (t :TIE)) (defun score-result (hands) (cond ((find hands my-win-combinations :TEST #'equal) 6) ((find hands my-loss-combinations :TEST #'equal) 0) (t 3))) (score-result '(A Z)) (score-result '(A Y)) ;;; now let's get score of the hands, by only my hand (defun score-my-hand (hands) (let ((my-hand (second hands))) (case my-hand (X 1) (Y 2) (z 3)))) (score-my-hand '(A Z)) (score-my-hand '(A Y)) (score-my-hand '(A X)) (defun full-score-hands (hands) (+ (score-my-hand hands) (score-result hands))) (full-score-hands '(A Y)) (full-score-hands '(B X)) (full-score-hands '(C Z)) ;;; and now, iterate over file, converting strings into symbols and accumulating the score... (require 'cl-ppcre) (setq running-sum 0) (let ((running-sum 0)) (with-open-file (in "~/Documents/personal/advent-of-code/2022/day2-input.txt") (loop for line = (read-line in nil nil) while line ;; do (format t "line ~A~%" line) do (let* ((line-word-list (cl-ppcre:split "(\\ )" line :with-registers-p nil)) (hands (mapcar #'intern line-word-list))) (incf running-sum (full-score-hands hands))) finally (return running-sum) ))) ;; (setq my-test-line-list (mapcar #'intern (cl-ppcre:split "(\\ )" my-test-line :with-registers-p nil))) ;; 12156 is the right answer! ;; let's wrap this into a function (defun count-plays-score (filename) (require 'cl-ppcre) (let ((running-sum 0)) (with-open-file (in filename) (loop for line = (read-line in nil nil) while line do (let* ((line-word-list (cl-ppcre:split "(\\ )" line :with-registers-p nil)) (hands (mapcar #'intern line-word-list))) (incf running-sum (full-score-hands hands))) finally (return running-sum) )))) (count-plays-score "~/Documents/personal/advent-of-code/2022/day2-input.txt") ;;; now for the Second part of the game ;; second part means something else! ;; X - need to loose ;; Y - need to draw ;; Z - need to win ;; ;; so, scoring is the same, but I need to calculate what is my hand ;; C Z means they play (SCISSORS) and i need to WIN, so I need to get ROCK ;; that goes into the calculation of the score ;; i would be able to reuse the scoring function, ;; but! i need a funtion that returns my hand ;; let's put it off for a bit? ;; or no. so. this would be best with what? ugh. ;; so Z - find hand from loose-hands that starts with required hand ;; Y - find from draw, Z - find from win ;; could use #'FIND with cusom :TEST - to compare only first item (defun get-hand-set-by-result (hands) (case (second hands) (X my-loss-combinations) (Y tie-combinations) (Z my-win-combinations))) (get-hand-set-by-result '(A Y)) (get-hand-set-by-result '(B X)) (get-hand-set-by-result '(C Z)) ;; ok, somewhat like that (find (first '(A Y)) (get-hand-set-by-result '(A Y)) :KEY (lambda (hands) (first hands)) ) (defun count-plays-score-2 (filename) (require 'cl-ppcre) (let ((running-sum 0)) (with-open-file (in filename) (loop for line = (read-line in nil nil) while line do (let* ((line-word-list (cl-ppcre:split "(\\ )" line :with-registers-p nil)) (hand-and-result (mapcar #'intern line-word-list)) (handset (get-hand-set-by-result hand-and-result)) (hands (find (first hand-and-result) handset :KEY (lambda (hands) (first hands)) ))) (incf running-sum (full-score-hands hands))) finally (return running-sum) )))) (count-plays-score-2 "~/Documents/personal/advent-of-code/2022/day2-input.txt") ;; 10835 is the right answer!