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

10.854 ms

+/- 0.118 ms

JS

9.789 ms

+/- 0.047 ms

Native

15.038 ms

+/- 0.077 ms

Part 2

Mean

Error

JVM

133.685 ms

+/- 0.453 ms

JS

173.258 ms

+/- 1.549 ms

Native

294.786 ms

+/- 4.225 ms

Run it in the browser!