If you have a lisp installation, emacs, org-mode, and org-babel support for lisp installed you can run this by:
- Starting slime (
M-x slime
) - Typing
C-c C-c
in the block initialize. - In the repl type
(in-package :aoc-2021-11)
- Typing
C-c C-c
in the block answers
(unless (find-package :cl-ppcre)
(ql:quickload "cl-ppcre"))
(unless (find-package :iterate)
(ql:quickload "iterate"))
(unless (find-package :parseq)
(ql:quickload "parseq"))
(unless (find-package :lparallel)
(ql:quickload "lparallel"))
(unless (find-package :fiveam)
(ql:quickload "fiveam"))
(unless (find-package :series)
(ql:quickload "series"))
(unless (find-package :cl-permutation)
(ql:quickload "cl-permutation"))
(unless (find-package :bordeaux-threads)
(ql:quickload "bordeaux-threads"))
<<packages>>
(defpackage :aoc-2021-11
(:use :common-lisp
:parseq
:fiveam)
(:export :problem-a
:problem-b))
(in-package :aoc-2021-11)
(defun read-input (file)
(with-open-file (in file)
(loop
for line = (read-line in nil)
while line
collect line)))
(defparameter *input*
(read-input "input/11.txt"))
(defun lines-to-grid (lines)
(loop
with grid = (make-hash-table)
for line in lines
for i from 0
finally (return grid)
do (loop
for c across line
for j from 0
for coord = (complex i j)
do (setf (gethash coord grid) (- (char-code c) (char-code #\0))))))
(defun print-grid (grid)
(loop
for i from 0
while (gethash i grid)
do (loop for j from 0
for coord = (complex i j)
while (gethash coord grid)
do (format t "~a" (gethash coord grid)))
(format t "~%")))
(defun step-grid (grid)
(let ((flash-count 0)
(flashers (make-hash-table)))
;; increment each by 1
(loop for k being the hash-keys of grid
do (incf (gethash k grid 0)))
;; handle flashing...
(loop
with flashed? = t
while flashed?
do
(setf flashed? nil)
(loop
for k being the hash-keys of grid using (hash-value v)
if (and (< 9 v) (not (gethash k flashers)))
do
(incf flash-count)
(setf flashed? t)
(setf (gethash k flashers) t)
(loop
for i in '(#C(0 1) #C(0 -1) #C(1 0) #C(-1 0) #C(1 1) #C(1 -1) #C(-1 1) #C(-1 -1))
for coord = (+ k i)
for present? = (nth-value 1 (gethash coord grid))
if present?
do (incf (gethash coord grid)))))
;; set all flashers back to 0
(loop for k being the hash-keys of grid using (hash-value v)
if (< 9 v)
do (setf (gethash k grid) 0))
flash-count))
(defun solve-a (lines &optional (steps 100) (debug nil))
(let ((grid (lines-to-grid lines)))
(loop repeat steps
sum (step-grid grid)
if debug
do (terpri) (print-grid grid))))
(defun problem-a () (format t "Problem 11 A: ~a~%" (solve-a *input*)))
(defun solve-b (lines &optional (debug nil))
(let ((grid (lines-to-grid lines)))
(loop
for gens from 0
until (loop for v being the hash-values of grid
always (zerop v))
finally (return gens)
do (step-grid grid)
if debug
do (terpri) (print-grid grid))))
(defun problem-b () (format t "Problem 11 B: ~a~%" (solve-b *input*)))
<<read-input>>
<<input>>
<<flashdance>>
<<syncronicity>>
<<initialize>>
<<structs>>
<<functions>>
<<input>>
<<problem-a>>
<<problem-b>>
(problem-a)
(problem-b)
Problem 11 A: 1665 Problem 11 B: 235
(def-suite aoc.2021.11)
(in-suite aoc.2021.11)
(defparameter *test-input* (read-input "test/11.txt"))
(test sample-input
(is (= 1656 (solve-a *test-input*)))
(is (= 195 (solve-b *test-input*))))
(run! 'aoc.2021.11)
Running test suite AOC.2021.11 Running test SAMPLE-INPUT .. Did 2 checks. Pass: 2 (100%) Skip: 0 ( 0%) Fail: 0 ( 0%)
Simple runner.
with AOC2021.Day11;
procedure Day11 is
begin
AOC2021.Day11.Run;
end Day11;
Specification for solution.
package AOC2021.Day11 is
procedure Run;
end AOC2021.Day11;
with GNAT.Regpat; use GNAT.Regpat;
with Text_IO; use Text_IO;
Actual implementation body.
<<ada-packages>>
package body AOC2021.Day11 is
<<types-and-generics>>
-- Used as an example of matching regular expressions
procedure Parse_Line (Line : Unbounded_String; P : out Password) is
Pattern : constant String := "(\d+)-(\d+) ([a-z]): ([a-z]+)";
Re : constant Pattern_Matcher := Compile(Pattern);
Matches : Match_Array (0..4);
Pass : Unbounded_String;
P0, P1 : Positive;
C : Character;
begin
Match(Re, To_String(Line), Matches);
P0 := Integer'Value(Slice(Line, Matches(1).First, Matches(1).Last));
P1 := Integer'Value(Slice(Line, Matches(2).First, Matches(2).Last));
C := Element(Line, Matches(3).First);
Pass := To_Unbounded_String(Slice(Line, Matches(4).First, Matches(4).Last));
P := (Min_Or_Pos => P0,
Max_Or_Pos => P1,
C => C,
P => Pass);
end Parse_Line;
procedure Run is
begin
Put_Line("Advent of Code 2021 - Day 11");
Put_Line("The result for Part 1 is " & Integer'Image(0));
Put_Line("The result for Part 2 is " & Integer'Image(0));
end Run;
end AOC2021.Day11;
In order to run this you have to “tangle” the code first using C-c
C-v C-t
.
cd ada
gnatmake day11
./day11