RJPlog
: RJPlog
RJPlog |
As in the past years I will get more into kotlin. Here in gitpod solutions will run with kotlin script.
For execution enter kotlin day2100.kts in the command line.
Read the input file is done via a function call:
fun read(): String {
var result: String = ""
File("day2100_puzzle_input.txt").forEachLine {
result = it
}
return result
}
Output is printed in main:app-name:
//main (args: Arrary<String>) {
var solution_1 = read()
println(" I like $solution_1")
//}
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/1
For execution enter kotlin day2101_1_2.kts in the command line.
How does it work:
Inside function sonar_sweep the puzzle input will be read into a list. Afterwards within a loop each value is compared to it’s previous value. If the current value is higher than the previous, the variable result is increased. After finishing the loop, result is returned.
fun sonar_sweep(): Int {
var result: Int = 0
var samples = mutableListOf<Int>()
File("day2101_puzzle_input.txt").forEachLine {
samples.add(it.toInt())
}
for (i in 1..samples.size-1) {
if (samples[i] > samples[i-1]){
result++
}
}
return result
}
How does it work:
Inside function sonar_sweep_noise the puzzle input will be read into a list as in solution for part 1. Afterwards within a loop a variable prev_sum and curr_sum is calculated out of the last and current 3 samples. Both are compared, if the current value is higher than the previous, the variable result is increased. After finishing the loop, result is returned.
fun sonar_sweep_noise(): Int {
var result: Int = 0
var samples = mutableListOf<Int>()
File("day2101_puzzle_input.txt").forEachLine {
samples.add(it.toInt())
}
for (i in 1..samples.size-1-2) {
var prev_sum: Int = samples[i-1]+samples[i]+ samples[i+1]
var cur_sum: Int = samples[i]+samples[i+1]+ samples[i+2]
if (cur_sum > prev_sum){
result++
}
}
return result
}
At the end, both solutions are printed out.
// print solution for part 1
println("**************************")
println("--- Day 1: Sonar Sweep ---")
println("**************************")
println("Solution for part1")
println(" $solution1 are larger than the previous measurement ")
println()
// print solution for part 2
println("**************************")
println("Solution for part2")
println(" $solution2 sums are larger than the previous measurement")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/2
For execution enter kotlin day2102_1_2.kts in the command line.
How does it work:
Inside function dive the puzzle input will be read line by line and split into the instruction part instruction[0] and the value instruction[1]. The varibles depth and horizontal are increased or decreased within a if/else instruction according to their instructions. After going through the complete input file depth multiplied by horizontal is returned
fun dive_1(): Int {
var depth: Int = 0
var horizontal: Int = 0
File("day2102_puzzle_input.txt").forEachLine {
var instruction = it.split(' ')
if (instruction[0].equals("forward")) {
horizontal = horizontal + instruction[1].toInt()
} else if (instruction[0].equals("down")) {
depth = depth + instruction[1].toInt()
} else if (instruction[0].equals("up")) {
depth = depth - instruction[1].toInt()
}
}
return depth*horizontal
}
How does it work:
Inside function dive_2 the puzzle input will be read line by line and split into the instruction part instruction[0] and the value instruction[1]. The varibles depth, horizontal and aim are increased or decreased within a if/else instruction according to their instructions. After going through the complete input file depth multiplied by horizontal is returned
fun dive_2(): Int {
var depth: Int = 0
var horizontal: Int = 0
var aim: Int = 0
File("day2102_puzzle_input.txt").forEachLine {
var instruction = it.split(' ')
if (instruction[0].equals("forward")) {
horizontal = horizontal + instruction[1].toInt()
depth = depth + aim * instruction[1].toInt()
} else if (instruction[0].equals("down")) {
aim = aim + instruction[1].toInt()
} else if (instruction[0].equals("up")) {
aim = aim - instruction[1].toInt()
}
}
return depth*horizontal
}
At the end, both solutions are printed out.
// print solution for part 1
println("*******************")
println("--- Day 2: Dive ---")
println("*******************")
println("Solution for part1")
println(" $solution1 is your final horizontal position multiplied by final depth ")
println()
// print solution for part 2
println("**************************")
println("Solution for part2")
println(" $solution2 is your final horizontal position multiplied by final depth")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/3
For execution enter kotlin day2103_1_2.kts in the command line.
How does it work:
Inside function diagnostic_power the puzzle input will be read line by line and within a loop over all elements of the string a counter for each position will be increased, if the string contains a ´1´ at this position. Afterwards there are strings for gamma and epsilon set up and converted to dezimal integers. The result of the multiplication of gamma and epsilon is returned as solution for part one:
fun diagnostic_power(): Int {
var count = mutableListOf(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
var reports: Int = 0
// search for most common bit
File("day2103_puzzle_input.txt").forEachLine {
reports += 1
for (i in 0..it.length - 1) {
if (it[i].equals('1')) {
count[i] = count[i] + 1
}
}
}
// calculate gamma and epsilon rate out of most common bit list
var gamma: String = ""
var epsilon: String = ""
count.forEach {
if (it > reports - it) {
gamma = gamma + "1"
epsilon = epsilon + "0"
} else {
gamma = gamma + "0"
epsilon = epsilon + "1"
}
}
// return power consumption
return gamma.toInt(2) * epsilon.toInt(2)
}
How does it work:
Inside function diagnostic_life the puzzle input will be read into a list for O2 and one for CO2. Then we start splitting the O2 list postition by position only keeping the part with the most common bit until there is only one entry left. Same is done for the CO2 list, only difference is, that only the list with the least common bit is kept. Both remaining entries are converted to dezimal integer and the result of the multiplication is returned as solution for part two:
fun diagnostic_life(): Int {
val list = mutableListOf<String>()
val list_co2 = mutableListOf<String>()
var pos: Int = 0
// setup lists for O2 and CO2 ratings
File("day2103_puzzle_input.txt").forEachLine {
list.add(it)
list_co2.add(it)
}
// determine O2 generator rating
while (list.size > 1) {
var (first, second) = list.partition { it[pos].equals('1') }
if (first.size >= second.size) {
list.clear()
first.forEach {
list.add(it)
}
} else {
list.clear()
second.forEach {
list.add(it)
}
}
pos += 1
}
// determine CO2 scrubber rating
pos = 0
while (list_co2.size > 1) {
var (first, second) = list_co2.partition { it[pos].equals('1') }
if (first.size >= second.size) {
list_co2.clear()
second.forEach {
list_co2.add(it)
}
} else {
list_co2.clear()
first.forEach {
list_co2.add(it)
}
}
pos += 1
}
// return life supporting rate
return list[0].toInt(2) * list_co2[0].toInt(2)
}
At the end, both solutions are printed out.
// print solution for part 1
println("********************************")
println("--- Day 3: Binary Diagnostic ---")
println("********************************")
println("Solution for part1")
println(" $solution1 is your power consumption ")
println()
// print solution for part 2
println("*********************************")
println("Solution for part2")
println(" $solution2 is your life supporting rate")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/4
For execution enter kotlin day2104_1_2.kts in the command line.
I never worked with classes, but today’s puzzle seemed to be a good start for learning something about it. At the beginning I had some difficulties to transfer the boards to the class, whenever I read in the next board also the last classes' boards where cleaned. I solved it by introducing a second list which I made unmutable, I guess there are better solutions but for the start it worked out to solve the today’s puzzle.
How does it work:
I created a class representing a bingo card with individual numbers and a method next_number. Evoking this method will mark all numbers matching the given number, evaluate, if already a row or column is complete and calculate the final score:
class bingo(field: List<Int>) {
// this class should represent a single bingo board. The board is initialized with it's individual numbers
var field = field
var fieldProgress = field.toMutableList()
var win: Boolean = false
var finalScore: Int = 0
// this method is used to print the board
fun print_board() {
println("-- Board --")
for (j in 0..4) {
for (i in 0..4) {
print("${fieldProgress[i + j * 5]} ")
}
println()
}
println()
}
// this method is used every time a new number is given, to check if bingo is complete and to calculate the final score
fun nextNumber(Number: Int) {
var currentNumber: Int = Number
var sumOfUnmarkedNumbers: Int = 0
// mark positions which have already fitted
for (i in 0..fieldProgress.size - 1) {
if (fieldProgress[i] == currentNumber) {
fieldProgress[i] = -1
}
}
// check if one row is complete - set win - claculate final score
if (fieldProgress[0] + fieldProgress[1] + fieldProgress[2] + fieldProgress[3] + fieldProgress[4] == -5 ||
fieldProgress[5] + fieldProgress[6] + fieldProgress[7] + fieldProgress[8] + fieldProgress[9] == -5 ||
fieldProgress[10] + fieldProgress[11] + fieldProgress[12] + fieldProgress[13] + fieldProgress[14] == -5 ||
fieldProgress[15] + fieldProgress[16] + fieldProgress[17] + fieldProgress[18] + fieldProgress[19] == -5 ||
fieldProgress[20] + fieldProgress[21] + fieldProgress[22] + fieldProgress[23] + fieldProgress[24] == -5 ||
fieldProgress[0] + fieldProgress[5] + fieldProgress[10] + fieldProgress[15] + fieldProgress[20] == -5 ||
fieldProgress[1] + fieldProgress[6] + fieldProgress[11] + fieldProgress[16] + fieldProgress[21] == -5 ||
fieldProgress[2] + fieldProgress[7] + fieldProgress[12] + fieldProgress[17] + fieldProgress[22] == -5 ||
fieldProgress[3] + fieldProgress[8] + fieldProgress[13] + fieldProgress[18] + fieldProgress[23] == -5 ||
fieldProgress[4] + fieldProgress[9] + fieldProgress[14] + fieldProgress[19] + fieldProgress[24] == -5
) {
win = true
fieldProgress.forEach {
if (it != -1) {
sumOfUnmarkedNumbers = sumOfUnmarkedNumbers + it
}
}
finalScore = currentNumber * sumOfUnmarkedNumbers
}
}
}
To start, the puzzle input will be read. All numbers are added to a list, for all boards a new bingo class is added to second list.
// setup for reading puzzle input
var numbers = mutableListOf<Int>()
var card = mutableListOf<Int>()
var cardboard = listOf<Int>()
var fields = mutableListOf<bingo>()
File("day2104_puzzle_input.txt").forEachLine {
if (it.length > 15) {
var instruction = it.split(",")
instruction.forEach { numbers.add(it.toInt()) }
} else if (it.length > 2) {
var line: String = ""
if (it[0].equals(' ')) {
line = it.drop(1)
} else {
line = it
}
var instruction = line.replace(" ", " ").replace(" ", " ").split(" ")
for (i in instruction) {
card.add(i.toInt())
}
} else if (it.length < 2 && card.size > 10) {
cardboard = card.toList()
fields.add(bingo(cardboard))
card.clear()
}
}
After the preparation, two nested loop’s run over each number and each board until the first board wins, and the final score is printed out.
// start game
// loop through numbers until gameend, then printout final score
var currentNumber: Int
var outOfGame = mutableListOf<Int>()
var winningScores = mutableListOf<Int>()
loop@ for (i in 0..numbers.size - 1) {
currentNumber = numbers[i]
var xx: Int = 0
for (j in fields) {//fields.forEach {
if (!outOfGame.contains(xx)) {
j.nextNumber(currentNumber)
if (j.win) {
outOfGame.add(xx)
winningScores.add(j.finalScore)
if (outOfGame.size == fields.size) {
break@loop
}
}
}
xx += 1
}
}
How does it work:
Instead stopping after the first win, all wins are added to a list, a board which has already a complete row or column is exluded for the ongoning game. The last element of the win list is the solution for number two.
At the end, both solutions are printed out.
// print solution for part 1
println("**************************")
println("--- Day 4: Giant Squid ---")
println("**************************")
println("Solution for part1")
println(" ${winningScores[0]} will your final score be if you choose that board")
println()
// print solution for part 2
println("*********************************")
println("Solution for part2")
println(" ${winningScores[winningScores.size-1]} would be the final score")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/5
For execution enter kotlin day2105_1_2.kts in the command line.
How does it work:
I created a class function reading file input and separating coordinates. Then for each horizontal and vertical lines a map entry is created with value 1 or if already existing, increased by one. The function returns the number of all map entries higher than one. The function has one parameter which is by default 0, that means the evaluation of diagonal lines will be skipped.
fun lines(solution: Int = 0): Int {
var ground = mutableMapOf<Pair<Int, Int>, Int>()
var result: Int = 0
File("day2105_puzzle_input.txt").forEachLine {
var instruction = it.split(" -> ")
var pos1 = instruction[0].split(",")
var pos2 = instruction[1].split(",")
var x1: Int = pos1[0].toInt()
var y1: Int = pos1[1].toInt()
var x2: Int = pos2[0].toInt()
var y2: Int = pos2[1].toInt()
if (x1 == x2) {
for (i in minOf(y1, y2)..maxOf(y1, y2)) {
if (ground.contains(Pair(x1, i))) {
ground.put(Pair(x1, i), ground.getValue(Pair(x1, i)) + 1)
} else {
ground.put(Pair(x1, i), 1)
}
}
} else if (y1 == y2) {
for (i in minOf(x1, x2)..maxOf(x1, x2)) {
if (ground.contains(Pair(i, y1))) {
ground.put(Pair(i, y1), ground.getValue(Pair(i, y1)) + 1)
} else {
ground.put(Pair(i, y1), 1)
}
}
} else {
// tag::lines2[]
if (solution > 0) {
for (j in 0..(maxOf(x1, x2)-minOf(x1, x2))) {
if (x2 > x1 && y2 > y1 ) {
if (ground.contains(Pair(j + minOf(x1, x2), j + minOf(y1, y2)))) {
ground.put(
Pair(j + minOf(x1, x2) , j + minOf(y1, y2)),
ground.getValue(Pair(j + minOf(x1, x2), j + minOf(y1, y2))) + 1
)
} else {
ground.put(Pair(j + minOf(x1, x2), j + minOf(y1, y2)), 1)
}
} else if (x2 < x1 && y2 > y1) {
if (ground.contains(Pair( maxOf(x1, x2) - j, minOf(y1,y2)+j))) {
ground.put(
Pair(maxOf(x1, x2) - j, minOf(y1, y2)+j),
ground.getValue(Pair(maxOf(x1, x2) - j, minOf(y1, y2) + j)) + 1
)
} else {
ground.put(Pair(maxOf(x1, x2) - j, minOf(y1, y2) +j), 1)
}
} else if (x2 > x1 && y2 < y1) {
if (ground.contains(Pair(j + minOf(x1, x2), maxOf(y1, y2) - j))) {
ground.put(
Pair(j + minOf(x1, x2) , maxOf(y1, y2) - j),
ground.getValue(Pair(j + minOf(x1, x2), maxOf(y1, y2)-j)) + 1
)
} else {
ground.put(Pair(j + minOf(x1, x2), maxOf(y1, y2)-j), 1)
}
} else if (x2 < x1 && y2 < y1) {
if (ground.contains(Pair(maxOf(x1, x2) - j, maxOf(y1, y2) - j))) {
ground.put(
Pair(maxOf(x1, x2) - j , maxOf(y1, y2) - j),
ground.getValue(Pair(maxOf(x1, x2) - j, maxOf(y1, y2)-j)) + 1
)
} else {
ground.put(Pair(maxOf(x1, x2) - j, maxOf(y1, y2)-j), 1)
}
}
}
}
}
}
for ((key, value) in ground) {
if (value > 1) {
result += 1
}
}
return result
}
How does it work:
By invokeing the function with a parameter higher than 0 the diagonal lines will also be taken into account.
At the end, both solutions are printed out.
// print solution for part 1
println("***********************************")
println("--- Day 5: Hydrothermal Venture ---")
println("***********************************")
println("Solution for part1")
println(" At $solution1 points at least two lines overlap ")
println()
// print solution for part 2
println("*********************************")
println("Solution for part2")
println(" At $solution2 points at least two lines overlap")
println()
// end::output[]
//}
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/6
For execution enter kotlin day2106_1_2.kts in the command line.
How does it work:
Within the function laternfish() the puzzle input is read into a list, each fish has one entry. Day by day the entry is either reduced by one or reset to 6 and a new entry added wiht value 8.
fun laternfish(day: Int): Int {
var population = mutableListOf<Int>()
File("day2106_puzzle_input.txt").forEachLine {
var instruction = it.split(",")
instruction.forEach {
population.add(it.toInt())
}
}
for (i in 1..day) {
for (x in 0..population.size - 1) {
if (population[x] == 0) {
population.add(8)
population[x] = 6
} else {
population[x] -= 1
}
}
}
return population.size
}
How does it work:
Just to increase days did not work, so I had to find a different solution. Finaly I went with a map, see fun laternfish2(). The keys are the reproducing days 0-8, the values the number of fishes. Every day this map is updated. At the end the sum over all values is calculated.
fun laternfish2(day: Long): Long {
var result: Long = 0
var population = mutableMapOf<Int, Long>()
var new_population = mutableMapOf<Int, Long>()
for (i in 0..8) {
population.put(i, 0)
new_population.put(i, 0)
}
File("day2106_puzzle_input.txt").forEachLine {
var instruction = it.split(",")
instruction.forEach {
population.put(it.toInt(), population.getValue(it.toInt()) + 1)
}
}
for (i in 1..day) {
new_population.put(0, population.getValue(1))
new_population.put(1, population.getValue(2))
new_population.put(2, population.getValue(3))
new_population.put(3, population.getValue(4))
new_population.put(4, population.getValue(5))
new_population.put(5, population.getValue(6))
new_population.put(6, population.getValue(7) + population.getValue(0))
new_population.put(7, population.getValue(8))
new_population.put(8, population.getValue(0))
for (j in 0..8) {
population.put(j, new_population.getValue(j))
}
}
for ((key, value) in population) {
result = result + value
}
return result
}
At the end, both solutions are printed out.
// print solution for part 1
println("**************************")
println("--- Day 6: Lanternfish ---")
println("**************************")
println("Solution for part1")
println(" $solution1 laternfish would be there after 80 days")
println()
// print solution for part 2
println("*********************************")
println("Solution for part2")
println(" $solution2 laternfish would be there after 80 days")
println()
// end::output[]
//}
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/7
For execution enter kotlin day2107_1_2.kts in the command line.
How does it work:
After reading the puzzle input and placing it in a list, I went through all possible positions and calculated the fuel amount. For each position the fuel amount is compared and the minimum kept as solution
How does it work:
Same procedure as in part 1, only some adder for the calculation of the consumed fuel.
At the end, both solutions are printed out.
// print solution for part 1
println("**************************************")
println("--- Day 7: The Treachery of Whales ---")
println("**************************************")
println("Solution for part1")
println(" $minPos fuel must they spend to align to that position?")
println()
// print solution for part 2
println("*********************************")
println("Solution for part2")
println(" $minPos2 fuel must they spend to align to that position?")
println()
// end::output[]
//}
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/8
For execution enter kotlin day2108_1_2.kts in the command line.
How does it work:
Frist part is just spliting in put lines and searching for values 2, 4, 3, 7 and counting.
// part 1
var solution1: Int = 0
File("day2108_puzzle_input.txt").forEachLine {
var instruction = it.split(" | ")
var output = instruction[1].split(" ")
output.forEach {
if (it.length == 2 || it.length == 4 || it.length == 3 || it.length == 7) {
solution1 += 1
}
}
}
How does it work:
Here I had several difficulties to sort samples out. I don’t think that this is a good example for learning, anyway it provides a correct result.
// part 2
var solution2: Int = 0
var mapTable = mutableListOf<String>()
for (i in 0..9) {
mapTable.add("")
}
File("day2108_puzzle_input.txt").forEachLine {
var instruction = it.split(" | ")
var inp = instruction[0].split(" ")
// sort all input values alphabetically
var input = mutableListOf<String>()
inp.forEach {
input.add(it.toCharArray().sorted().joinToString(""))
}
// assigning 1, 4, 7, 8
input.forEach {
if (it.length == 2) {
mapTable[1] = it
} else if (it.length == 4) {
mapTable[4] = it
} else if (it.length == 3) {
mapTable[7] = it
} else if (it.length == 7) {
mapTable[8] = it
}
}
// assigning 5
input.forEach {
var help: String = ""
mapTable[4].forEach {
if (!mapTable[1].contains(it)) {
help = help + it
}
}
if (it.length == 5) {
if (it.toList().containsAll(mapTable[1].toList())) { // if it contains 1 --> 3
mapTable.set(3, it)
} else if (it.toList().containsAll(help.toList())) { // if it contains 4 -->5
mapTable.set(5, it)
} else { // else --> 2
mapTable.set(2, it)
}
}
}
// assigning 6
input.forEach {
if (it.length == 6) {
if (it.toList().containsAll(mapTable[3].toList())) { // if it contains 3 --> 9
mapTable.set(9, it)
} else if (it.toList().containsAll(mapTable[5].toList())) { // if it contains 5 --> 9
mapTable.set(6, it) // if it containns 4 --> 9
} else {
mapTable.set(0, it)
}
}
}
var out = instruction[1].split(" ")
// sort all input values alphabetically
var output = mutableListOf<String>()
out.forEach {
output.add(it.toCharArray().sorted().joinToString(""))
}
solution2 =
solution2 + mapTable.indexOf(output[0]) * 1000 + mapTable.indexOf(output[1]) * 100 + mapTable.indexOf(output[2]) * 10 + mapTable.indexOf(output[3])
}
At the end, both solutions are printed out.
// print solution for part 1
println("***********************************")
println("--- Day 8: Seven Segment Search ---")
println("***********************************")
println("Solution for part1")
println(" $solution1 times do digits 1, 4, 7, or 8 appear")
println()
// print solution for part 2
println("*********************************")
println("Solution for part2")
println(" You get $solution2 if you add up all of the output values")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/9
For execution enter kotlin day2109_1_2.kts in the command line.
How does it work:
For the first part I read in the puzzle input and added a frame outside, one line with '9' on each side. For evalation of risk level, I went through the map and checked, if the adjacent tiles are higher or lower. If all are lower, you found a sink and added it to the result (+1)
var solution1: Int = 0
var solution2: Int
var solution2_results = mutableListOf<Int>()
var heightmap = mutableListOf<Int>()
var width: Int = 0
var height: Int = 0
// read puzzle input to evaluate width and height of grid
File("day2109_puzzle_input.txt").forEachLine {
width = it.length
height += 1
}
// add a frame to grid, makes following evaluations easier, you don't have to check if value is out of grid at borders
width = width + 2
height = height + 2
for (i in 0..width - 1) {
heightmap.add(9)
}
// read puzzle input into list
File("day2109_puzzle_input.txt").forEachLine {
heightmap.add(9)
it.forEach {
heightmap.add(it.toString().toInt())
}
heightmap.add(9)
}
for (i in 0..width - 1) {
heightmap.add(9)
}
// check for sinks and add up risk level, for each sink start fun smokeBasin to get size of basin
for (y in 1..height - 2) {
for (x in 1..width - 2) {
if (heightmap[x + y * width] < heightmap[(x - 1) + (y) * width] && heightmap[x + y * width] < heightmap[(x + 1) + (y) * width] && heightmap[x + y * width] < heightmap[(x) + (y + 1) * width] && heightmap[x + y * width] < heightmap[(x) + (y - 1) * width]) {
solution1 = solution1 + heightmap[x + y * width] + 1
solution2_results.add(smokeBasin(x, y, heightmap, width, height))
}
}
}
// sort list to find highest 3
solution2_results.sort()
solution2 = solution2_results[solution2_results.size-1] * solution2_results[solution2_results.size-2] * solution2_results[solution2_results.size-3]
How does it work:
The second part is nested into part one, whenever a sink is identified, a function is called, which evaluates the size of the basin arround. All basins are stored into a list, the result is calculated by multiplication of the three largest.
fun smokeBasin(input1: Int, input2: Int, input3: List<Int>, input4: Int, input5: Int): Int {
var xpos = input1
var ypos = input2
var map = mutableListOf<Char>()
var width = input4
var height = input5
var result: Int = 1
input3.forEach {
map.add((it + 48).toChar())
}
map.set(xpos + ypos * width, 'x')
var searchEnd: Boolean = false
while (!searchEnd) {
searchEnd = true
for (y in 1..height - 2) {
for (x in 1..width - 2) {
if (map[x + y * width].isDigit()) { // check if digit (no evaluation for already placed 'x')
if (map[x + y * width].toString().toInt() < 9 && map[(x - 1) + (y) * width] == 'x') {
result = result + 1
map.set(x + y * width, 'x')
searchEnd = false
} else if (map[x + y * width].toString().toInt() < 9 && map[(x + 1) + (y) * width] == 'x') {
result = result + 1
map.set(x + y * width, 'x')
searchEnd = false
} else if (map[x + y * width].toString().toInt() < 9 && map[(x) + (y - 1) * width] == 'x') {
result = result + 1
map.set(x + y * width, 'x')
searchEnd = false
} else if (map[x + y * width].toString().toInt() < 9 && map[(x) + (y + 1) * width] == 'x') {
result = result + 1
map.set(x + y * width, 'x')
searchEnd = false
}
} // if digit
} //end for x
} // end for y
} // searchEnd
return result
}
At the end, both solutions are printed out.
// print solution for part 1
println("**************************")
println("--- Day 9: Smoke Basin ---")
println("**************************")
println("Solution for part1")
println(" $solution1 is the sum of the risk levels of all low points on your heightmap")
println()
// print solution for part 2
println("*********************************")
println("Solution for part2")
println(" You get $solution2 if you add up all of the output values")
println()
// end::output[]
//}
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/10
For execution enter kotlin day2110_1_2.kts in the command line.
The conditions for the if construction got longer and longer, which was not comfortable to edit and to read. So I started to try to solve it with lambda operations, since Peter already animated me some days ago to investigate in this. I guess the result is more readable, and it was also more easy to edit and check for typos.
How does it work:
Each line will be stripped iterative of legal pairs of chunks until no legal pair is found any more. Then the remaining string is checked, if a wrong closing is in, which means it is a corrupt line and will be part of result calculation or otherwise put in a list already for part 2 (added after revealing part2)
File("day2110_puzzle_input.txt").forEachLine {
var instruction = it
var searchEnd: Boolean = false
var pattern0 = arrayOf("()", "[]", "{}", "<>")
var pattern1 = arrayOf("[)", "{)", "<)")
var pattern2 = arrayOf("(]", "{]", "<]")
var pattern3 = arrayOf("(}", "[}", "<}")
var pattern4 = arrayOf("(>", "[>", "{>")
// remove iterative all legal pairs of chunks in string
while (!searchEnd) {
if (pattern0.any { instruction.contains(it) }) {
//if (instruction.contains("()") || instruction.contains("<>") || instruction.contains("[]") || instruction.contains("{}")) {
instruction = instruction.replace("()", "")
instruction = instruction.replace("[]", "")
instruction = instruction.replace("{}", "")
instruction = instruction.replace("<>", "")
} else {
searchEnd = true
}
}
// determine if there is a wrong closing character in remaining string
if (pattern1.any { instruction.contains(it) }) {
points.put(3, points.getValue(3) + 1)
} else if (pattern2.any { instruction.contains(it) }) {
points.put(57, points.getValue(57) + 1)
} else if (pattern3.any { instruction.contains(it) }) {
points.put(1197, points.getValue(1197) + 1)
} else if (pattern4.any { instruction.contains(it) }) {
points.put(25137, points.getValue(25137) + 1)
} else {
// add all correct lines to a list, revert them already for later calculation of score for part2
correctInstructions.add(instruction.reversed())
}
}
solution1 = 3*points.getValue(3) + 57*points.getValue(57) + 1197*points.getValue(1197) + 25137*points.getValue(25137)
How does it work:
For each incomplete but correct line the total score algorithm is applied and the value put to a list. The middle value of the list is the result asked for.
// evaluate total score for all incomplete but not corrupted lines
correctInstructions.forEach {
var totalScore: Long = 0
it.forEach {
if (it.equals('(')) {
totalScore = totalScore * 5 + 1
} else if (it.equals('[')) {
totalScore = totalScore * 5 + 2
} else if (it.equals('{')) {
totalScore = totalScore * 5 + 3
} else if (it.equals('<')) {
totalScore = totalScore * 5 + 4
}
}
scoresSolution2.add(totalScore)
}
scoresSolution2.sort()
solution2 = scoresSolution2[scoresSolution2.size / 2]
At the end, both solutions are printed out.
// print solution for part 1
println("******************************")
println("--- Day 10: Syntax Scoring ---")
println("******************************")
println("Solution for part1")
println(" $solution1 is the total syntax error score for those errors")
println()
// print solution for part 2
println("*********************************")
println("Solution for part2")
println(" $solution2 is the middle score")
println()
// end::output[]
//}
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/11
For execution enter kotlin day2111_1_2.kts in the command line.
How does it work:
The puzzle input will be read into a array as integers. Then the rules are applied.
First: Increase each octopus by one. To show that a octopus is ready to flash (>9), I choosed to just set it to 100, at this time I already started counting.
Second: Iterative go through all of the tiles and if it is an octopus readiy to flash, increase all adjacent tiles
Third: Set all flashed tiles to zero.
After 100 rounds the flash counter will be reported.
var solution1: Int = 0
var solution2: Int = 0
var dumboField = Array(10) { Array(10) { 0 } }
var countFlash: Int = 0
var greaterNine: Boolean
var n: Int = 1
var stepPartTwo: Int
var allDumboFlash = false
// read puzzle input in array
var j: Int = 0
File("day2111_puzzle_input.txt").forEachLine {
for (i in 0..it.length - 1) {
dumboField[i][j] = it[i].toString().toInt()
}
j += 1
}
// run for at least 100 steps or until all dumbo's flash at same time
while (!allDumboFlash || n < 101) {
greaterNine = false
// first step: increase every tile by 1
for (y in 0..9) {
for (x in 0..9) {
dumboField[x][y] = dumboField[x][y] + 1
if (dumboField[x][y] > 9) {
greaterNine = true
}
}
}
// second step: if tile > 9, flash and increase energy level of nighbours until no tile > 9
while (greaterNine) { // loop while grid.contains 9
greaterNine = false
// go through field and search > nine
for (y in 0..9) {
for (x in 0..9) {
if (dumboField[x][y] > 9 && dumboField[x][y] < 100) {
// set field to burst (= 100), increase burstcount solution1 +=
dumboField[x][y] = 100
// count number of bursts
countFlash += 1
// now increase adjacent tiles
for (dy in -1..1) {
for (dx in -1..1) {
if (!(dx == 0 && dy == 0)) {
// if in grid increase adjacent tiles
if ((y + dy) >= 0 && (y + dy) <= 9 && (x + dx) >= 0 && (x + dx) <= 9) {
if (dumboField[x + dx][y + dy] < 100) {
dumboField[x + dx][y + dy] = dumboField[x + dx][y + dy] + 1
}
if (dumboField[x + dx][y + dy] > 9) {
greaterNine = true
}
}
}
}
}
}
}
}
} // loop greaterNine end
// 100 turns --> solution for part1
if (n == 100) {
solution1 = countFlash
}
// third step: set all tiles flashed in current turn to zero
stepPartTwo = 0
for (y in 0..9) {
for (x in 0..9) {
if (dumboField[x][y] == 100) {
dumboField[x][y] = 0
stepPartTwo += 1
// check if all dumbos flashed at same time --> solution for part2
if (stepPartTwo == 100) {
solution2 = n
allDumboFlash = true
}
}
}
}
n += 1
} // end loop allDumboFlash
How does it work:
This is integrated in the solution for part one, when applying the third rule, setting all flashed tiles to zero, also a counter is implemented. If the counter is 100, then the solution for part 2 is reached.
At the end, both solutions are printed out.
// print solution for part 1
println("*****************************")
println("--- Day 11: Dumbo Octopus ---")
println("*****************************")
println("Solution for part1")
println(" $solution1 total flashes are there after 100 steps")
println()
// print solution for part 2
println("*********************************")
println("Solution for part2")
println(" $solution2 is the first step during which all octopuses flash")
println()
// end::output[]
//}
After some discussion with Peter about using lists or arrays I created a verson based on a list and one on an array. Both are running 1000 times and the execution time is measured. I run it several times, but there was not realy a valuable result reachable, one time the array version was faster, one time the list. My expectation would have been, that the array version is faster.
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/12
For execution enter kotlin day2112_1_2.kts in the command line.
How does it work:
All possible pathes are build up step by step, each new path is checked if following the rule. As an extension for part 2 the 'followPath' function has an input paramter which is able to switch to a new rule. All path which came to an end are stored in a separate list.
fun followPath(input1: Int): Int {
var segments = mutableListOf<Pair<String, String>>()
var searchPath = mutableListOf<String>()
var searchPathNew = mutableListOf<String>()
var validPath = mutableListOf<String>()
var searchEnd: Boolean = false
var currentPath: String
var newCurrentPath: String
var ruleCheckPassed: Boolean = false
File("day2112_puzzle_input.txt").forEachLine {
var instruction = it.split("-")
if (instruction[0] == "start") {
searchPath.add(instruction[0] + "," + instruction[1])
} else if (instruction[1] == "start") {
searchPath.add(instruction[1] + "," + instruction[0])
} else {
segments.add(Pair(instruction[0], instruction[1]))
}
}
while (!searchEnd) {
searchEnd = true
searchPath.forEach {
currentPath = it
var instruction = it.split(",")
var lastSegment = instruction[instruction.size - 1]
segments.forEach {
if (lastSegment == it.first) {
newCurrentPath = currentPath + "," + it.second
if (it.second == "end") {
//if (!validPath.contains(newCurrentPath)) {
validPath.add(newCurrentPath)
//}
} else {
if (input1 == 1) {
ruleCheckPassed = !(it.second.toLowerCase() == it.second && currentPath.contains(it.second))
} else if (input1 == 2) {
ruleCheckPassed = ruleCheck2(newCurrentPath.drop(6))
}
if (ruleCheckPassed) {
searchPathNew.add(newCurrentPath)
searchEnd = false
}
}
} else if (lastSegment == it.second) {
newCurrentPath = currentPath + "," + it.first
if (it.first == "end") {
//if (!validPath.contains(newCurrentPath)) {
validPath.add(newCurrentPath)
//}
} else {
// check rule
if (input1 == 1) {
ruleCheckPassed = !(it.first.toLowerCase() == it.first && currentPath.contains(it.first))
} else if (input1 == 2) {
// rule for part 2
ruleCheckPassed = ruleCheck2(newCurrentPath.drop(6))
}
if (ruleCheckPassed) {
searchPathNew.add(newCurrentPath)
searchEnd = false
}
}
}
}
}
searchPath.clear()
searchPath.addAll(searchPathNew)
searchPathNew.clear()
}
return validPath.size
}
How does it work:
Solution for this part is integrated in function 'followPath' by just choosing an other rule to be applied. Since the rule does need some lines of code, I separated it into a new function 'ruleCheck2'
fun ruleCheck2(input1: String): Boolean {
var count = mutableMapOf<String, Int>()
var instruction = input1.split(",")
instruction.forEach {
if (it.toLowerCase() == it) {
if (count.containsKey(it)) {
count.put(it, count.getValue(it) + 1)
if (count.getValue(it) > 2) {
return false
}
} else {
count.put(it, 1)
}
}
}
var sum: Int = 0
for ((key, value) in count.entries) {
sum = sum + value
}
if (sum > count.size + 1) {
return false
}
return true
}
At the end, both solutions are printed out.
// print solution for part 1
println("*******************************")
println("--- Day 12: Passage Pathing ---")
println("*******************************")
println("Solution for part1")
println(" $solution1 paths through this cave system are there that visit small caves at most once")
println()
// print solution for part 2
println("*******************************")
println("Solution for part2")
println(" $solution2 how many paths through this cave system are there")
println()
// end::output[]
//}
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/13
For execution enter kotlin day2113_1_2.kts in the command line.
How does it work:
First the width and the height of the samples is identified. Then a list is set up for a grid, all points which are not included in the samples are marked with ".", all samples are marked with "#".
Then the rules for folding are applied, after each folding step the grid is reduced and width or height are adapted. After the first fold the number of marked dots is caluclated for the solution of part 1
// go trough each fold instruction
var firstInstruction : Boolean = true
foldInstruction.forEach {
var instruction = it.split("=")
if (instruction[0] == "y") {
// do the folding
for (y in instruction[1].toInt()..height - 1) {
for (x in 0..width - 1) {
if (markedPoints[x + y * width] == "#") {
markedPoints[x + (instruction[1].toInt() - (y - instruction[1].toInt())) * width] =
markedPoints[x + y * width]
}
}
}
// create new list
height = instruction[1].toInt()
for (y in 0..height - 1) {
for (x in 0..width - 1) {
newMarkedPoints.add(markedPoints[x + y * width])
}
}
// exchange lists
markedPoints.clear()
markedPoints.addAll(newMarkedPoints)
newMarkedPoints.clear()
} else if (instruction[0] == "x") {
// do the folding
for (y in 0..height - 1) {
for (x in instruction[1].toInt()..width - 1) {
if (markedPoints[x + y * width] == "#") {
markedPoints[(instruction[1].toInt() - (x - instruction[1].toInt())) + y * width] =
markedPoints[x + y * width]
}
}
}
// create new list
for (y in 0..height - 1) {
for (x in 0..instruction[1].toInt() - 1) {
newMarkedPoints.add(markedPoints[x + y * width])
}
}
width = instruction[1].toInt()
// exchange lists
markedPoints.clear()
markedPoints.addAll(newMarkedPoints)
newMarkedPoints.clear()
}
if (firstInstruction) {
solution1 = markedPoints.count() { it == "#" }
firstInstruction = false
}
}
How does it work:
Instead of conting all dots after first fold, folding will continue over all instructions and the resulting grid is printed out.
At the end, both solutions are printed out.
// print solution for part 1
println("***********************************")
println("--- Day 13: Transparent Origami ---")
println("***********************************")
println("Solution for part1")
println(" $solution1 dots are visible after completing just the first fold instruction on your transparent paper")
println()
// print solution for part 2
println("***********************************")
println("Solution for part2")
for (y in 0..height - 1) {
for (x in 0..width - 1) {
print(markedPoints[x + y * width])
}
println()
}
println(" do you use to activate the infrared thermal imaging camera system")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/14
For execution enter kotlin day2114_1_2.kts in the command line.
How does it work:
fun poly() will read puzzle input. For each pair of letters in the initial template the rule is applied by building up a new string. After repeating this 10 times, count the occurency of all letters and return max - min.
fun poly(input1: Int): Int {
var rules = mutableMapOf<String, String>()
var polyTemp: String = ""
File("day2114_puzzle_input.txt").forEachLine {
if (it != "") {
if (!it.contains("->")) {
polyTemp = it
} else {
var instruction = it.split(" -> ")
rules.put(instruction[0], instruction[1])
}
}
}
//iterate input1 number of steps and create new string with replacement of each pair with given rules
var newPolyTemp: String = polyTemp.take(1)
for (i in 1..input1) {
for (j in 0..polyTemp.length - 2) {
if (rules.containsKey(polyTemp.subSequence(j, j + 2).toString())) {
newPolyTemp = newPolyTemp + rules.getValue(polyTemp.subSequence(j, j + 2).toString()) + polyTemp[j + 1]
} else
newPolyTemp = newPolyTemp + polyTemp[j + 1]
}
polyTemp = newPolyTemp
newPolyTemp = polyTemp.take(1)
}
// count elements and determine max and min value
var countMap = mutableMapOf<Char, Int>()
polyTemp.forEach {
if (countMap.contains(it)) {
countMap.set(it, countMap.getValue(it) + 1)
} else {
countMap.put(it, 1)
}
}
var max: Int = 0
var min: Int = 10000
countMap.forEach {
if (it.value > max) {
max = it.value
} else if (it.value < min) {
min = it.value
}
}
return max - min
}
How does it work:
In theory, same function could work, but it takes much to long. So there is fun polyAdv(), each combination of a pair of letters will be stored with it’s number of occurency and for the next round with applying the rules new pairs are generated. After repeating this 40 times, count the occurency of all letters and return max - min.
fun polyAdv(input1: Int): Long {
var rules = mutableMapOf<String, String>()
var polyTemp: String = ""
File("day2114_puzzle_input.txt").forEachLine {
if (it != "") {
if (!it.contains("->")) {
polyTemp = it
} else {
var instruction = it.split(" -> ")
rules.put(instruction[0], instruction[1])
}
}
}
//setup Map with subSequences and counter for occurency
var polyPairs = mutableMapOf<String, Long>()
var newPolyPairs = mutableMapOf<String, Long>()
polyPairs.put(polyTemp.takeLast(1), 1)
for (j in 0..polyTemp.length - 2) {
if (polyPairs.containsKey(polyTemp.subSequence(j, j + 2).toString())) {
polyPairs.set(
polyTemp.subSequence(j, j + 2).toString(),
polyPairs.getValue(polyTemp.subSequence(j, j + 2).toString()) + 1
)
} else {
polyPairs.put(polyTemp.subSequence(j, j + 2).toString(), 1)
}
}
// iterate input1 number of steps and determine, how many new sequences will be created for the current step
for (i in 1..input1) {
polyPairs.forEach {
if (rules.contains(it.key)) {
var new1 = it.key.take(1) + rules.getValue(it.key)
var new2 = rules.getValue(it.key) + it.key.takeLast(1)
if (newPolyPairs.containsKey(new1)) {
newPolyPairs.put(
new1,
newPolyPairs.getValue(new1) + it.value
)
} else {
newPolyPairs.put(new1, it.value)
}
if (newPolyPairs.containsKey(new2)) {
newPolyPairs.put(new2, newPolyPairs.getValue(new2) + it.value)
} else {
newPolyPairs.put(new2, it.value)
}
} else {
newPolyPairs.put(it.key, it.value)
}
}
polyPairs.clear()
polyPairs.putAll(newPolyPairs)
newPolyPairs.clear()
}
// count elements and determine max and min value
var countMap = mutableMapOf<String, Long>()
for ((key, value) in polyPairs) {
if (countMap.contains(key.take(1))) {
countMap.set(key.take(1), countMap.getValue(key.take(1)) + value)
} else {
countMap.put(key.take(1), value)
}
}
var max: Long = countMap.getValue(polyTemp.take(1))
var min: Long = countMap.getValue(polyTemp.take(1))
countMap.forEach {
if (it.value > max) {
max = it.value
} else if (it.value < min) {
min = it.value
}
}
return (max - min)
}
At the end, both solutions are printed out.
// print solution for part 1
println("****************************************")
println("--- Day 14: Extended Polymerization ---")
println("****************************************")
println("Solution for part1")
println(" $solution1 you get if you take the quantity of the most common element and subtract the quantity of the least common element")
println()
// print solution for part 2
println("*******************************")
println("Solution for part2")
println(" $solution2 you get if you take the quantity of the most common element and subtract the quantity of the least common element")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/17
For execution enter kotlin day2117_1_2.kts in the command line.
How does it work:
First of all, read the puzzle input and determine target area.
The trajectory can be separated in x part and y part. So first all possible x velocites, which are able to reach target area, are calculated and stored into a list validXvel. The range can be reduced to 1 (0 and negative will never reach) to xmax (> xmax will overshoot already in first step).
// if x is > xmax, initial window will be missed already after the first step.
// find possible x velocities which are able to reach target window
for (i in 1..xmax) {
xvel = i
while (true) {
xpos = xpos + xvel
xvel = maxOf(xvel - 1, 0)
if (xpos >= xmin && xpos <= xmax) {
validXvel.add(i)
break
} else if (xpos > xmax) {
break
} else if (xvel == 0) {
break
}
}
xpos = 0
}
The minimum x velocity will need the most steps, so that is also the velocity which will enable to reach highest y position. In the first version therefore all possible y velocities for only the smalles x velocity where calculated and the highest position reached is kept as result for part one.
As a modification for part 2 all possible y velocities are not only calculated for the smallest x velocity, but for all possible x velocities. The sum of all possible x and y velocities is added up as a result for part2. Similar to narrowing the range of x velocities, y velocities can be narrowed from ymin (lower will already undershot in first step) to -ymin (asssuming a target area lower then 0 level and that a probe crossing zero will always have reached absolute value of starting velocity and therefore also definitly undershoot)
var ypos: Int = 0
var yvel: Int
var validYvel = mutableListOf<Int>()
var reachedYMax: Int = 0
var reachedYMaxOverall: Int = 0
var numberOfInit: Int = 0
validXvel.forEach {
xvel = it
// if starts lower ymin, target will already be missed with first step. If y > abs(ymin), target will also be missed
for (i in ymin..-ymin) {
yvel = i
while (true) {
xpos = xpos + xvel
xvel = maxOf(xvel - 1, 0)
ypos = ypos + yvel
yvel = yvel - 1
if (ypos > reachedYMax) {
reachedYMax = ypos
}
if (ypos >= ymin && ypos <= ymax && xpos >= xmin && xpos <= xmax) {
validYvel.add(i)
if (reachedYMax > reachedYMaxOverall) {
reachedYMaxOverall = reachedYMax
}
break
} else if (ypos < ymin) {
break
}
}
xpos = 0
xvel = it
ypos = 0
reachedYMax = 0
}
numberOfInit = numberOfInit + validYvel.size
validYvel.clear()
}
How does it work:
See description above.
At the end, both solutions are printed out.
// print solution for part 1
println("*************************")
println("--- Day 17: Tick Shot ---")
println("*************************")
println("Solution for part1")
println(" $reachedYMaxOverall is the highest y position it reaches on this trajectory")
println()
// print solution for part 2
println("*************************")
println("Solution for part2")
println(" $numberOfInit many distinct initial velocity values cause the probe to be within the target area after any step")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/18
For execution enter kotlin day2118_1.kts in the command line or _kotlin day218_2.kts
How does it work:
General idea is to create to lists for each snailfish number, one contains all values, the second one contains the level. The level is created by counting the input string’s brackets, an opening bracket will increase the level, an closing bracket will decrease. As soon as a digit is regcognised in the string, the value and the level are stored in the corresponding lists. When adding a second snailfish number, it is added to the lists and afterwards the level of all entries is increased.
After that within a while loop the reduction is started following the rules, manipulating entries of both lists. After all values are added, the magnitude is calculated
var snailFishNumber = mutableListOf<Int>()
var snailFishNumLev = mutableListOf<Int>()
var levelCount: Int = 0
var startAddition: Boolean = false
File("day2118_puzzle_input.txt").forEachLine {
it.forEach {
if (it == '[') {
levelCount += 1
} else if (it == ']') {
levelCount -= 1
} else if (it.isDigit()) {
snailFishNumber.add(it.toString().toInt())
snailFishNumLev.add(levelCount)
}
}
if (startAddition) {
// values are now added, therefore Level has to be increased by one
for (i in 0..snailFishNumLev.size - 1) {
snailFishNumLev[i] += 1
}
// reduce snail fish number
var nestInProg: Boolean = true
var j: Int = 0
while (nestInProg) {// while ....
j += 1
var nested = snailFishNumLev.indexOf(5)
var greater: Int = -1
for (i in 0..snailFishNumber.size - 1) {
if (snailFishNumber[i] > 9) {
greater = i
break
}
}
if (nested > -1) {
if (nested == 0) {
snailFishNumber[nested + 2] = snailFishNumber[nested + 2] + snailFishNumber[nested + 1]
snailFishNumber[nested + 1] = 0
snailFishNumLev[nested + 1] -= 1
snailFishNumber.removeAt(0)
snailFishNumLev.removeAt(0)
} else if (nested == snailFishNumber.size - 2) {
snailFishNumber[nested - 1] = snailFishNumber[nested - 1] + snailFishNumber[nested]
snailFishNumber[nested] = 0
snailFishNumLev[nested] -= 1
snailFishNumber.removeAt(nested + 1)
snailFishNumLev.removeAt(nested + 1)
} else {
snailFishNumber[nested - 1] = snailFishNumber[nested - 1] + snailFishNumber[nested]
snailFishNumber[nested + 2] = snailFishNumber[nested + 2] + snailFishNumber[nested + 1]
snailFishNumber[nested + 1] = 0
snailFishNumLev[nested + 1] -= 1
snailFishNumber.removeAt(nested)
snailFishNumLev.removeAt(nested)
}
} else if (greater > -1) {
var value = snailFishNumber[greater]
snailFishNumber[greater] = value / 2
snailFishNumber.add(greater + 1, value / 2 + value % 2)
snailFishNumLev[greater] = snailFishNumLev[greater] + 1
snailFishNumLev.add(greater, snailFishNumLev[greater])
} else if (nested == -1 && greater == -1) {
nestInProg = false
}
}// end while
}
startAddition = true
}
println(snailFishNumLev)
println(snailFishNumber)
println()
// calculate magnitude
while(snailFishNumLev.contains(4)) {
var lowLev = snailFishNumLev.indexOf(4)
snailFishNumber[lowLev] = snailFishNumber[lowLev]*3 + snailFishNumber[lowLev+1]*2
snailFishNumLev[lowLev] = snailFishNumLev[lowLev]- 1
snailFishNumber.removeAt(lowLev + 1)
snailFishNumLev.removeAt(lowLev + 1)
}
while(snailFishNumLev.contains(3)) {
var lowLev = snailFishNumLev.indexOf(3)
snailFishNumber[lowLev] = snailFishNumber[lowLev]*3 + snailFishNumber[lowLev+1]*2
snailFishNumLev[lowLev] = snailFishNumLev[lowLev]- 1
snailFishNumber.removeAt(lowLev + 1)
snailFishNumLev.removeAt(lowLev + 1)
}
while(snailFishNumLev.contains(2)) {
var lowLev = snailFishNumLev.indexOf(2)
snailFishNumber[lowLev] = snailFishNumber[lowLev]*3 + snailFishNumber[lowLev+1]*2
snailFishNumLev[lowLev] = snailFishNumLev[lowLev]- 1
snailFishNumber.removeAt(lowLev + 1)
snailFishNumLev.removeAt(lowLev + 1)
}
while(snailFishNumber.size > 1) {
snailFishNumber[0] = snailFishNumber[0]*3 + snailFishNumber[1]*2
snailFishNumber.removeAt(1)
}
println("magnitude: $snailFishNumber")
println()
solution1 = snailFishNumber[0]
How does it work:
Here only some modifications are necessary to run through all possible combinations of values to add, meanwhile the largest value is keept.
var snailFishNumber = mutableListOf<Int>()
var snailFishNumLev = mutableListOf<Int>()
var levelCount: Int = 0
var startAddition: Boolean = false
File("day2118_puzzle_input.txt").forEachLine {
it.forEach {
if (it == '[') {
levelCount += 1
} else if (it == ']') {
levelCount -= 1
} else if (it.isDigit()) {
snailFishNumber.add(it.toString().toInt())
snailFishNumLev.add(levelCount)
}
}
if (startAddition) {
// values are now added, therefore Level has to be increased by one
for (i in 0..snailFishNumLev.size - 1) {
snailFishNumLev[i] += 1
}
// reduce snail fish number
var nestInProg: Boolean = true
var j: Int = 0
while (nestInProg) {// while ....
j += 1
var nested = snailFishNumLev.indexOf(5)
var greater: Int = -1
for (i in 0..snailFishNumber.size - 1) {
if (snailFishNumber[i] > 9) {
greater = i
break
}
}
if (nested > -1) {
if (nested == 0) {
snailFishNumber[nested + 2] = snailFishNumber[nested + 2] + snailFishNumber[nested + 1]
snailFishNumber[nested + 1] = 0
snailFishNumLev[nested + 1] -= 1
snailFishNumber.removeAt(0)
snailFishNumLev.removeAt(0)
} else if (nested == snailFishNumber.size - 2) {
snailFishNumber[nested - 1] = snailFishNumber[nested - 1] + snailFishNumber[nested]
snailFishNumber[nested] = 0
snailFishNumLev[nested] -= 1
snailFishNumber.removeAt(nested + 1)
snailFishNumLev.removeAt(nested + 1)
} else {
snailFishNumber[nested - 1] = snailFishNumber[nested - 1] + snailFishNumber[nested]
snailFishNumber[nested + 2] = snailFishNumber[nested + 2] + snailFishNumber[nested + 1]
snailFishNumber[nested + 1] = 0
snailFishNumLev[nested + 1] -= 1
snailFishNumber.removeAt(nested)
snailFishNumLev.removeAt(nested)
}
} else if (greater > -1) {
var value = snailFishNumber[greater]
snailFishNumber[greater] = value / 2
snailFishNumber.add(greater + 1, value / 2 + value % 2)
snailFishNumLev[greater] = snailFishNumLev[greater] + 1
snailFishNumLev.add(greater, snailFishNumLev[greater])
} else if (nested == -1 && greater == -1) {
nestInProg = false
}
}// end while
}
startAddition = true
}
println(snailFishNumLev)
println(snailFishNumber)
println()
// calculate magnitude
while(snailFishNumLev.contains(4)) {
var lowLev = snailFishNumLev.indexOf(4)
snailFishNumber[lowLev] = snailFishNumber[lowLev]*3 + snailFishNumber[lowLev+1]*2
snailFishNumLev[lowLev] = snailFishNumLev[lowLev]- 1
snailFishNumber.removeAt(lowLev + 1)
snailFishNumLev.removeAt(lowLev + 1)
}
while(snailFishNumLev.contains(3)) {
var lowLev = snailFishNumLev.indexOf(3)
snailFishNumber[lowLev] = snailFishNumber[lowLev]*3 + snailFishNumber[lowLev+1]*2
snailFishNumLev[lowLev] = snailFishNumLev[lowLev]- 1
snailFishNumber.removeAt(lowLev + 1)
snailFishNumLev.removeAt(lowLev + 1)
}
while(snailFishNumLev.contains(2)) {
var lowLev = snailFishNumLev.indexOf(2)
snailFishNumber[lowLev] = snailFishNumber[lowLev]*3 + snailFishNumber[lowLev+1]*2
snailFishNumLev[lowLev] = snailFishNumLev[lowLev]- 1
snailFishNumber.removeAt(lowLev + 1)
snailFishNumLev.removeAt(lowLev + 1)
}
while(snailFishNumber.size > 1) {
snailFishNumber[0] = snailFishNumber[0]*3 + snailFishNumber[1]*2
snailFishNumber.removeAt(1)
}
println("magnitude: $snailFishNumber")
println()
solution1 = snailFishNumber[0]
At the end, both solutions are printed out.
// print solution for part 1
println("**************************")
println("--- Day 18: Snailfish ---")
println("**************************")
println("Solution for part1")
println(" $solution1 ")
println()
// print solution for part 2
println("**************************")
println("Solution for part2")
println(" $solution2 ")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/19
For execution enter kotlin day2119_1_2.kts in the command line.
For the solution of this puzzle at first I created a class which holds for each scan the scanner id, the position of the scanner (which are at the beginning only placeholders) and the raw data. There are three functions for this class, one to flip and rotate the raw data in the 24 different views, one to adapt an offset to the data, and a function to set the position after it is caluclated. The class is implemented with a lot of copy-paste-modify for the flip/rot operations, which are not very elegant, but at the end it worked and I have already put to much time into it. If you are really interested, you can find the code in the repository.
The puzzle input is read and the scans are put into an object of the above described class and put into a list allScans. The first one is already move out into a second list _matchedScans with position of the scanner set to (0,0,0).
// setup for reading puzzle input
var scanInput = mutableListOf<Triple<Int, Int, Int>>()
var allScans = mutableListOf<scanX>()
var scanID: String = ""
// read all scans of puzzle input into scanX classes and add them to a list of unmathced scans (allScans)
File("day2119_puzzle_input.txt").forEachLine {
if (it.contains("--")) {
scanInput.clear()
scanID = it.drop(4).dropLast(4).replace(" ", "-")
} else if (it.length > 1) {
var position = it.split(",")
scanInput.add(
Triple(
position[0].toString().toInt(),
position[1].toString().toInt(),
position[2].toString().toInt()
)
)
} else {
//println(scanInput.sortedWith(compareBy({ it.first }, { it.second }, { it.third }))): not necessary, does not bring any benefit
allScans.add(scanX(scanInput.toList(), scanID))
}
}
Now for all remaining objects out of allScans an element is picked and a second loop is nested to flip and rotate it in all directions. With each result, all beacons of last matchedSans objects are compared with allScans. Therefore over all beacons the offset necessary to match a single beacons is caluclated and the complete dataset of the object is shifted. If then there are 12 or more matches, the object is moved into matchedScans and removed out of allScans. At this time already also the absolut position of the new matched object is determined and stored.
At the end the list matchedScans contains all scans flipped and rotated in the right position with their absolute position stored.
// initialize list with matched scans (matchedScans) with first element of allScans list
var matchedScans = mutableListOf<scanX>()
matchedScans.add(allScans[0])
matchedScans[0].flipRotate(0)
matchedScans[0].scanPosX = 0
matchedScans[0].scanPosY = 0
matchedScans[0].scanPosY = 0
allScans.removeAt(0)
// allScans contains the unmatched scans, if a match is detected the object will be moved to matchedScans
// so if allScans is empty, no scan to match is left, job done
var matchList = mutableListOf<Int>()
var mm: Int = 0
while (allScans.isNotEmpty()) {
for (m in 0..allScans.size - 1) {
Loop@ for (ii in 0..23) {
allScans[m].flipRotate(ii)
for (j in 0..matchedScans[mm].beaconsFlipRot.size - 1) {
var beacon1 = matchedScans[mm].beaconsFlipRot[j]
for (i in 0..allScans[m].beaconsFlipRot.size - 1) {
var beacon2 = allScans[m].beaconsFlipRot[i]
var beacon2Raw = allScans[m].beacons[i]
var x_off = beacon1.first - beacon2.first
var y_off = beacon1.second - beacon2.second
var z_off = beacon1.third - beacon2.third
allScans[m].shiftByOffset(x_off, y_off, z_off)
if (matchedScans[mm].beaconsFlipRot.intersect(allScans[m].beaconsFlipRot).size > 11) {
// this is the right place to set positions of scans:
// beacon1 is used as first input. beacon2 is already shifted and transformed, so we need var beacon2Raw = allScans[m].beacons[i]
allScans[m].setPosition(beacon1, beacon2Raw, ii)
// shift allScan into matchedScan
matchedScans.add(allScans[m])
matchList.add(m)
break@Loop
}
}
}
}
}
// this is used to know which objects out of allScans where transfered into matchedScans and therefor can be deleted
matchList.sortDescending()
matchList.forEach {
allScans.removeAt(it)
}
matchList.clear()
mm += 1
}
How does it work:
For the first star, all beacons out ouf all scans of matchesScans are stored in a new list without dublicates. The size of the list is result of part 1
// for part1 print all beacons in a list without dublicates and count
var beaconsList = mutableListOf<Triple<Int, Int, Int>>()
matchedScans.forEach {
it.beaconsFlipRot.forEach {
if (!beaconsList.contains(it)) {
beaconsList.add(it)
}
}
}
solution1 = beaconsList.size
// end::part1[]
// for part2 iterate through absolute coordinates of all Scans and calculate manhatten distance
var manhattenDistMax: Int = 0
var manhattenDist: Int = 0
for (i in 0..matchedScans.size-1) {
for( j in 0..matchedScans.size-1) {
if (i!=j) {
manhattenDist = abs(matchedScans[i].scanPosX - matchedScans[j].scanPosX)
manhattenDist = manhattenDist + abs(matchedScans[i].scanPosY - matchedScans[j].scanPosY)
manhattenDist = manhattenDist + abs(matchedScans[i].scanPosZ - matchedScans[j].scanPosZ)
if (manhattenDist > manhattenDistMax) {
manhattenDistMax = manhattenDist
}
}
}
}
solution2 = manhattenDistMax
// print solution for part 1
println("******************************")
println("--- Day 19: Beacon Scanner ---")
println("******************************")
println("Solution for part1")
println(" $solution1 beacons are there")
println()
// print solution for part 2
println("******************************")
println("Solution for part2")
println(" $solution2 is the largest Manhattan distance between any two scanners")
println()
t1 = System.currentTimeMillis() - t1
println("puzzle solved in ${t1} ms")
//}
How does it work:
For the second star all positions out of all objects in matchedScans are compared to each other by calculating the manhatten distance. The max value is solution for part 2
// for part2 iterate through absolute coordinates of all Scans and calculate manhatten distance
var manhattenDistMax: Int = 0
var manhattenDist: Int = 0
for (i in 0..matchedScans.size-1) {
for( j in 0..matchedScans.size-1) {
if (i!=j) {
manhattenDist = abs(matchedScans[i].scanPosX - matchedScans[j].scanPosX)
manhattenDist = manhattenDist + abs(matchedScans[i].scanPosY - matchedScans[j].scanPosY)
manhattenDist = manhattenDist + abs(matchedScans[i].scanPosZ - matchedScans[j].scanPosZ)
if (manhattenDist > manhattenDistMax) {
manhattenDistMax = manhattenDist
}
}
}
}
solution2 = manhattenDistMax
At the end, both solutions are printed out. Be patient, it takes around 20 seconds.
// print solution for part 1
println("******************************")
println("--- Day 19: Beacon Scanner ---")
println("******************************")
println("Solution for part1")
println(" $solution1 beacons are there")
println()
// print solution for part 2
println("******************************")
println("Solution for part2")
println(" $solution2 is the largest Manhattan distance between any two scanners")
println()
t1 = System.currentTimeMillis() - t1
println("puzzle solved in ${t1} ms")
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/20
For execution enter kotlin day2120_1_2.kts in the command line.
How does it work:
First of all puzzle input is read into enhAlg string for the ruleset and inputImage map for the first image
var width: Int = 0
var height: Int = 0
var enhAlg: String = ""
var inputImage = mutableMapOf<Pair<Int, Int>, Int>()
File("day2120_puzzle_input.txt").forEachLine {
if (it.length == 512) {
enhAlg = it
} else if (it.length != 0) {
width = it.length
for (x in 0..it.length - 1) {
var light: Int
if (it[x].toString() == ".") {
light = 0
} else {
light = 1
}
inputImage.put(Pair(x, height), light)
}
height = height + 1
}
}
After reading puzzle input, the enhancement algorithm is applied n times. After each time the lights which are on are conunted and at n == 2 solution for part 1 is available.
var outputImage = mutableMapOf<Pair<Int, Int>, Int>()
for (n in 1..50) {
// iterate over input
var numLights = 0
for (y in 0 - 5 - n..height - 1 + n + 5) {
for (x in 0 - 5 - n..width - 1 + n + 5) {
var xpos = x
var ypos = y
var index: String = ""
// find index for each tile
for (yy in ypos - 1..ypos + 1) {
for (xx in xpos - 1..xpos + 1) {
if (inputImage.containsKey(Pair(xx, yy))) {
index = index + inputImage.getValue(Pair(xx, yy)).toString()
} else {
if (n % 2 == 0) {
index = index + "1"
} else {
index = index + "0"
}
}
}
}
// get value out of enhancedment algorithm and put Value in outputImage
if (enhAlg[index.toInt(2)] == '#') {
outputImage.put(Pair(x, y), 1)
numLights = numLights + 1
if (n == 2) {
solution1 = numLights
} else if (n == 50) {
solution2 = numLights
}
} else {
outputImage.put(Pair(x, y), 0)
}
}
}
inputImage.clear()
inputImage.putAll(outputImage)
outputImage.clear()
}
How does it work:
Just continue after n == 2 of part 1 until n reachd 50, then the counted lights are solution for part 2
var outputImage = mutableMapOf<Pair<Int, Int>, Int>()
for (n in 1..50) {
// iterate over input
var numLights = 0
for (y in 0 - 5 - n..height - 1 + n + 5) {
for (x in 0 - 5 - n..width - 1 + n + 5) {
var xpos = x
var ypos = y
var index: String = ""
// find index for each tile
for (yy in ypos - 1..ypos + 1) {
for (xx in xpos - 1..xpos + 1) {
if (inputImage.containsKey(Pair(xx, yy))) {
index = index + inputImage.getValue(Pair(xx, yy)).toString()
} else {
if (n % 2 == 0) {
index = index + "1"
} else {
index = index + "0"
}
}
}
}
// get value out of enhancedment algorithm and put Value in outputImage
if (enhAlg[index.toInt(2)] == '#') {
outputImage.put(Pair(x, y), 1)
numLights = numLights + 1
if (n == 2) {
solution1 = numLights
} else if (n == 50) {
solution2 = numLights
}
} else {
outputImage.put(Pair(x, y), 0)
}
}
}
inputImage.clear()
inputImage.putAll(outputImage)
outputImage.clear()
}
At the end, both solutions are printed out.
// print solution for part 1
println("**************************")
println("--- Day 20: Trench Map ---")
println("**************************")
println("Solution for part1")
println(" $solution1 pixels are lit in the resulting image")
println()
// print solution for part 2
println("**************************")
println("Solution for part2")
println(" $solution2 pixels are lit in the resulting image")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/21
For execution enter kotlin day2121_1_2.kts in the command line.
How does it work:
First the puzzle input is read into variables for further proceeding.
var startingSpace = mutableListOf<Int>()
File("day2121_puzzle_input.txt").forEachLine {
startingSpace.add(it.takeLast(1).toString().toInt())
}
var play1 = startingSpace[0]
var play2 = startingSpace[1]
All the calculations are placed into a function, which is called from the main part with the puzzle input:
var solution1 = standardDice(play1, play2)
Inside the function the game and the rules are implemented and if one player wins, the result of player’s score multiplied by number of dices thrown is returned:
fun standardDice(in1: Int, in2: Int): Int {
var play1 = in1
var play2 = in2
var play1Score: Int = 0
var play2Score: Int = 0
var dice: Int = 1
var diceCount = 0
while (play1Score < 1000 && play2Score < 1000) {
// three turns player 1
for (i in 0..2) {
play1 = ((play1 + dice - 1) % 10) + 1
dice = (dice) % 100 + 1
}
diceCount += 3
play1Score = play1Score + play1
if (play1Score >= 1000) {
return (play2Score * diceCount)
}
// three turns player 2
for (i in 0..2) {
play2 = (play2 + dice - 1) % 10 + 1
dice = (dice) % 100 + 1
}
diceCount += 3
play2Score = play2Score + play2
if (play2Score >= 1000) {
return (play1Score * diceCount)
}
}
return 1
}
How does it work:
Here the same puzzle input is used, but for calculation of the result some modifications are necessary. The spedification now asks not for a standardized row of dice results, but for a variant tree, starting with (1),(2),(3) and then (1,1),(1,2),(1,3),(2,1)…. Every round of throwing dices you multiply the input vector by 3 -→ 3, 9, 27, 81, 243… . Each player has it’s turn only after 3 times throwing the dices, so you can combine any combination of (1,2,3) to one throw with value 3-9. Each value has a number out of which dice combinations it could be reached, which is stored in a map and used to calculate the number of games following that path.
This reduction was not enough, the only idea I had was to split the calculation into separte ones and to add up the result, this is done in the main part, where already some of the staring vectors of dices are created, and then it is continued until payer one or two wins, or game ends without win, then new vectors are created with a range of 3 to 9 added to the input vector.
Tryouts have shown, that for beeing able to reach the end, the starting vector has at least to be filled with the first two values.
var play1Wins: Long = 0
var play2Wins: Long = 0
var diceVarOverall = MutableList(0) { mutableListOf<Int>() }
var diceVarOverallNew = MutableList(0) { mutableListOf<Int>() }
var diceVariation = mutableListOf<Int>()
for (ii in 3..9) {
for (iii in 3..9) {
diceVariation.add(ii)
diceVariation.add(iii)
diceVarOverall.add(diceVariation.toMutableList())
diceVariation.clear()
println("-----------------")
println("-- next turn --")
println("-----------------")
print(" diceVarOverall: ")
println(diceVarOverall)
while (diceVarOverall.isNotEmpty()) {
diceVarOverall.forEach {
var result = diracDice(play1, play2, it)
if (result.first == 1) {
play1Wins = play1Wins + result.second
} else if (result.first == 2) {
play2Wins = play2Wins + result.second
} else if (result.first == 0) {
for (i in 3..9) {
var diceVariationNew = it.toMutableList()
diceVariationNew.add(i)
diceVarOverallNew.add(diceVariationNew.toMutableList())
// diceVariationNew.clear()
}
}
}
diceVarOverall.clear()
diceVarOverall.addAll(diceVarOverallNew)
diceVarOverallNew.clear()
} // end While (diceVarOverall.isNotEmpty())
println()
}
}
var solution2 = maxOf(play1Wins, play2Wins)
With these starting vectors the function diracDice is started, if one player wins, the number of different worlds is calculated and summed up, if now player wins, the main algorithm will add nine new input vectors to the list for next run.
fun diracDice(in1: Int, in2: Int, in3: List<Int>): Pair<Int, Long> {
var play1 = in1
var play2 = in2
var play1Score: Int = 0
var play2Score: Int = 0
var dice = in3
var diceCount = 0
var numOfVars: Long = 1
var mapTable = mutableMapOf<Int, Int>()
mapTable.put(3, 1)
mapTable.put(4, 3)
mapTable.put(5, 6)
mapTable.put(6, 7)
mapTable.put(7, 6)
mapTable.put(8, 3)
mapTable.put(9, 1)
var i: Int = 0
while (true) {
play1 = ((play1 + dice[i] - 1) % 10) + 1
numOfVars = numOfVars * mapTable.getValue(dice[i])
i += 1
diceCount += 3
play1Score = play1Score + play1
if (play1Score >= 21) {
return Pair(1, numOfVars)
} else if (i > dice.size - 1) {
return Pair(0, 0)
}
play2 = (play2 + dice[i] - 1) % 10 + 1
numOfVars = numOfVars * mapTable.getValue(dice[i])
i += 1
diceCount += 3
play2Score = play2Score + play2
if (play2Score >= 21) {
return Pair(2, numOfVars)
} else if (i > dice.size - 1) {
return Pair(0, 0)
}
}
}
At the end, both solutions are printed out.
// print solution for part 1
println("*******************************")
println("--- Day 21: Dirac Dice ---")
println("*******************************")
println("Solution for part1")
println(" $solution1 you get if you multiply the score of the losing player by the number of times the die was rolled during the game")
println()
// print solution for part 2
println("*******************************")
println("Solution for part2")
println(" $solution2 are the most wins in all universes")
println()
This solution is written in Kotlin.
The original puzzle can be found at https://adventofcode.com/2021/day/25
For execution enter kotlin day2125_1.kts in the command line.
How does it work:
Puzzle input is read into a map with coordinates as key and cucumbers or free spaces as value. Within a while loop first the cucumbers facing east are considered moving, than the cucumbers facing south. As long as any cucumber has moved, the loop continues.
After no cucumber moves any more, the number of steps is printed out as solution.
import java.io.File
//fun main(args: Array<String>) {
var solution1: Int
var width: Int = 0
var depth: Int = 0
var ground = mutableMapOf<Pair<Int, Int>, String>()
File("day2125_puzzle_input.txt").forEachLine {
width = 0
it.forEach {
ground.put(Pair(width, depth), it.toString())
width += 1
}
depth += 1
}
// initial state
/* println("Inital state:")
for (y in 0..depth - 1) {
for (x in 0..width - 1) {
print(ground.getValue(Pair(x, y)))
}
println()
}
println() */
// start moves
var n: Int = 0
var groundNew = mutableMapOf<Pair<Int, Int>, String>()
var moveEnd: Boolean = false
while (!moveEnd) { // move loop
n += 1
moveEnd = true
// move east
// prepare groundNew
for (y in 0..depth - 1) {
for (x in 0..width - 1) {
groundNew.put(Pair(x, y), ground.getValue(Pair(x, y)))
}
}
// move where possible
for (y in 0..depth - 1) {
for (x in 0..width - 1) {
if (ground.getValue(Pair(x % width, y)).contains(">")) {
if (ground.getValue(Pair((x + 1) % width, y)).contains(".")) {
groundNew.put(Pair((x + 1) % width, y), ">")
groundNew.put(Pair((x) % width, y), ".")
moveEnd = false
}
}
}
}
ground.clear()
ground.putAll(groundNew)
groundNew.clear()
// move west
// prepare groundNew
for (y in 0..depth - 1) {
for (x in 0..width - 1) {
groundNew.put(Pair(x, y), ground.getValue(Pair(x, y)))
}
}
// move where possible
for (y in 0..depth - 1) {
for (x in 0..width - 1) {
if (ground.getValue(Pair(x, y % depth)).contains("v")) {
if (ground.getValue(Pair(x, (y + 1) % depth)).contains(".")) {
groundNew.put(Pair(x, (y + 1) % depth), "v")
groundNew.put(Pair(x, y % depth), ".")
moveEnd = false
}
}
}
}
ground.clear()
ground.putAll(groundNew)
groundNew.clear()
// n-th state
/* println("After $n step:")
for (y in 0..depth - 1) {
for (x in 0..width - 1) {
print(ground.getValue(Pair(x, y)))
}
println()
}
println() */
} // move loop
solution1 = n
// print solution for part 1
println("****************************")
println("--- Day 25: Sea Cucumber ---")
println("****************************")
println("Solution for part1")
println(" $solution1 is the first step on which no sea cucumbers move")
//}
How does it work:
Collect all stars, up to now (25.12.2021, 10:44 CET) I am still missing some of the puzzles :-(