Day 1: Report Repair

Puzzle Description

Advent of Code 2020, Day 1

Solution Summary

  1. Parse input into List[Int]
  2. Get n entries that sum to 2020, and get their product
    • In part 1 n is 2
    • In part 2 n is 3

Part 1

Let's parse first.

def parse(str: String): List[Int] =
  str.linesIterator.map(_.toInt).toList

Haxe has issues with newlines, so we'll need to pull in StringTools to trim it.

using StringTools;

class Day01 {
    static public function parse(str: String): Array<Int> {
        return str.trim().split("\n").map((a) -> Std.parseInt(a.trim()));
    }
}

Then, let's iterate both. I never ran into this with my input, but just for safety let's check to make sure our indexes don't overlap:

Scala's combinations function is a perfect fit here, and does exactly what we need. flatMap on an Iterator into an Option and then next is like doing find, but we can map the value immediately.

def part1(input: List[Int]): Int =
  input.combinations(2).flatMap { case List(x, y) =>
    Option.when(x + y == 2020)(x * y)
  }.next()
// inside Day01...
static public function part1(ls: Array<Int>): Int {
  for (xi => x in ls) {
      for (yi => y in ls) {
          if (xi != yi && x + y == 2020) {
              return x * y;
          }
      } 
   }
   return -1;
}

Part 2

Part 2 is just iterating over a 3rd time, which is easy.

For Scala only minor changes are needed:

def part2(input: List[Int]): Int =
  input.combinations(3).flatMap { case List(x, y, z) =>
    Option.when(x + y + z == 2020)(x * y * z)
  }.next()
static public function part2(ls: Array<Int>): Int {
    for (xi => x in ls) {
        for (yi => y in ls) {
            if (xi != yi) {
                for (zi => z in ls) {
                    if (xi != zi && yi != zi && x + y + z == 2020) {
                        return x * y * z;
                    }
                }
            }
        }
    }
    return -1;
}

And that's part 2 done.

Final Code

def parse(str: String): List[Int] =
  str.linesIterator.map(_.toInt).toList

def part1(input: List[Int]): Int =
  input.combinations(2).flatMap { case List(x, y) =>
    Option.when(x + y == 2020)(x * y)
  }.next()

def part2(input: List[Int]): Int =
  input.combinations(3).flatMap { case List(x, y, z) =>
    Option.when(x + y + z == 2020)(x * y * z)
  }.next()
using StringTools;

class Day01 {
    static public function parse(str: String): Array<Int> {
		return str.trim().split("\n").map((a) -> Std.parseInt(a.trim()));
	}
	
    static public function part1(ls: Array<Int>): Int {
        for (xi => x in ls) {
           for (yi => y in ls) {
               if (xi != yi && x + y == 2020) {
                   return x * y;
               }
           } 
        }
        return -1;
    }
    static public function part2(ls: Array<Int>): Int {
       for (xi => x in ls) {
           for (yi => y in ls) {
               if (xi != yi) {
                   for (zi => z in ls) {
                       if (xi != zi && yi != zi && x + y + z == 2020) {
                           return x * y * z;
                       }
                   }
               }
           }
       }
       return -1;
    } 
}

Benchmark

Part 1

Mean

Error

JVM

6.330 ms

+/- 0.418 ms

JS

19.054 ms

+/- 0.157 ms

Native

13.354 ms

+/- 0.138 ms

Part 2

Mean

Error

JVM

114.071 ms

+/- 12.256 ms

JS

205.994 ms

+/- 7.980 ms

Native

249.938 ms

+/- 0.054 ms

Run it in the browser!