#!/usr/bin/env -S emacs --script ;; -*- lexical-binding: t; -*- ;; Copyright (C) 2022 ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . (add-to-list 'load-path "../") (require 'ert) (require 'advent-of-code) (defvar solution-example-input "../../input/day-2-example.txt") (defvar solution-input "../../input/day-2.txt") (defvar solution-shapes '(rock paper scissors)) (defvar solution-outcomes '(win lose draw)) (defvar solution-opponent-letter-to-shape-alist '(("A" . rock) ("B" . paper) ("C" . scissors))) (defvar solution-player-letter-to-shape-alist '(("X" . rock) ("Y". paper) ("Z" . scissors))) (defvar solution-player-letter-to-outcome-alist '(("X" . lose) ("Y" . draw) ("Z" . win))) (defvar solution-shape-score-alist '((rock . 1) (paper . 2) (scissors . 3))) (defvar solution-outcome-score-alist '((win . 6) (draw . 3) (lose . 0))) ;; Each shape points to another shape creating a cyclical list. ;; Each shape points to the shape that it beats, so deciding a game ;; outcome is a simple list search! (defvar solution-shape-outcome-alist '((rock . scissors) (scissors . paper) (paper . rock))) (defun solution-decide-game (a b) (cond ((equal a b) 'draw) ((equal (cdr (assoc a solution-shape-outcome-alist)) b) 'win) (t 'lose))) (defun solution-shape-for-outcome (a outcome) (pcase outcome ('lose (cdr (assoc a solution-shape-outcome-alist))) ('draw a) ('win (car (seq-find (lambda (c) (equal (cdr c) a)) solution-shape-outcome-alist))))) (defun solution-part-1 (input) (let ((rows (seq-map (lambda (s) (string-split s " " t)) input))) (seq-reduce (lambda (acc row) (let* ((their-shape (cdr (assoc (car row) solution-opponent-letter-to-shape-alist))) (our-shape (cdr (assoc (cadr row) solution-player-letter-to-shape-alist))) (outcome (solution-decide-game our-shape their-shape))) (+ acc (cdr (assoc our-shape solution-shape-score-alist)) (cdr (assoc outcome solution-outcome-score-alist))))) rows 0))) (defun solution-part-2 (input) (let ((rows (seq-map (lambda (s) (string-split s " " t)) input))) (seq-reduce (lambda (acc row) (let* ((their-shape (cdr (assoc (car row) solution-opponent-letter-to-shape-alist))) (desired-outcome (cdr (assoc (cadr row) solution-player-letter-to-outcome-alist))) (our-shape (solution-shape-for-outcome their-shape desired-outcome))) (+ acc (cdr (assoc our-shape solution-shape-score-alist)) (cdr (assoc desired-outcome solution-outcome-score-alist))))) rows 0))) (ert-deftest solution-test-decide-game () (should (equal (solution-decide-game 'rock 'paper) 'lose)) (should (equal (solution-decide-game 'paper 'rock) 'win)) (should (equal (solution-decide-game 'rock 'rock) 'draw))) (ert-deftest solution-test-part-1-example () (should (equal (solution-part-1 (aoc-read-file-lines solution-example-input)) 15))) (ert-deftest solution-test-part-1-input () (should (equal (solution-part-1 (aoc-read-file-lines solution-input)) 12740))) (ert-deftest solution-test-part-2-example () (should (equal (solution-part-2 (aoc-read-file-lines solution-example-input)) 12))) (ert-deftest solution-test-part-2 () (should (equal (solution-part-2 (aoc-read-file-lines solution-input)) 11980))) (when noninteractive (ert-run-tests-batch-and-exit)) ;; Local Variables: ;; read-symbol-shorthands: (("solution-" . "advent-of-code-day-2-") ("aoc-" . "advent-of-code-")) ;; End: