Home » Advent of Code 2019 Day 4 in Scala
Programming

Advent of Code 2019 Day 4 in Scala

adventofcode2019-3559164

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)

Related posts

Advent of Code Day 1 and 2 in Scala

dkowis

Advent of Code 2019 Day 3 in Scala

dkowis

Mocking OpenID Connect in Micronaut Integration Tests

dkowis
The Rambling Homelabist