Advent of Code 2022 - Day 10 - Kotlin Edition
Tags: adventofcode, kotlin, guide, programming
Published: 2022-12-23 10:16:05

---
title: Advent of Code 2022 - Day 10 - Kotlin Edition
published: true
date: 2022-12-21 16:52:36 UTC
tags: adventofcode,kotlin,guide,programming
canonical_url: https://yonatankarp.com/advent-of-code-2022-day-10-kotlin-edition
---

## Part 1

### Task

> You avoid the ropes, plunge into the river, and swim to shore.
> 
> The Elves yell something about meeting back up with them upriver, but the river is too loud to tell exactly what they're saying. They finish crossing the bridge and disappear from view.
> 
> Situations like this must be why the Elves prioritized getting the communication system on your handheld device working. You pull it out of your pack, but the amount of water slowly draining from a big crack in its screen tells you it probably won't be of much immediate use.
> 
> _Unless_, that is, you can design a replacement for the device's video system! It seems to be some kind of [cathode-ray tube](https://en.wikipedia.org/wiki/Cathode-ray_tube) screen and simple CPU that are both driven by a precise _clock circuit_. The clock circuit ticks at a constant rate; each tick is called a _cycle_.
> 
> Start by figuring out the signal being sent by the CPU. The CPU has a single register, `X`, which starts with the value `1`. It supports only two instructions:
> 
> - `addx V` takes _two cycles_ to complete. _After_ two cycles, the `X` register is increased by the value `V`. (`V` can be negative.)
> 
> - `noop` takes _one cycle_ to complete. It has no other effect.
> 
> The CPU uses these instructions in a program (your puzzle input) to, somehow, tell the screen what to draw.
> 
> Consider the following small program:
> 
> ```
> noop
> addx 3
> addx -5
> 
> ```
> 
> Execution of this program proceeds as follows:
> 
> - At the start of the first cycle, the `noop` instruction begins execution. During the first cycle, `X` is `1`. After the first cycle, the `noop` instruction finishes execution, doing nothing.
> 
> - At the start of the second cycle, the `addx 3` instruction begins execution. During the second cycle, `X` is still `1`.
> 
> - During the third cycle, `X` is still `1`. After the third cycle, the `addx 3` instruction finishes execution, setting `X` to `4`.
> 
> - At the start of the fourth cycle, the `addx -5` instruction begins execution. During the fourth cycle, `X` is still `4`.
> 
> - During the fifth cycle, `X` is still `4`. After the fifth cycle, the `addx -5` instruction finishes execution, setting `X` to `-1`.
> 
> Maybe you can learn something by looking at the value of the `X` register throughout execution. For now, consider the _signal strength_ (the cycle number multiplied by the value of the `X` register) _during_ the 20th cycle and every 40 cycles after that (that is, during the 20th, 60th, 100th, 140th, 180th, and 220th cycles).
> 
> For example, consider this larger program:
> 
> ```
> addx 15
> addx -11
> addx 6
> addx -3
> addx 5
> addx -1
> addx -8
> addx 13
> addx 4
> noop
> addx -1
> addx 5
> addx -1
> addx 5
> addx -1
> addx 5
> addx -1
> addx 5
> addx -1
> addx -35
> addx 1
> addx 24
> addx -19
> addx 1
> addx 16
> addx -11
> noop
> noop
> addx 21
> addx -15
> noop
> noop
> addx -3
> addx 9
> addx 1
> addx -3
> addx 8
> addx 1
> addx 5
> noop
> noop
> noop
> noop
> noop
> addx -36
> noop
> addx 1
> addx 7
> noop
> noop
> noop
> addx 2
> addx 6
> noop
> noop
> noop
> noop
> noop
> addx 1
> noop
> noop
> addx 7
> addx 1
> noop
> addx -13
> addx 13
> addx 7
> noop
> addx 1
> addx -33
> noop
> noop
> noop
> addx 2
> noop
> noop
> noop
> addx 8
> noop
> addx -1
> addx 2
> addx 1
> noop
> addx 17
> addx -9
> addx 1
> addx 1
> addx -3
> addx 11
> noop
> noop
> addx 1
> noop
> addx 1
> noop
> noop
> addx -13
> addx -19
> addx 1
> addx 3
> addx 26
> addx -30
> addx 12
> addx -1
> addx 3
> addx 1
> noop
> noop
> noop
> addx -9
> addx 18
> addx 1
> addx 2
> noop
> noop
> addx 9
> noop
> noop
> noop
> addx -1
> addx 2
> addx -37
> addx 1
> addx 3
> noop
> addx 15
> addx -21
> addx 22
> addx -6
> addx 1
> noop
> addx 2
> addx 1
> noop
> addx -10
> noop
> noop
> addx 20
> addx 1
> addx 2
> addx 2
> addx -6
> addx -11
> noop
> noop
> noop
> 
> ```
> 
> The interesting signal strengths can be determined as follows:
> 
> - During the 20th cycle, register `X` has the value `21`, so the signal strength is 20 \* 21 = _420_. (The 20th cycle occurs in the middle of the second `addx -1`, so the value of register `X` is the starting value, `1`, plus all of the other `addx` values up to that point: 1 + 15 - 11 + 6 - 3 + 5 - 1 - 8 + 13 + 4 = 21.)
> 
> - During the 60th cycle, register `X` has the value `19`, so the signal strength is 60 \* 19 = `1140`.
> 
> - During the 100th cycle, register `X` has the value `18`, so the signal strength is 100 \* 18 = `1800`.
> 
> - During the 140th cycle, register `X` has the value `21`, so the signal strength is 140 \* 21 = `2940`.
> 
> - During the 180th cycle, register `X` has the value `16`, so the signal strength is 180 \* 16 = `2880`.
> 
> - During the 220th cycle, register `X` has the value `18`, so the signal strength is 220 \* 18 = `3960`.
> 
> The sum of these signal strengths is `13140`.
> 
> Find the signal strength during the 20th, 60th, 100th, 140th, 180th, and 220th cycles. _What is the sum of these six signal strengths?_

