I decided to do Advent of Code 2019 Day 4! I’m gonna solve the puzzles in Scala! I’m starting late, because I found out about it late. So we’re going to start at Day 4, and catch up in another post, or posts.
I have also decided to implement the solutions in Scala. My Scala skills have gotten rusty, so this is a good time to exercise them again. I have forgotten much of my Scala, since I don’t use it. Reading another post, in Kotlin, showed me just how much I’ve forgotten of the standard library functions. My first solution follows. I may add another solution using the Scala Standard Library functions to do even less actual code.
The full code is on my gitlab.
Part 1
To start with, I have a simple executable that runs the valid password count method, and prints it out to the command line. I just hard-coded the range, rather than reading in the input from a file.
object Puzzle4Main extends App { val p4 = new Puzzle4 val range = 134792 to 675810 println("Valid passwords Part 1: " + p4.validPasswordCount1(range)) println("Valid passwords Part 2: " + p4.validPasswordCount2(range)) }
I didn’t start with both parts, but that’s the final product. Next I took the criteria from the puzzle and built a scalatest FunSpec for part one.
class Puzzle4Spec extends AnyFunSpec { val p4 = new Puzzle4 describe("Tests for puzzle 4: part 1") { it("111111 meets the password criteria") { assert(p4.passwordValidPart1("111111")) } it("223450 does not meet the criteria") { assert(!p4.passwordValidPart1("223450")) } it("123789 does not meet criteria") { assert(!p4.passwordValidPart1("123789")) } it("123455 meets criteria") { assert(p4.passwordValidPart1("123455")) } } }
I added another criteria when I wasn’t sure if my indexing logic was actually doing the right thing. These tests all passed my implementation, eventually.
def passwordValidPart1(input: String): Boolean = { if (input.length != 6) { false } else { val numbers = input.toCharArray.map(_.asDigit).toList atLeastOneDouble(numbers) && numbersNeverDecrease(numbers) } } def atLeastOneDouble(numbers: List[Int]): Boolean = { (0 until (numbers.length - 1)).exists(index => numbers(index) == numbers(index + 1)) } def numbersNeverDecrease(numbers: List[Int]): Boolean = { (0 until (numbers.length - 1)).forall(index => numbers(index) passwordValidPart2(number.toString)) } def passwordValidPart2(input: String): Boolean = { val numbers = input.toCharArray.map(_.asDigit).toList val grouped = numberGroups(numbers) numbersNeverDecrease(numbers) && numberGroupsOfOnlyTwo(grouped) } def numbersNeverDecrease(numbers: List[Int]): Boolean = { (0 until (numbers.length - 1)).forall(index => numbers(index)