Skip to content

Latest commit

 

History

History
305 lines (296 loc) · 8.56 KB

2021.02.org

File metadata and controls

305 lines (296 loc) · 8.56 KB

Day 02

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

Input

(defun read-input (file)
  (with-open-file (in file)
    (loop
       for direction = (read in nil)
       for distance = (read in nil)
       while (and direction distance)
       collect (list direction distance))))
(defparameter *input* (read-input "input/02.txt"))

Part 1

(defun follow-directions (directions)
  (loop
     with position = #C(0 0)
     for (dir dist) in directions
     finally (return (* (realpart position) (imagpart position)))
     do (case dir
          (up (decf position dist))
          (down (incf position dist))
          (forward (incf position (complex 0 dist))))))
     
(defun problem-a () (format t "Problem 02 A: ~a~%" (follow-directions *input*)))

Part 2

(defun follow-directions-aim (directions)
  (loop
     with position = #C(0 0)
     with aim = 0
     for (dir dist) in directions
     finally (return (* (realpart position) (imagpart position)))
     do (case dir
          (up (decf aim dist))
          (down (incf aim dist))
          (forward (incf position (complex (* aim dist) dist))))))
     
(defun problem-b () (format t "Problem 02 B: ~a~%" (follow-directions-aim *input*)))

Putting it all together

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

Answer

Problem 02 A: 2091984
Problem 02 B: 2086261056

Test Cases

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

(run! 'aoc.2021.02)

Test Results

Thoughts

Ada

Runner

Simple runner.

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

Specification

Specification for solution.

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

Packages

with Text_IO; use Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;

Types and generics

type Direction is (Up, Down, Forward);
package Direction_IO is new Enumeration_IO(Direction);
use Direction_IO;

Part 1

function Follow_Directions return Integer is
   Input_File : File_Type;
   To : Direction;
   By : Integer;
   Depth : Integer := 0;
   Horizontal : Integer := 0;
begin
   Open (Input_File, In_File, "../input/02.txt");
   loop
      exit when end_of_file (Input_File);
      Get (Input_File, To);
      Get (Input_File, By);
      case To is
         when Up => Depth := Depth - By;
         when Down => Depth := Depth + By;
         when Forward => Horizontal := Horizontal + By;
      end case;
   end loop;
   Close (Input_File);
   return Depth * Horizontal;
end Follow_Directions;

Part 2

function Follow_Directions_Aim return Integer is
   Input_File : File_Type;
   To : Direction;
   By : Integer;
   Depth : Integer := 0;
   Horizontal : Integer := 0;
   Aim : Integer := 0;
begin
   Open (Input_File, In_File, "../input/02.txt");
   loop
      exit when end_of_file (Input_File);
      Get (Input_File, To);
      Get (Input_File, By);
      case To is
         when Up => Aim := Aim - By;
         when Down => Aim := Aim + By;
         when Forward =>
            Horizontal := Horizontal + By;
            Depth := Depth + Aim * By;
      end case;
   end loop;
   Close (Input_File);
   return Depth * Horizontal;
end Follow_Directions_Aim;

Implementation

Actual implementation body.

<<ada-packages>>
package body AOC2021.Day02 is
   <<types-and-generics>>
   <<ada-part-1>>
   <<ada-part-2>>
   procedure Run is
   begin
      Put_Line("Advent of Code 2021 - Day 02");
      Put_Line("The result for Part 1 is " & Integer'Image(Follow_Directions));
      Put_Line("The result for Part 2 is " & Integer'Image(Follow_Directions_Aim));
   end Run;
end AOC2021.Day02;

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 day02
./day02
Advent of Code 2021 - Day 02
The result for Part 1 is  2091984
The result for Part 2 is  2086261056

Rust

I’m not splitting it up this time, placing here for completeness. This is also located in Day 2 Rust Source.

Some thoughts:

  • Type inference is great. I need to remember to specify types more often, but Rust does a good job of propagating type information. d, h, and aim didn’t have to be specified as i64 since this could be determined by the function return type.
  • str/string is confusing.
  • The borrow checker is both friend and foe. I had a version that used an iterator (like day 1) but ran into a problem after splitting the input. Now I think I know the solution, but this version is probably clearer anyways.
use std::fs::File;
use std::io::{BufRead, BufReader};

pub fn day02_01() -> i64 {
    let filename = "../input/02.txt";
    let file = File::open(filename).unwrap();
    let reader = BufReader::new(file);
    let (mut h, mut d) = (0, 0);
    for line in reader.lines() {
        let line = line.unwrap();
        let parts: Vec<_> = line.split_whitespace().collect();
        let distance = parts[1].parse::<i64>().unwrap();
        match parts[0] {
            "forward" => h = h + distance,
            "up" => d = d - distance,
            "down" => d = d + distance,
            _ => (),
        }
    }
    return h * d;
}
pub fn day02_02() -> i64 {
    let filename = "../input/02.txt";
    let file = File::open(filename).unwrap();
    let reader = BufReader::new(file);
    let (mut h, mut d, mut aim) = (0, 0, 0);
    for line in reader.lines() {
        let line = line.unwrap();
        let parts: Vec<_> = line.split_whitespace().collect();
        let distance = parts[1].parse::<i64>().unwrap();
        match parts[0] {
            "forward" => {
                h = h + distance;
                d = d + distance * aim;
            }
            "up" => aim = aim - distance,
            "down" => aim = aim + distance,
            _ => (),
        }
    }
    return h * d;
}