Skip to content

Commit c1a2866

Browse files
committed
Merge branch 'release/15days2023'
2 parents e0f4ace + ca8a5e0 commit c1a2866

File tree

5 files changed

+319
-0
lines changed

5 files changed

+319
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package net.olegg.aoc.year2023.day11
2+
3+
import net.olegg.aoc.someday.SomeDay
4+
import net.olegg.aoc.utils.Vector2D
5+
import net.olegg.aoc.utils.pairs
6+
import net.olegg.aoc.year2023.DayOf2023
7+
8+
/**
9+
* See [Year 2023, Day 11](https://adventofcode.com/2023/day/11)
10+
*/
11+
object Day11 : DayOf2023(11) {
12+
override fun first(): Any? {
13+
return solve(2)
14+
}
15+
16+
override fun second(): Any? {
17+
return solve(1000000)
18+
}
19+
20+
private fun solve(add: Long): Long {
21+
val emptyRows = matrix.mapIndexedNotNull { index, row ->
22+
index.takeIf { row.all { it == '.' } }
23+
}
24+
val emptyColumns = matrix.first().indices
25+
.filter { column ->
26+
matrix.all { it[column] == '.' }
27+
}
28+
29+
val galaxies = matrix.flatMapIndexed { y, row ->
30+
row.mapIndexedNotNull { x, c ->
31+
if (c == '#') {
32+
Vector2D(x, y)
33+
} else {
34+
null
35+
}
36+
}
37+
}
38+
39+
return galaxies.pairs()
40+
.map {
41+
val dx = (minOf(it.first.x, it.second.x)..<maxOf(it.first.x, it.second.x))
42+
.sumOf { x ->
43+
if (x in emptyColumns) add else 1
44+
}
45+
46+
val dy = (minOf(it.first.y, it.second.y)..<maxOf(it.first.y, it.second.y))
47+
.sumOf { y ->
48+
if (y in emptyRows) add else 1
49+
}
50+
51+
dx + dy
52+
}
53+
.sum()
54+
}
55+
}
56+
57+
fun main() = SomeDay.mainify(Day11)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package net.olegg.aoc.year2023.day12
2+
3+
import net.olegg.aoc.someday.SomeDay
4+
import net.olegg.aoc.utils.parseInts
5+
import net.olegg.aoc.utils.toPair
6+
import net.olegg.aoc.year2023.DayOf2023
7+
8+
/**
9+
* See [Year 2023, Day 12](https://adventofcode.com/2023/day/12)
10+
*/
11+
object Day12 : DayOf2023(12) {
12+
private val DOTS = "\\.+".toRegex()
13+
private val EMPTY = setOf('.', '?', null)
14+
private val FILLED = setOf('#', '?')
15+
16+
override fun first(): Any? {
17+
return lines
18+
.map { line -> line.split(" ").toPair() }
19+
.map { (line, counts) ->
20+
line to counts.parseInts(",")
21+
}
22+
.sumOf { (line, counts) ->
23+
count(line, counts)
24+
}
25+
}
26+
27+
override fun second(): Any? {
28+
return lines
29+
.map { line -> line.split(" ").toPair() }
30+
.map { (line, counts) ->
31+
line to counts.parseInts(",")
32+
}
33+
.map { (line, counts) ->
34+
List(5) { line }.joinToString(separator = "?") to List(5) { counts }.flatten()
35+
}
36+
.sumOf { (line, counts) ->
37+
count(line, counts)
38+
}
39+
}
40+
41+
private fun count(line: String, counts: List<Int>): Long {
42+
val dyn = Array(counts.size + 1) { LongArray(line.length + 1) { 0 } }
43+
44+
dyn[0][line.length] = 1
45+
line.withIndex()
46+
.reversed()
47+
.takeWhile { it.value != '#' }
48+
.forEach { dyn[0][it.index] = 1 }
49+
50+
for (j in 1..counts.size) {
51+
val count = counts[counts.size - j]
52+
val fix = if (j == 1) 0 else 1
53+
for (i in line.length - 1 downTo 0) {
54+
if (line[i] in EMPTY) {
55+
dyn[j][i] += dyn[j].getOrElse(i + 1) { 0 }
56+
}
57+
if (line[i] in FILLED) {
58+
if (line.getOrNull(i - 1) in EMPTY &&
59+
(i + 1..<i + count).all { line.getOrNull(it) in FILLED } &&
60+
line.getOrNull(i + count) in EMPTY) {
61+
dyn[j][i] += dyn[j - 1].getOrElse(i + count + fix) { 0 }
62+
}
63+
}
64+
}
65+
}
66+
67+
return dyn.last().first()
68+
}
69+
}
70+
71+
fun main() = SomeDay.mainify(Day12)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package net.olegg.aoc.year2023.day13
2+
3+
import net.olegg.aoc.someday.SomeDay
4+
import net.olegg.aoc.year2023.DayOf2023
5+
6+
/**
7+
* See [Year 2023, Day 13](https://adventofcode.com/2023/day/13)
8+
*/
9+
object Day13 : DayOf2023(13) {
10+
override fun first(): Any? {
11+
val patterns = data.split("\n\n").map { pattern -> pattern.lines().map { it.toList() } }
12+
val transposed = patterns.map { it.transpose() }
13+
14+
return transposed.sumOf { it.rowsBeforeReflection() } + 100 * patterns.sumOf { it.rowsBeforeReflection() }
15+
}
16+
17+
override fun second(): Any? {
18+
val patterns = data.split("\n\n").map { pattern -> pattern.lines().map { it.toList() } }
19+
val transposed = patterns.map { it.transpose() }
20+
21+
return transposed.sumOf { it.rowsBeforeSmudge() } + 100 * patterns.sumOf { it.rowsBeforeSmudge() }
22+
}
23+
24+
private fun List<List<Char>>.transpose(): List<List<Char>> {
25+
return List(first().size) { row ->
26+
List(size) { column -> this[column][row] }
27+
}
28+
}
29+
30+
private fun List<List<Char>>.rowsBeforeReflection(): Int {
31+
val rev = asReversed()
32+
for (i in 1..<size) {
33+
val below = drop(i)
34+
val above = rev.takeLast(i)
35+
36+
if (above.zip(below).all { (a, b) -> a == b }) {
37+
return i
38+
}
39+
}
40+
return 0
41+
}
42+
43+
private fun List<List<Char>>.rowsBeforeSmudge(): Int {
44+
val rev = asReversed()
45+
for (i in 1..<size) {
46+
val below = drop(i)
47+
val above = rev.takeLast(i)
48+
49+
if (above.zip(below).sumOf { (a, b) -> a.zip(b).count { (ca, cb) -> ca != cb } } == 1) {
50+
return i
51+
}
52+
}
53+
return 0
54+
}
55+
}
56+
57+
fun main() = SomeDay.mainify(Day13)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package net.olegg.aoc.year2023.day14
2+
3+
import net.olegg.aoc.someday.SomeDay
4+
import net.olegg.aoc.year2023.DayOf2023
5+
6+
/**
7+
* See [Year 2023, Day 14](https://adventofcode.com/2023/day/14)
8+
*/
9+
object Day14 : DayOf2023(14) {
10+
override fun first(): Any? {
11+
val shifted = matrix.transpose().shiftLeft()
12+
13+
return shifted.transpose().northLoad()
14+
}
15+
16+
override fun second(): Any? {
17+
val seen = mutableMapOf<List<List<Char>>, Int>()
18+
val rev = mutableMapOf<Int, List<List<Char>>>()
19+
20+
var curr = matrix
21+
var step = 0
22+
23+
while (curr !in seen){
24+
rev[step] = curr
25+
seen[curr] = step
26+
step++
27+
val north = curr.transpose().shiftLeft().transpose()
28+
val west = north.shiftLeft()
29+
val south = west.transpose().flip().shiftLeft().flip().transpose()
30+
curr = south.flip().shiftLeft().flip()
31+
}
32+
33+
val head = seen.getValue(curr)
34+
val loop = step - head
35+
val tail = (1000000000 - head) % loop
36+
37+
val final = rev.getValue(head + tail)
38+
39+
return final.northLoad()
40+
}
41+
42+
private fun List<List<Char>>.transpose(): List<List<Char>> {
43+
return List(first().size) { row ->
44+
List(size) { column -> this[column][row] }
45+
}
46+
}
47+
48+
private fun List<List<Char>>.northLoad(): Int {
49+
return mapIndexed { y, row ->
50+
(size - y) * row.count { it == 'O' }
51+
}.sum()
52+
}
53+
54+
private fun List<List<Char>>.shiftLeft() = map { row ->
55+
val total = StringBuilder()
56+
val round = StringBuilder()
57+
"#$row".reversed().forEach { char ->
58+
when (char) {
59+
'.' -> total.append(char)
60+
'O' -> round.append(char)
61+
'#' -> {
62+
total.append(round).append(char)
63+
round.setLength(0)
64+
}
65+
}
66+
}
67+
68+
total.setLength(total.length - 1)
69+
total.reverse().toList()
70+
}
71+
72+
private fun List<List<Char>>.flip() = map { it.asReversed() }
73+
}
74+
75+
fun main() = SomeDay.mainify(Day14)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package net.olegg.aoc.year2023.day15
2+
3+
import net.olegg.aoc.someday.SomeDay
4+
import net.olegg.aoc.utils.toPair
5+
import net.olegg.aoc.year2023.DayOf2023
6+
import net.olegg.aoc.year2023.day15.Day15.Step.Companion.toStep
7+
8+
/**
9+
* See [Year 2023, Day 15](https://adventofcode.com/2023/day/15)
10+
*/
11+
object Day15 : DayOf2023(15) {
12+
override fun first(): Any? {
13+
return data.split(",").sumOf { step ->
14+
step.hash()
15+
}
16+
}
17+
18+
override fun second(): Any? {
19+
val steps = data.split(",").map { it.toStep() }
20+
21+
val boxes = List(256) { LinkedHashMap<String, Int>() }
22+
23+
steps.forEach { step ->
24+
val index = step.label.hash()
25+
when (step) {
26+
is Step.Remove -> boxes[index].remove(step.label)
27+
is Step.Add -> boxes[index][step.label] = step.value
28+
}
29+
}
30+
31+
return boxes.mapIndexed { box, lenses ->
32+
(box + 1) * lenses.values.mapIndexed { index, value -> (index + 1) * value }.sum()
33+
}.sum()
34+
}
35+
36+
private fun String.hash() = fold(0) { acc, char -> (acc + char.code) * 17 % 256 }
37+
38+
sealed interface Step {
39+
val label: String
40+
41+
data class Add(
42+
override val label: String,
43+
val value: Int,
44+
) : Step
45+
46+
data class Remove(
47+
override val label: String,
48+
) : Step
49+
50+
companion object {
51+
fun String.toStep() = when {
52+
last() == '-' -> Remove(dropLast(1))
53+
else -> split("=").toPair().let { Add(it.first, it.second.toInt()) }
54+
}
55+
}
56+
}
57+
}
58+
59+
fun main() = SomeDay.mainify(Day15)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy