Advent of Code 2021 day 1
12/01/2022, 5:00 AMKroppeb
12/01/2022, 5:03 AMKroppeb
12/01/2022, 5:04 AMMichael de Kaste
12/01/2022, 5:12 AMDavid Whittaker
12/01/2022, 5:14 AMNeil Banman
12/01/2022, 5:14 AMDavid Whittaker
12/01/2022, 5:14 AMMichael de Kaste
12/01/2022, 5:18 AMDan Fingal-Surma
12/01/2022, 5:18 AMNeil Banman
12/01/2022, 5:18 AMMarcin Wisniowski
12/01/2022, 5:29 AMDan Fingal-Surma
12/01/2022, 5:29 AMMichael de Kaste
12/01/2022, 5:32 AMobject Day1 : Challenge() {
val parsed = input.split(lineSeparator() + lineSeparator())
.map { it.lines().sumOf(Integer::parseInt) }
.sortedDescending()
override fun part1() = parsed.first()
override fun part2() = parsed.take(3).sum()
}
Dan Fingal-Surma
12/01/2022, 5:34 AMMarcin Wisniowski
12/01/2022, 5:34 AMinput
is the entire file here.Dan Fingal-Surma
12/01/2022, 5:34 AMDan Fingal-Surma
12/01/2022, 5:34 AMMichael de Kaste
12/01/2022, 5:35 AMMarcin Wisniowski
12/01/2022, 5:35 AMMichael de Kaste
12/01/2022, 5:35 AMMichael de Kaste
12/01/2022, 5:35 AMDavid Whittaker
12/01/2022, 5:38 AMsortedDescending()
then you can take
instead of takeLast
Neil Banman
12/01/2022, 5:38 AMMarcin Wisniowski
12/01/2022, 5:39 AMsorted()
and takeLast(3)
because it's shorter than sortedDescending()
and take(3)
. 😄Maciej Procyk
12/01/2022, 5:57 AMandrew
12/01/2022, 6:20 AMandrew
12/01/2022, 6:21 AMbabel
12/01/2022, 6:24 AMlines
.mapIndexedNotNull { index, entry ->
index.takeIf { index == 0 || entry.isEmpty() || index == lines.lastIndex }
}
.windowed(2)
.maxOf { (from, to) ->
lines.subList(from, to)
.filter(String::isNotEmpty)
.sumOf(String::toInt)
}
.also(::println)
Davio
12/01/2022, 7:39 AMMichael Böiers
12/01/2022, 7:42 AMfun main() = day01(String(System.`in`.readAllBytes())).toList().forEach(::println)
fun day01(input: String) = input.split("\n\n")
.map { it.split("\n").map(String::toInt).sum() }
.sortedDescending()
.let { it.first() to it.take(3).sum() }
Michael Böiers
12/01/2022, 7:47 AMJan Durovec
12/01/2022, 7:49 AMsubList
in a loop as it feels O(n) to me, but it depends on what type of list your lines
are 😉Davio
12/01/2022, 7:51 AMvar maxElfCalories = 0
getInputAsSequence().fold(0) { acc, line ->
if (line.isBlank()) {
maxElfCalories = maxOf(acc, maxElfCalories)
0
} else {
acc + line.toInt()
}
}.call { println(maxElfCalories) }
Davio
12/01/2022, 7:53 AMcall
is an extension function I made as a companion to the let, apply etc. family, it takes a block which returns Unit and returns Unit itself, so it's a simple consumer if you willMichael Böiers
12/01/2022, 8:06 AMfun day01(lines: List<String>): Pair<Int, Int> {
var sum = 0
var maxSum = Int.MIN_VALUE
val maxSums = mutableListOf<Int>()
for (line in lines) {
if (line == "") {
maxSums += sum
maxSum = max(maxSum, sum)
sum = 0
} else sum += line.toInt()
}
return maxSum to maxSums.sortedDescending().let { it[0] + it[1] + it[2] }
}
Davio
12/01/2022, 8:34 AMDavio
12/01/2022, 8:35 AMMichael Böiers
12/01/2022, 8:37 AMDavio
12/01/2022, 8:38 AMMichael Böiers
12/01/2022, 8:38 AMDavio
12/01/2022, 8:39 AMMichael Böiers
12/01/2022, 8:40 AMDavio
12/01/2022, 8:42 AMDavio
12/01/2022, 8:43 AMMichael de Kaste
12/01/2022, 8:44 AMDavio
12/01/2022, 8:46 AMMichael Böiers
12/01/2022, 8:46 AMDavio
12/01/2022, 8:47 AMDavio
12/01/2022, 8:49 AMMichael Böiers
12/01/2022, 8:50 AMfun <T> List<T>.chunked(separator: (T) -> Boolean): List<List<T>>
And then you would just
list.chunked { it.isBlank() }
Davio
12/01/2022, 8:52 AMMichael Böiers
12/01/2022, 8:52 AMJoey Haas
12/01/2022, 9:12 AMfun part1() = parse().takeLast(1).sum().let(::println)
fun part2() = parse().takeLast(3).sum().let(::println)
fun parse() = FileReader("1.in")
.readLines()
.joinToString("-")
.split("--")
.map { elf ->
elf
.split("-")
.map(String::toLong)
.sum()
}
.sorted()
No intention to mess with newline chars, so I hacked it up like this.Davio
12/01/2022, 9:15 AMchunked with predicate
function:
fun <T> Sequence<T>.chunked(predicate: (T) -> Boolean): Sequence<List<T>> {
val iterator = this.iterator()
val buffer = mutableListOf<T>()
return sequence {
while (iterator.hasNext()) {
val element = iterator.next()
if (predicate.invoke(element)) {
yield(buffer.toList())
buffer.clear()
} else {
buffer.add(element)
}
}
if (buffer.isNotEmpty()) {
yield(buffer.toList())
}
}
}
Davio
12/01/2022, 9:16 AMDavio
12/01/2022, 9:45 AMchunked
function, the solution for part 1 simplifies to:
getInputAsSequence()
.chunked { it.isBlank() }
.map { it.sumOf(String::toInt) }
.max()
Michael Böiers
12/01/2022, 9:47 AMMichael Böiers
12/01/2022, 9:48 AMDavio
12/01/2022, 9:49 AMJan Durovec
12/01/2022, 9:49 AMsorted()
in parse()
makes it O(n*log(n)). I personally think that it would be better if parse()
returned just the collection without the sorting and then in part1
you can just call max
(keeping it O(n)) and applied sortedDescending().take(3).sum()
only in part2
Michael Böiers
12/01/2022, 9:52 AMKroppeb
12/01/2022, 9:53 AMDavio
12/01/2022, 9:54 AMfun <T : Comparable<T>> List<T>.top(n: Int): List<T> = this.sortedDescending().take(n)
fun <T : Comparable<T>> List<T>.bottom(n: Int): List<T> = this.sorted().take(n)
fun <T : Comparable<T>> Sequence<T>.top(n: Int): Sequence<T> = this.sortedDescending().take(n)
fun <T : Comparable<T>> Sequence<T>.bottom(n: Int): Sequence<T> = this.sorted().take(n)
Jan Durovec
12/01/2022, 9:54 AMArrayList
or random access list. On LinkedList
etc it must be O(n) as there's no other way to iterate to nth elementDavio
12/01/2022, 9:54 AMgetInputAsSequence()
.split { it.isBlank() }
.map { it.sumOf(String::toInt) }
.top(3)
Kroppeb
12/01/2022, 9:56 AMMichael Böiers
12/01/2022, 9:57 AMDavio
12/01/2022, 9:57 AMMichael Böiers
12/01/2022, 9:57 AMKroppeb
12/01/2022, 9:58 AMDavio
12/01/2022, 9:58 AMDavio
12/01/2022, 9:58 AMMichael Böiers
12/01/2022, 9:59 AMDavio
12/01/2022, 10:00 AMDavio
12/01/2022, 10:01 AMDavio
12/01/2022, 10:01 AMgetInputAsSequence()
.split { it.isBlank() }
.map { it.sumOf(String::toInt) }
.top(3)
.sum()
Michael de Kaste
12/01/2022, 10:02 AM.split(String::isBlank)
to stay in line with the line below it 😛Davio
12/01/2022, 10:02 AMit
😄Michael Böiers
12/01/2022, 10:06 AMDavio
12/01/2022, 10:09 AMMichael Böiers
12/01/2022, 10:10 AMKroppeb
12/01/2022, 10:11 AMMichael Böiers
12/01/2022, 10:11 AMKroppeb
12/01/2022, 10:13 AMMichael Böiers
12/01/2022, 10:14 AMDavio
12/01/2022, 11:21 AMDavio
12/01/2022, 11:22 AMxxfast
12/01/2022, 11:44 AMfun summed(input: List<String>) = input
.fold(listOf(listOf(0))) { acc, i ->
if(i.isEmpty()) return@fold acc + listOf(listOf(0))
val updated = acc.last().plus(i.toInt())
acc.dropLast(1) + listOf(updated)
}
.map { it.sum() }
fun part1(input: List<String>): Int = summed(input).max()
fun part2(input: List<String>): Int = summed(input).sortedDescending().take(3).sum()
Paul Woitaschek
12/01/2022, 12:01 PMKroppeb
12/01/2022, 12:05 PMMichael Böiers
12/01/2022, 12:06 PMMichael Böiers
12/01/2022, 12:19 PMfun main() = day01Fold(String(System.`in`.readAllBytes())).forEach(::println)
fun day01Fold(input: String) = input.split("\n")
.fold(mutableListOf(0)) { acc, line ->
if (line.isBlank()) acc += 0 else acc[acc.lastIndex] = acc[acc.lastIndex] + line.toInt()
acc
}
.sortedDescending()
.let { listOf(it.first(), it.take(3).sum()) }
Davio
12/01/2022, 1:09 PMDavio
12/01/2022, 1:10 PMMichael Böiers
12/01/2022, 1:33 PMlist.sortedDescending(take = 3)
.Davio
12/01/2022, 1:48 PMfun getResultPart2() {
val fixedSizeList = FixedSizeList(3, { 0 }) { newElement ->
this.mapIndexed { index, element -> Pair(index, element) }
.filter { newElement > it.second }
.minByOrNull { it.second }
?.first ?: -1
}
getInputAsSequence()
.split(String::isBlank)
.map { it.sumOf(String::toInt) }
.forEach { fixedSizeList.add(it) }
println(fixedSizeList.sum())
}
private class FixedSizeList<T>(
private val maxSize: Int,
private val initializer: () -> T,
private val additionIndexBlock: FixedSizeList<T>.(T) -> Int
) : ArrayList<T>(maxSize) {
init {
repeat(maxSize) {
add(initializer.invoke())
}
}
override fun add(element: T): Boolean {
if (size < maxSize) {
return super.add(element)
}
val indexOfElementToOverwrite = additionIndexBlock.invoke(this, element)
return if (indexOfElementToOverwrite > -1) {
this[indexOfElementToOverwrite] = element
true
} else {
false
}
}
}
Davio
12/01/2022, 1:50 PMadd
function returns a Boolean to let the user know if their addition changed the list or not, this is totally not used or needed in this example, but it's fun that it existsDavio
12/01/2022, 1:52 PMKevin Del Castillo
12/01/2022, 3:32 PMphldavies
12/01/2022, 3:34 PM@JvmInline value class MaxIntArray(val values: IntArray) {
constructor(size: Int) : this(IntArray(size))
operator fun plusAssign(v: Int) {
if(values.size == 1) { values[0] = maxOf(values[0], v) }
else values.indices.lastOrNull { v > values[it] }?.let { idx ->
repeat(idx) { values[it] = values[it + 1] }
values[idx] = v
}
}
}
fun List<String>.topElves(n: Int): Int {
val q = MaxIntArray(n)
var sum = 0
map(String::toIntOrNull).forEach {
if (it == null) q += sum
sum += it ?: -sum
}
return q.values.sum()
}
Michael de Kaste
12/01/2022, 3:36 PMtodd.ginsberg
12/01/2022, 3:37 PMMichael Böiers
12/01/2022, 3:56 PMfun day01SortedSet(input: String): List<Int> {
val top = TreeSet<Int>(reverseOrder())
for (elf in input.split("\n\n")) {
top += elf.lines().sumOf(String::toInt)
if (top.size > 3) top -= top.last()
}
return listOf(top.first(), top.sum())
}
Kevin Del Castillo
12/01/2022, 3:57 PMTreeSet
for my solutionphldavies
12/01/2022, 4:01 PMephemient
12/01/2022, 4:02 PMKevin Del Castillo
12/01/2022, 4:05 PMKevin Del Castillo
12/01/2022, 4:40 PMTreeSet
to use a List instead, now I'm actively looking for the place where the element should be inserted so it keeps the list sorted and of course avoids the issue with duplicated values.
• CodeDavid Whittaker
12/01/2022, 5:57 PMMichael Böiers
12/01/2022, 7:40 PMfun day01SortedSet(input: String): List<Int> {
class Food(val calories: Int)
val top = TreeSet(compareByDescending(Food::calories))
for (elf in input.split("\n\n")) {
top += Food(elf.lines().sumOf(String::toInt))
if (top.size > 3) top -= top.last()
}
return listOf(top.first().calories, top.sumOf { it.calories })
}
ephemient
12/01/2022, 9:48 PM.quickSelectDescending(2)
came out about 30% faster than .sorted().takeLast(3)
. it's a lot more code thoughephemient
12/01/2022, 9:52 PMTreeSet
treats the objects as identical and only keeps one, even if the objects aren't equal()
TreeSet(Comparator<Any> { _, _ -> 0 }).apply { addAll(listOf(1, 2, 3)) }.size == 1
Kevin Del Castillo
12/01/2022, 10:04 PMNeil Banman
12/01/2022, 10:41 PMNeil Banman
12/01/2022, 10:46 PMDavio
12/02/2022, 7:14 AMDan Fingal-Surma
12/02/2022, 7:27 AMMichael Böiers
12/02/2022, 7:31 AMMichael Böiers
12/02/2022, 7:32 AMfun day01MinMax(input: String): List<Int> {
val top = mutableListOf<Int>()
for (elf in input.split("\n\n")) {
top += elf.lines().sumOf(String::toInt)
if (top.size > 3) top -= top.min()
}
return listOf(top.max(), top.sum())
}
Dan Fingal-Surma
12/02/2022, 7:32 AMprintln(
lines.fold(0 to 0) { acc, value ->
if (value.isBlank()) {
0 to maxOf(acc.first, acc.second)
} else {
acc.first + value.toInt() to acc.second
}
}.second
)
Dan Fingal-Surma
12/02/2022, 7:42 AMval top = java.util.PriorityQueue<Int>()
for (elf in input.split("\n\n")) {
top += elf.lines().sumOf(String::toInt)
if (top.size > 3) top.poll()
}
return listOf(top.max(), top.sum())
Michael Böiers
12/02/2022, 7:47 AMDan Fingal-Surma
12/02/2022, 8:13 AMDan Fingal-Surma
12/02/2022, 8:14 AMDavio
12/02/2022, 8:22 AMgetInputAsSequence()
.split(String::isBlank)
.map { it.sumOf(String::toInt) }
.fold(intArrayOf(0, 0, 0)) { acc, element ->
if (element > acc[0]) {
if (element > acc[1]) {
acc[0] = acc[1]
if (element > acc[2]) {
acc[1] = acc[2]
acc[2] = element
} else {
acc[1] = element
}
} else {
acc[0] = element
}
}
println(acc.joinToString())
acc
}.sum()
.call { println(it) }
Davio
12/02/2022, 8:23 AMDavio
12/02/2022, 8:24 AMDavio
12/02/2022, 8:25 AMDavio
12/02/2022, 8:31 AMgetInputAsSequence()
.split(String::isBlank)
.map { it.sumOf(String::toInt) }
.fold(intArrayOf(0, 0, 0)) { acc, element ->
val indexToInsert = acc.indexOfLast { element > it }
if (indexToInsert > -1) {
(0 until indexToInsert).forEach { index ->
acc[index] = acc[index + 1]
}
acc[indexToInsert] = element
}
acc
}.sum()
.call { println(it) }
phldavies
12/02/2022, 8:55 AMindexOfLast
🙂Bence Blaskovics
12/13/2022, 5:25 PMKevin Del Castillo
12/13/2022, 5:27 PM\r\n
if I recall correctly, but I'm not 100% sure if that's the correct order or the other way around because I don't use that crappy OS for anything but gaming 😝Michael Böiers
12/13/2022, 5:28 PMBence Blaskovics
12/13/2022, 5:53 PMMichael Böiers
12/13/2022, 5:56 PMBence Blaskovics
12/13/2022, 6:14 PMKevin Del Castillo
12/13/2022, 6:18 PM\n
with \r\n
, not only one of those because you want to separate lines when there's a blank one, so you should be instead using \r\n\r\n
Bence Blaskovics
12/13/2022, 6:27 PMephemient
12/13/2022, 7:39 PM\n
-only line endings