
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)