### Solution

For today's solution, I tried to take the simplest solution. Since I was sick maniple days and needed to catch up on the puzzles.

Our solution would look as follow:

- Initialize 2 variables that will represent our register and cycle state.

- Map each instruction to its signal strength

- sum all strengths

Keep in mind that when calculating the strength we need to know whether to include the new value or not.

Let's start by adding an extension function. This function would return us the cycle signal strength:

```kotlin
private fun Int.getCycleSignal(register: Int) =
    if (this % 40 == 20) this * register
    else 0

```

Now, we will map each instruction in our input into its strength. To do so, we will follow the following instructions:

- Increase the cycle by 1

- get the current signal strength

- if this is a `addx` operation:

In the end, we will just sum all signals and receive our results:

```kotlin
fun solvePart1(): Int {
    var register = 1
    var cycle = 1
    return input
        .filter { it.isNotBlank() }
        .map { instruction ->
            cycle++

            var signal = cycle.getCycleSignal(register)

            if (instruction.startsWith("addx")) {
                // addx operation takes 2 cycles
                cycle++
                val (_, value) = instruction.split(" ")
                register += value.toInt()
                // Update signal if needed for addx operation
                signal += cycle.getCycleSignal(register)
            }

            signal
        }
        .sumOf { it }
}

```

We're done. Let's run our tests:

```kotlin
@Test
fun `Part 1 - Example`() {
    val day10 = Day10(exampleInput)
    assertEquals(13140, day10.solvePart1())
}

@Test
fun `Part 1 - Real Input`() {
    val day10 = Day10(resourceAsList("2022/day10.txt"))
    assertEquals(15260, day10.solvePart1())
}

```

## Part 2

### Task

