Skip to content

Commit 3bb85b8

Browse files
committed
upload 2023 folder + utils + day 1 & 2 so far
1 parent 8db44e3 commit 3bb85b8

File tree

13 files changed

+1014
-0
lines changed

13 files changed

+1014
-0
lines changed

adventofcode2023/pom.xml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
8+
<name>adventofcode2023</name>
9+
10+
<groupId>com.matsemann</groupId>
11+
<artifactId>adventofcode2023</artifactId>
12+
<version>1.0-SNAPSHOT</version>
13+
14+
<properties>
15+
<maven.compiler.source>21</maven.compiler.source>
16+
<maven.compiler.target>21</maven.compiler.target>
17+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18+
<kotlin.version>1.9.21</kotlin.version>
19+
20+
<kotlin.compiler.jvmTarget>21</kotlin.compiler.jvmTarget>
21+
</properties>
22+
23+
<dependencies>
24+
<dependency>
25+
<groupId>org.jetbrains.kotlin</groupId>
26+
<artifactId>kotlin-stdlib-jdk8</artifactId>
27+
<version>${kotlin.version}</version>
28+
</dependency>
29+
<dependency>
30+
<groupId>org.jetbrains.kotlin</groupId>
31+
<artifactId>kotlin-test</artifactId>
32+
<version>${kotlin.version}</version>
33+
<scope>test</scope>
34+
</dependency>
35+
</dependencies>
36+
37+
<build>
38+
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
39+
<plugins>
40+
<plugin>
41+
<groupId>org.jetbrains.kotlin</groupId>
42+
<artifactId>kotlin-maven-plugin</artifactId>
43+
<version>${kotlin.version}</version>
44+
<extensions>true</extensions>
45+
</plugin>
46+
</plugins>
47+
</build>
48+
</project>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.matsemann.adventofcode2023
2+
3+
import com.matsemann.adventofcode2023.utils.*
4+
5+
fun day01_1(lines: List<String>): Any {
6+
return lines
7+
.map { it.split("").ints() }
8+
.map { it.first().toString() + it.last().toString() }
9+
.map { it.toInt() }
10+
.sum()
11+
}
12+
13+
14+
fun day01_2(lines: List<String>): Any {
15+
val replacements = listOf(
16+
"one" to "1",
17+
"two" to "2",
18+
"three" to "3",
19+
"four" to "4",
20+
"five" to "5",
21+
"six" to "6",
22+
"seven" to "7",
23+
"eight" to "8",
24+
"nine" to "9"
25+
)
26+
27+
return lines
28+
.map {
29+
// substitute => "one" to "one1one" etc (to survive eightwo otherwise being eigh2 after a replacement)
30+
replacements.fold(it) { acc, pair ->
31+
acc.replace(pair.first, pair.first + pair.second + pair.first)
32+
}
33+
}
34+
// Then just use logic from part1
35+
.map { it.split("").ints() }
36+
.map { it.first().toString() + it.last().toString() }
37+
.map { it.toInt() }
38+
.sum()
39+
}
40+
41+
fun main() {
42+
43+
// run("1", fileName = "day01_ex.txt", func = ::day01_1)
44+
run("2", fileName = "day01_ex2.txt", func = ::day01_2)
45+
46+
47+
// run("1", fileName = "day01.txt", func = ::day01_1)
48+
run("2", fileName = "day01.txt", func = ::day01_2)
49+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.matsemann.adventofcode2023
2+
3+
import com.matsemann.adventofcode2023.utils.*
4+
import kotlin.math.max
5+
6+
data class CubeDraw(val r: Int, val g: Int, val b: Int)
7+
8+
fun parseCubeDraws(lines: List<String>): List<Pair<Int, List<CubeDraw>>> {
9+
return lines.map {
10+
val spl = it.split(":")
11+
val gameNr = spl[0].firstInt()
12+
13+
val draws = spl[1].split("; ").map { draw ->
14+
val colors = draw.split(", ")
15+
val r = colors.find { color -> color.contains("red") }?.firstInt() ?: 0
16+
val g = colors.find { color -> color.contains("green") }?.firstInt() ?: 0
17+
val b = colors.find { color -> color.contains("blue") }?.firstInt() ?: 0
18+
CubeDraw(r, g, b)
19+
}
20+
gameNr to draws
21+
}
22+
}
23+
24+
fun day02_1(lines: List<String>): Any {
25+
val limit = CubeDraw(12, 13, 14)
26+
27+
return parseCubeDraws(lines)
28+
.filter {
29+
it.second.all { draw ->
30+
draw.r <= limit.r && draw.g <= limit.g && draw.b <= limit.b
31+
}
32+
}.sumOf { it.first }
33+
}
34+
35+
36+
fun day02_2(lines: List<String>): Any {
37+
return parseCubeDraws(lines)
38+
.sumOf { game ->
39+
game.second.fold(CubeDraw(0, 0, 0)) { limit, draw ->
40+
CubeDraw(max(limit.r, draw.r), max(limit.g, draw.g), max(limit.b, draw.b))
41+
}.let { it.r * it.b * it.g }
42+
}
43+
}
44+
45+
fun main() {
46+
47+
// run("1", fileName = "day02_ex.txt", func = ::day02_1)
48+
run("2", fileName = "day02_ex.txt", func = ::day02_2)
49+
50+
51+
// run("1", fileName = "day02.txt", func = ::day02_1)
52+
run("2", fileName = "day02.txt", func = ::day02_2)
53+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.matsemann.adventofcode2023.utils
2+
3+
4+
class Cached<I1, O>(val func: Cached<I1, O>.(I1) -> O) {
5+
private val cache = mutableMapOf<I1, O>()
6+
7+
operator fun invoke(i: I1): O {
8+
return if (i in cache) {
9+
cache[i]!!
10+
} else {
11+
this.func(i).also {
12+
cache[i] = it
13+
}
14+
}
15+
}
16+
}
17+
18+
class Cached2<I1, I2, O>(val func: Cached2<I1, I2, O>.(I1, I2) -> O) {
19+
private val cache = mutableMapOf<Pair<I1, I2>, O>()
20+
21+
operator fun invoke(i1: I1, i2: I2): O {
22+
val key = i1 to i2
23+
return if (key in cache) {
24+
cache[key]!!
25+
} else {
26+
this.func(i1, i2).also {
27+
cache[key] = it
28+
}
29+
}
30+
}
31+
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
package com.matsemann.adventofcode2023.utils
2+
3+
/**
4+
* A general cartesian function, accepts any number of lists
5+
* and returns a sequence. So it's lazy, only ever keeping
6+
* the current product in memory when iterating through it
7+
*
8+
* cartesian([1,2], [a,b,c])
9+
* => [(1,a), (1,b), (1,c), (2,a), (2,b), (2,c)]
10+
*/
11+
fun <E> cartesian(lists: List<List<E>>): Sequence<List<E>> {
12+
return sequence {
13+
val counters = Array(lists.size) { 0 }
14+
val length = lists.fold(1) { acc, list -> acc * list.size }
15+
16+
for (i in 0 until length) {
17+
val result = lists.mapIndexed { index, list ->
18+
list[counters[index]]
19+
}
20+
yield(result)
21+
for (pointer in lists.size - 1 downTo 0) {
22+
counters[pointer]++
23+
if (counters[pointer] == lists[pointer].size) {
24+
counters[pointer] = 0
25+
} else {
26+
break
27+
}
28+
}
29+
}
30+
}
31+
}
32+
33+
/**
34+
* Cartesian product of two lists,
35+
* util for keeping typing
36+
*/
37+
fun <E, F> cartesian(list1: List<E>, list2: List<F>): Sequence<Pair<E, F>> =
38+
cartesian(listOf(list1, list2)).map { it[0] as E to it[1] as F }
39+
40+
/**
41+
* Cartesian product of two lists,
42+
* util for keeping typing
43+
*/
44+
@JvmName("cartesianExt")
45+
fun <E, F> List<E>.cartesian(list2: List<F>) = cartesian(this, list2)
46+
47+
/**
48+
* Cartesian product of three lists,
49+
* util for keeping typing
50+
*/
51+
fun <E, F, G> cartesian(list1: List<E>, list2: List<F>, list3: List<G>): Sequence<Triple<E, F, G>> =
52+
cartesian(listOf(list1, list2, list3)).map { Triple(it[0] as E, it[1] as F, it[2] as G) }
53+
54+
55+
/**
56+
* All combinations of items in the list, of the given length.
57+
* If length is not given, the length is the size of the list
58+
* Similar to permutations, but order doesn't matter.
59+
*
60+
* [a, b, c], length=2 => [(a,b), (a,c), (b, c)]
61+
* (while permutations would also have (b,a) for instance)
62+
*/
63+
fun <E> combinations(list: List<E>, length: Int? = null): Sequence<List<E>> {
64+
65+
return sequence {
66+
val n = list.size
67+
val r = length ?: list.size
68+
// a b c d , 2
69+
val counters = Array(r) { it } // 0,1
70+
val maxes = Array(r) { it + n - r } // 2 3
71+
72+
yield(counters.map { list[it] })
73+
while (true) {
74+
val lastNotAtMax = counters.indices.findLast { counter ->
75+
counters[counter] != maxes[counter]
76+
} ?: return@sequence // All was at max
77+
78+
counters[lastNotAtMax]++
79+
80+
// Increase the others behind (that were one max)
81+
for (toUpdate in lastNotAtMax + 1 until r) {
82+
counters[toUpdate] = counters[toUpdate - 1] + 1
83+
}
84+
85+
yield(counters.map { list[it] })
86+
87+
88+
}
89+
90+
}
91+
92+
}
93+
94+
/**
95+
* All possible permutations of the list for the given length.
96+
* If length is not given, the length is the size of the list
97+
*
98+
* [a, b, c], length=2 =>
99+
* [(a,b), (a,c), (b,a), (b,c), (c,a), (c,b)]
100+
*/
101+
fun <E> permutations(list: List<E>, length: Int? = null): Sequence<List<E>> = sequence {
102+
val n = list.size
103+
val r = length ?: list.size
104+
105+
val indices = list.indices.toMutableList()
106+
val cycles = (n downTo (n - r)).toMutableList()
107+
yield(indices.take(r).map { list[it] })
108+
109+
while (true) {
110+
var broke = false
111+
for (i in (r - 1) downTo 0) {
112+
cycles[i]--
113+
if (cycles[i] == 0) {
114+
val end = indices[i]
115+
for (j in i until indices.size - 1) {
116+
indices[j] = indices[j + 1]
117+
}
118+
indices[indices.size - 1] = end
119+
cycles[i] = n - i
120+
} else {
121+
val j = cycles[i]
122+
val tmp = indices[i]
123+
indices[i] = indices[-j + indices.size]
124+
indices[-j + indices.size] = tmp
125+
yield(indices.take(r).map { list[it] })
126+
broke = true
127+
break
128+
}
129+
}
130+
if (!broke) {
131+
break
132+
}
133+
}
134+
}
135+
136+
operator fun <E> Int.times(list: List<E>): List<List<E>> {
137+
return List(this) { list }
138+
}
139+
140+
@JvmName("timesMutable")
141+
operator fun <E> Int.times(list: MutableList<E>) =
142+
MutableList(this) { list.toMutableList() }
143+
144+
145+
146+
fun main() {
147+
println(permutations(listOf("a", "b", "c")).toList())
148+
println(permutations(listOf("a", "b", "c"), 2).toList())
149+
println(permutations(listOf("a", "b", "c", "d"), 2).toList())
150+
println(permutations(listOf("a", "b", "c", "d"), 2).map { it.toSet() }.toSet())
151+
println()
152+
println(combinations(listOf("a", "b", "c", "d"), 2).toList())
153+
println()
154+
println(cartesian(2 * listOf("a", "b", "c", "d")).toList())
155+
}

0 commit comments

Comments
 (0)