Advent of Code 2020 in Kotlin: Day 02
Tags: kotlin, adventofcode
Published: 2020-12-02 22:02:39

---
title: Advent of Code 2020 in Kotlin: Day 02
published: true
date: 2020-12-02 18:19:49 UTC
tags: Kotlin, adventofcode
canonical_url: https://heylucas.net/2020/12/02/advent-of-code-2020-in-kotlin-day-02/
---

A new day, a new challenge. Day 02 of the [Advent of Code](https://adventofcode.com/) gave us a “practical” problem: There’s a database of passwords and it has inconsistent data. We need to find the passwords that match the correct format and count them.

The input is provided in a file, where each line is formatted as `<number>-<number> <letter>: <password>`.

How the input should be interpreted is different in parts 1 and 2.

## Part 1

In this first part, the `<number>` items in the line indicate the minimum and the maximum (respectively) number of times `<letter>` should appear in the `<password>` for it to be valid.

Here’s how I solved it:

```kotlin
import java.io.File

data class PasswordEntry(
  val min: Int,
  val max: Int,
  val letter: Char,
  val password: String) {
  companion object {
    val entryRegex = Regex("""(\d+)-(\d+) +([a-z]): ([a-z]+)""")
	
    fun of(string: String) : PasswordEntry? {
      val matchResult = entryRegex.matchEntire(string)

      if (matchResult != null) {
        val (min, max, letter, password) = matchResult.destructured
        return PasswordEntry(min.toInt(), max.toInt(), letter[0], password)
      }
      return null
    }
  }

  fun isValid(): Boolean {
    val count = password.count({ it == letter })
    return (min <= count && count <= max)
  }
}

fun main() {
  var numberOfValidPasswords: Int = 0

  File("input.txt").forEachLine {
    val entry = PasswordEntry.of(it)

    if (entry != null && entry.isValid()) {
      numberOfValidPasswords++
    }
  }

  println(numberOfValidPasswords)
}

```

### How it works

The solution is quite simple: We go over each line, use a `Regex` to extract the components we are interested in, and then create an object representing the entry.

The way I solved it is a bit over-engineered for such a simple problem, but it let me play with a few Kotlin concepts: Regexes and companion objects.

Kotlin doesn’t support static methods like Java, which you would normally use to define a [Factory method](https://en.wikipedia.org/wiki/Factory_method_pattern). Instead, it offers companion objects: Inside your class, you can define another that provides methods to construct the object you want.

So after we covert each line into a `PasswordEntry `object, we call `isValid()` to determine if the password is valid. If it is, we bump the count of valid passwords.

## Part 2

The solution is almost identical, but the condition to determine if a password is valid changes. The `<number>` entries indicate that `<letter>` should be present in one of those indexes, but not both at the same time.

Here’s the code:

```kotlin
data class PasswordEntry(
  val firstOffset: Int,
  val secondOffset: Int,
  val letter: Char,
  val password: String) {
  companion object {
    val entryRegex = Regex("""(\d+)-(\d+) +([a-z]): ([a-z]+)""")
 
    fun of(string: String) : PasswordEntry? {
      // ... 
       return PasswordEntry(firstIndex.toInt() - 1, secondIndex.toInt() - 1, letter[0], password)
      // ...
      }
    }

    fun isValid(): Boolean = 
      (password[firstOffset] == letter).xor(password[secondOffset] == letter)
}
```

### How it works

Not much changed here. Since the `<number>` entries represent the index, we subtract 1 from them. This way we get the correct offset in the string.

Then in the `isValid()` method, we use `Boolean.xor` to check that only of those offsets has the letter.

## Done for the day

This was a nice little program to work on. I was exposed to Kotlin’s regex facilities and companion objects. Not sure how I feel about latter yet. I need to play with them for a while longer to see what’s the advantage over static methods.

Next up, Day 03.