Skip to content

Latest commit

 

History

History
264 lines (256 loc) · 7.31 KB

2021.11.org

File metadata and controls

264 lines (256 loc) · 7.31 KB

Day 11

Executing this code

If you have a lisp installation, emacs, org-mode, and org-babel support for lisp installed you can run this by:

  1. Starting slime (M-x slime)
  2. Typing C-c C-c in the block initialize.
  3. In the repl type (in-package :aoc-2021-11)
  4. Typing C-c C-c in the block answers

Initial stuffs

Packages to load

(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"))

Create package for this day

<<packages>>
(defpackage :aoc-2021-11
  (:use :common-lisp
        :parseq
        :fiveam)
  (:export :problem-a
           :problem-b))
(in-package :aoc-2021-11)

Input

(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"))

Part 1

(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*)))

Part 2

(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*)))

Putting it all together

<<read-input>>
<<input>>
<<flashdance>>
<<syncronicity>>
<<initialize>>
<<structs>>
<<functions>>
<<input>>
<<problem-a>>
<<problem-b>>
(problem-a)
(problem-b)

Answer

Problem 11 A: 1665
Problem 11 B: 235

Test Cases

(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)

Test Results

Running test suite AOC.2021.11
 Running test SAMPLE-INPUT ..
 Did 2 checks.
    Pass: 2 (100%)
    Skip: 0 ( 0%)
    Fail: 0 ( 0%)

Thoughts

Ada

Runner

Simple runner.

with AOC2021.Day11;
procedure Day11 is
begin
  AOC2021.Day11.Run;
end Day11;

Specification

Specification for solution.

package AOC2021.Day11 is
   procedure Run;
end AOC2021.Day11;

Packages

with GNAT.Regpat; use GNAT.Regpat;
with Text_IO; use Text_IO;

Types and generics

Implementation

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;

Run the program

In order to run this you have to “tangle” the code first using C-c C-v C-t.

cd ada
gnatmake day11
./day11