> It seems like the `X` register controls the horizontal position of a [sprite](https://en.wikipedia.org/wiki/Sprite_(computer_graphics)). Specifically, the sprite is 3 pixels wide, and the `X` register sets the horizontal position of the _middle_ of that sprite. (In this system, there is no such thing as "vertical position": if the sprite's horizontal position puts its pixels where the CRT is currently drawing, then those pixels will be drawn.)
> 
> You count the pixels on the CRT: 40 wide and 6 high. This CRT screen draws the top row of pixels left-to-right, then the row below that, and so on. The left-most pixel in each row is in position `0`, and the right-most pixel in each row is in position `39`.
> 
> Like the CPU, the CRT is tied closely to the clock circuit: the CRT draws _a single pixel during each cycle_. Representing each pixel of the screen as a `#`, here are the cycles during which the first and last pixel in each row are drawn:
> 
> ```
> Cycle 1 -> ######################################## <- Cycle 40
> Cycle 41 -> ######################################## <- Cycle 80
> Cycle 81 -> ######################################## <- Cycle 120
> Cycle 121 -> ######################################## <- Cycle 160
> Cycle 161 -> ######################################## <- Cycle 200
> Cycle 201 -> ######################################## <- Cycle 240
> 
> ```
> 
> So, by [carefully](https://en.wikipedia.org/wiki/Racing_the_Beam) [timing](https://www.youtube.com/watch?v=sJFnWZH5FXc) the CPU instructions and the CRT drawing operations, you should be able to determine whether the sprite is visible the instant each pixel is drawn. If the sprite is positioned such that one of its three pixels is the pixel currently being drawn, the screen produces a _lit_ pixel (`#`); otherwise, the screen leaves the pixel _dark_ (`.`).
> 
> The first few pixels from the larger example above are drawn as follows:
> 
> ```
> Sprite position: ###.....................................
> 
> Start cycle 1: begin executing addx 15
> During cycle 1: CRT draws pixel in position 0
> Current CRT row: #
> 
> During cycle 2: CRT draws pixel in position 1
> Current CRT row: ##
> End of cycle 2: finish executing addx 15 (Register X is now 16)
> Sprite position: ...............###......................
> 
> Start cycle 3: begin executing addx -11
> During cycle 3: CRT draws pixel in position 2
> Current CRT row: ##.
> 
> During cycle 4: CRT draws pixel in position 3
> Current CRT row: ##..
> End of cycle 4: finish executing addx -11 (Register X is now 5)
> Sprite position: ....###.................................
> 
> Start cycle 5: begin executing addx 6
> During cycle 5: CRT draws pixel in position 4
> Current CRT row: ##..#
> 
> During cycle 6: CRT draws pixel in position 5
> Current CRT row: ##..##
> End of cycle 6: finish executing addx 6 (Register X is now 11)
> Sprite position: ..........###...........................
> 
> Start cycle 7: begin executing addx -3
> During cycle 7: CRT draws pixel in position 6
> Current CRT row: ##..##.
> 
> During cycle 8: CRT draws pixel in position 7
> Current CRT row: ##..##..
> End of cycle 8: finish executing addx -3 (Register X is now 8)
> Sprite position: .......###..............................
> 
> Start cycle 9: begin executing addx 5
> During cycle 9: CRT draws pixel in position 8
> Current CRT row: ##..##..#
> 
> During cycle 10: CRT draws pixel in position 9
> Current CRT row: ##..##..##
> End of cycle 10: finish executing addx 5 (Register X is now 13)
> Sprite position: ............###.........................
> 
> Start cycle 11: begin executing addx -1
> During cycle 11: CRT draws pixel in position 10
> Current CRT row: ##..##..##.
> 
> During cycle 12: CRT draws pixel in position 11
> Current CRT row: ##..##..##..
> End of cycle 12: finish executing addx -1 (Register X is now 12)
> Sprite position: ...........###..........................
> 
> Start cycle 13: begin executing addx -8
> During cycle 13: CRT draws pixel in position 12
> Current CRT row: ##..##..##..#
> 
> During cycle 14: CRT draws pixel in position 13
> Current CRT row: ##..##..##..##
> End of cycle 14: finish executing addx -8 (Register X is now 4)
> Sprite position: ...###..................................
> 
> Start cycle 15: begin executing addx 13
> During cycle 15: CRT draws pixel in position 14
> Current CRT row: ##..##..##..##.
> 
> During cycle 16: CRT draws pixel in position 15
> Current CRT row: ##..##..##..##..
> End of cycle 16: finish executing addx 13 (Register X is now 17)
> Sprite position: ................###.....................
> 
> Start cycle 17: begin executing addx 4
> During cycle 17: CRT draws pixel in position 16
> Current CRT row: ##..##..##..##..#
> 
> During cycle 18: CRT draws pixel in position 17
> Current CRT row: ##..##..##..##..##
> End of cycle 18: finish executing addx 4 (Register X is now 21)
> Sprite position: ....................###.................
> 
> Start cycle 19: begin executing noop
> During cycle 19: CRT draws pixel in position 18
> Current CRT row: ##..##..##..##..##.
> End of cycle 19: finish executing noop
> 
> Start cycle 20: begin executing addx -1
> During cycle 20: CRT draws pixel in position 19
> Current CRT row: ##..##..##..##..##..
> 
> During cycle 21: CRT draws pixel in position 20
> Current CRT row: ##..##..##..##..##..#
> End of cycle 21: finish executing addx -1 (Register X is now 20)
> Sprite position: ...................###..................
> 
> ```
> 
> Allowing the program to run to completion causes the CRT to produce the following image:
> 
> ```
> ##..##..##..##..##..##..##..##..##..##..
> ###...###...###...###...###...###...###.
> ####....####....####....####....####....
> #####.....#####.....#####.....#####.....
> ######......######......######......####
> #######.......#######.......#######.....
> 
> ```
> 
> Render the image given by your program. _What eight capital letters appear on your CRT?_

### Solution

To be honest, I had to read the instructions roughly 10 times until I manage to understand the task. So to clarify that we're all understanding it I will simplify it:

- Print the rows column by column

- For each column:

I would start by introducing a new function that would return the character to print on the CRT screen. Note that this function also breaks the line after 40 characters.

```kotlin
private fun getCRTCharacter(index: Int, register: Int): String {
    val adjustedIndex = index % 40
    return when (adjustedIndex) {
        in register - 1..register + 1 -> "#"
        else -> "."
    }.let {
        // If that's the 1st character of the new line break line
        if (adjustedIndex == 0) System.lineSeparator() + it
        else it
    }
}

```

Now, all we need to do is:

- iterate over the instructions.

- For each instruction, append the relevant character(s)

We will use a `StringBuilder` object to improve our performance a bit:

```kotlin
fun solvePart2(): String {
    val crt = StringBuilder()
    var register = 1
    var cycle = 1
    input.filter { it.isNotBlank() }
        .forEach { instruction ->
            crt.append(getCRTCharacter(cycle - 1, register))
            cycle++

            if (instruction.startsWith("addx")) {
                crt.append(getCRTCharacter(cycle - 1, register))
                cycle++
                register += instruction.substringAfter("addx").toInt()
            }
        }

    return crt
        .toString()
        // Remove the 1st break line
        .removePrefix(System.lineSeparator())
}

```

Note that we need to remove our 1st breaking line just for the tests as otherwise, the response will not match our expected results.

Ok, we're almost done, let's run our tests:

```kotlin
@Test
fun `Part 2 - Example`() {
    val exampleOutput = """
        ##..##..##..##..##..##..##..##..##..##..
        ###...###...###...###...###...###...###.
        ####....####....####....####....####....
        #####.....#####.....#####.....#####.....
        ######......######......######......####
        #######.......#######.......#######.....
    """.trimIndent()
    val day10 = Day10(exampleInput)
    assertEquals(exampleOutput, day10.solvePart2())
}

@Test
fun `Part 2 - Real Input`() {
    val realOutput = """
        ###...##..#..#.####..##..#....#..#..##..
        #..#.#..#.#..#.#....#..#.#....#..#.#..#.
        #..#.#....####.###..#....#....#..#.#....
        ###..#.##.#..#.#....#.##.#....#..#.#.##.
        #....#..#.#..#.#....#..#.#....#..#.#..#.
        #.....###.#..#.#.....###.####..##...###.
    """.trimIndent()
    val day10 = Day10(resourceAsList("2022/day10.txt"))
    assertEquals(realOutput, day10.solvePart2())
}

```

All of the code that was presented in the article, along with the utility classes that are used are available in [**my GitHub account.**](https://github.com/yonatankarp/advent-of-code)

See you on the next challenge!

## Links

- The code of this post is available [here](https://github.com/yonatankarp/advent-of-code/commit/b70ad017c77cc9907d849de604aa57fdabdf1401).