Skip to content

Latest commit

 

History

History
278 lines (270 loc) · 7.83 KB

2020.06.org

File metadata and controls

278 lines (270 loc) · 7.83 KB

Day 06

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-2020-06)
  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 :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-2020-06
  (:use :common-lisp
        :iterate
        :parseq
        :fiveam)
  (:export :problem-a
           :problem-b))
(in-package :aoc-2020-06)

Input

(defun read-input (file)
  (iter (for line in-file file using #'read-line)
        (collect line)))
(defparameter *input*
  (read-input "input/06.txt"))

Part 1

The input consists of series of question answers from multiple people. I will take their answers, put them into a hash table (so duplicates aren’t double counted) and then total answers given over all groups.

(defun split-groups (raw)
  (loop for s in raw
     with total = nil
     with current = ""
     do (cond ((string= "" s)
               (push current total)
               (setf current ""))
              (t (setf current (concatenate 'string current s))))
     finally (return (push current total))))
(defun count-anyone-answers (s)
  (loop for c across s
     with h = (make-hash-table)
     do (setf (gethash c h) t)
     finally (return (hash-table-count h))))
(defun tally-anyone-answers (groups)
  (reduce #'+ (mapcar #'count-anyone-answers groups)))
<<split-groups>>
<<count-anyone-answers>>
<<tally-anyone-answers>>
(defun problem-a () (format t "Problem 06 A: ~a~%" (tally-anyone-answers (split-groups *input*))))

Part 2

Instead of questions anyone answers yes to, we need the count of ones they all answered yes to. Same tally across all groups, but now the way we tally changes.

(defun gather-groups (raw)
  (loop for s in raw
     with total = nil
     with current = nil
     do (cond ((string= "" s)
               (push current total)
               (setf current nil))
              (t (push s current)))
     finally (return (push current total))))
(defun count-everyone-answers (group)
  (let ((letters "abcdefghijklmnopqrstuvwxyz"))
    (loop for s in group
       with l = letters
       do (loop for c across letters
             do (unless (position c s)
                  (setf l (remove c l))))
       finally (return (length l)))))
(defun tally-everyone-answers (groups)
  (reduce #'+ (mapcar #'count-everyone-answers groups)))
<<gather-groups>>
<<count-everyone-answers>>
<<tally-everyone-answers>>
(defun problem-b ()
  (format t "Problem 06 B: ~a~%"
          (tally-everyone-answers (gather-groups *input*))))

Putting it all together

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

Answer

Problem 06 A: 6249
Problem 06 B: 3103

Test Cases

(def-suite aoc.2020.06)
(in-suite aoc.2020.06)

(run! 'aoc.2020.06)

Test Results

Thoughts

Ada

Simple runner.

with AOC2020.Day06;
procedure Day06 is
begin
  AOC2020.Day06.Run;
end Day06;

Specification for solution.

package AOC2020.Day06 is
   procedure Run;
end AOC2020.Day06;

Actual implementation body.

with Text_IO; use Text_IO;
package body AOC2020.Day06 is
   procedure Sum_Of_Anyones_Answers is
      F : File_Type;
      Count, T : Natural := 0;
      Answers : array (Character range 'a' .. 'z') of Boolean
        := (others => False);
      C : Character;
   begin
      Open (F, In_File, "../input/06.txt");
      loop
         if End_Of_Line (F) or End_Of_File (F)
         then
            if End_Of_Line (F) then Skip_Line(F); end if;
            if End_Of_Line (F) or End_Of_File(F)
            then
               T := 0;
               for B of Answers loop
                  if B
                  then T := T + 1;
                  end if;
               end loop;
               Count := Count + T;
               Answers := (others => False);
               exit when End_Of_File(F);
            end if;
         end if;
         Get (F, C);
         Answers (C) := True;
      end loop;
      Close (F);
      Put_Line ("The result for Part 1 is: " & Count'Image);
   end Sum_Of_Anyones_Answers;

   procedure Sum_Of_Everyones_Answers is
      F : File_Type;
      Count, T : Natural := 0;
      Answers : array (Character range 'a' .. 'z') of Integer
        := (others => 0);
      Group_Count : Natural := 0;
      C : Character;
   begin
      Open (F, In_File, "../input/06.txt");
      loop
         if End_Of_Line (F) or End_Of_File (F)
         then
            if End_Of_Line (F) then Skip_Line (F); end if;
            Group_Count := Group_Count + 1;
            if End_Of_Line (F) or End_Of_File (F)
            then
               T := 0;
               for I of Answers loop
                  if I = Group_Count
                  then T := T + 1;
                  end if;
               end loop;
               Count := Count + T;
               Group_Count := 0;
               Answers := (others => 0);
               exit when End_Of_File(F);
            end if;
         end if;
         Get (F, C);
         Answers (C) := Answers (C) + 1;
      end loop;
      Close (F);
      Put_Line("The result for Part 2 is: " & Count'Image);
   end Sum_Of_Everyones_Answers;

   procedure Run is
   begin
      Put_Line("Advent of Code 2020 - Day 06:"); New_Line;
      Sum_Of_Anyones_Answers;
      Sum_Of_Everyones_Answers;
   end Run;
end AOC2020.Day06;

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

cd ada
gnatmake day06
./day06
Advent of Code 2020 - Day 06:

The result for Part 1 is:  6249
The result for Part 2 is:  3103