Advent of Code 2022 day 4
12/04/2023, 5:00 AMMarcin Wisniowski
12/04/2023, 5:40 AMMarcin Wisniowski
12/04/2023, 5:40 AMMarcin Wisniowski
12/04/2023, 5:41 AMJakub Gwóźdź
12/04/2023, 5:43 AMJakub Gwóźdź
12/04/2023, 5:45 AMNorbert Kiesel
12/04/2023, 5:46 AMcards.forEachIndexed { index, card ->
(1..card.wins).forEach { cards[index + it].count += card.count }
}
return cards.sumOf { it.count }
Jakub Gwóźdź
12/04/2023, 5:47 AMNorbert Kiesel
12/04/2023, 5:48 AMclass Card(val wins: Int, var count: Int = 1)
But yeah, sometimes use mutable data classes as wellJakub Gwóźdź
12/04/2023, 5:52 AMfun String.ints() = split(" ").map { it.toInt() }
which failed on ...65 6 55...
and required additional `.filterNot { it.isBlank() }`…Michael de Kaste
12/04/2023, 5:52 AMobject Day4 : Challenge() {
private val parsed = input.lines().map { line ->
line.split("\\D+".toRegex()).drop(1).map(String::toInt).let { numbers ->
numbers.subList(1, 11).intersect(numbers.subList(11, 36).toSet()).indices
}
}
override fun part1() = parsed.sumOf { 1.shl(it.last + 1) }
override fun part2() = IntArray(parsed.size) { 1 }.apply {
parsed.forEachIndexed { index, winningNumbers ->
winningNumbers.forEach {
this[index + it + 1] += this[index]
}
}
}.sum()
}
Norbert Kiesel
12/04/2023, 5:55 AMwinning
and mine
properties, but then saw that we just need the size of the intersection. And my "extract numbers" is
fun nums(line: String) = Regex("""\d+""").findAll(line).map { it.value.toInt() }.toSet()
Michael de Kaste
12/04/2023, 5:56 AMNorbert Kiesel
12/04/2023, 5:56 AMsplit(Regex(" +"))
to avoid the filterJonathan Kolberg
12/04/2023, 5:57 AMDan Fingal-Surma
12/04/2023, 5:59 AMJakub Gwóźdź
12/04/2023, 6:04 AMDan Fingal-Surma
12/04/2023, 6:06 AMshl
instead of using pow
Michael Böiers
12/04/2023, 6:08 AMDan Fingal-Surma
12/04/2023, 6:09 AMMutableList(lines.size) { 1 }
, that’s what I was looking forDan Fingal-Surma
12/04/2023, 6:20 AMDan Fingal-Surma
12/04/2023, 6:20 AMJakub Gwóźdź
12/04/2023, 6:21 AMJakub Gwóźdź
12/04/2023, 6:22 AMPeter Duong
12/04/2023, 6:24 AMephemient
12/04/2023, 6:26 AMrunningFold
pushing the counts forward, but simplified it down to a single mutable array of countsDan Fingal-Surma
12/04/2023, 6:36 AMNorbert Kiesel
12/04/2023, 6:44 AMJakub Gwóźdź
12/04/2023, 6:45 AMvar
, it’s not too functional yet, but there is an opportunity to introduce fold
instead. (Although it will be probably less optimal)Jakub Gwóźdź
12/04/2023, 6:52 AMmaiatoday
12/04/2023, 7:14 AMDavio
12/04/2023, 7:17 AMDavio
12/04/2023, 7:18 AMfun getScore(): Int = 2.0.pow(myNumbers.intersect(winningNumbers).size - 1).toInt()
y9san9
12/04/2023, 7:38 AMritesh
12/04/2023, 7:53 AMPotatoboy
12/04/2023, 7:54 AMDavio
12/04/2023, 7:58 AMoverride fun part2(): Int {
val totalCopies = cards.associateWith { 1 }.toMutableMap()
totalCopies.forEach { (card, total) ->
val idsOfCopies = card.getIdsOfCopies()
idsOfCopies.forEach { id ->
val copy = Card(id)
totalCopies[copy] = totalCopies.getValue(copy) + total
}
}
return totalCopies.values.sum()
}
This just keeps a running count of number of copies of each card, starting with 1.
As the table is scanned from top to bottom, we only have to increase the running totals of the IDs that match. So in the example, #1 has 4 winning numbers, so we increase the totals of cards 2, 3, 4 and 5. Then we get to #2 and see it has 2 copies so we need to increase the winning cards ID totals with 2, etcphldavies
12/04/2023, 8:00 AMIntArray
to track copies as a map felt overkill.
year 2023 day 4 part 1
Default took 488.366us (1.00x): 23673
year 2023 day 4 part 2
Default took 402.9us (1.00x): 12263631
> note: this was missing a .filter { it > 0 }
in part 1, however I ended up with an even number of non-winning cards which resulted in an even number of 1 shl -1 == Int.MIN_VALUE
which summed to 0 and didn't impact my resulty9san9
12/04/2023, 8:03 AMxxfast
12/04/2023, 8:05 AMDavio
12/04/2023, 8:14 AMsetA.count { setB.contains(it) (or it in setB) }
, but I quite like setA.intersect(setB).size
it might not be optimal as we don't really need a new set, only the number of matches, but it's a fun and straightforward way to get itJakub Gwóźdź
12/04/2023, 8:22 AMvar
, any side effect, just map
and fold
, and yes it is.
following is the excerpt, sans boring parsing:
The interesting thing in part2 is, I pass only the important data in fold’s accumulator, immediately forgetting about the copies of cards already calculated. I believe it’s pretty optimized now
EDIT: Fixed mistake discussed belowDavio
12/04/2023, 8:44 AMDavio
12/04/2023, 8:45 AMDavio
12/04/2023, 8:52 AM1 shl -1
returns Int.MIN_VALUE
?Jakub Gwóźdź
12/04/2023, 9:00 AM1 shl -1
is basically 1 / 2 => 0
Jakub Gwóźdź
12/04/2023, 9:00 AMMichael de Kaste
12/04/2023, 9:00 AMMichael de Kaste
12/04/2023, 9:01 AMJakub Gwóźdź
12/04/2023, 9:01 AMJakub Gwóźdź
12/04/2023, 9:01 AMphldavies
12/04/2023, 9:02 AM.filter { it > 0 }
when refactoring and didn't notice as my answer came out the same.phldavies
12/04/2023, 9:05 AMInt.MIN_VALUE
an even number of times, which ends up overflowing to 0
PoisonedYouth
12/04/2023, 9:06 AMDavio
12/04/2023, 9:08 AMJakub Gwóźdź
12/04/2023, 9:12 AMphldavies
12/04/2023, 9:13 AMJaap Beetstra
12/04/2023, 9:18 AMRafs
12/04/2023, 9:23 AMJakub Gwóźdź
12/04/2023, 9:33 AM1 shl -1
, I thought it will be equivalent of 1 shr 1 => 0
, while the docs clearly say:
Note that only the five lowest-order bits of the bitCount are used as the shift distance. The shift distance actually used is therefore always in the range 0..31.and 5 lowest-order bits of -1 (
0b11111111111111111111111111111111
) equal to 31. now 1 shl 31
is effing far from 1 shr 1
😆Davio
12/04/2023, 9:38 AMphldavies
12/04/2023, 9:39 AM(1 shl 31) + (1 shl 31) == 0
😄 so either Eric was feeling generous and always included multiples of 2 non-winning cards or 50/50 luck 😉Rafs
12/04/2023, 9:45 AMPaul Woitaschek
12/04/2023, 9:47 AMphldavies
12/04/2023, 9:47 AMDavio
12/04/2023, 9:47 AMJakub Gwóźdź
12/04/2023, 9:51 AMAnirudh
12/04/2023, 11:09 AMCard = List<Int>
(but that feels like we're lying about how we did it for part 1 😂 )Anirudh
12/04/2023, 11:13 AMPaul Woitaschek
12/04/2023, 11:18 AM@Test
fun part1() {
Day4.solvePart1() shouldBeExactly 25174
}
@Test
fun part1TestInput() {
Day4.solvePart1(testInput) shouldBeExactly 13
}
@Test
fun part2() {
Day4.solvePart2() shouldBeExactly 6420979
}
@Test
fun part2TestInput() {
Day4.solvePart2(testInput) shouldBeExactly 30
}
phldavies
12/04/2023, 11:19 AMDavio
12/04/2023, 11:40 AMphldavies
12/04/2023, 11:41 AMDavio
12/04/2023, 11:41 AMDavio
12/04/2023, 11:42 AMphldavies
12/04/2023, 11:43 AM402.9us
(after warming up the VM, ~1.3ms
cold)Davio
12/04/2023, 11:56 AMDavio
12/04/2023, 11:57 AMval contents = StringSelection(result.toString())
Toolkit.getDefaultToolkit().systemClipboard.setContents(contents, null)
for those that are interested...Jakub Gwóźdź
12/04/2023, 11:58 AMTolly Kulczycki
12/04/2023, 12:40 PMShahad H.
12/04/2023, 12:41 PMStefano Sansone
12/04/2023, 12:59 PMintersect
fun main() {
val cards = readInput("Day04")
val cardsInfo = buildList {
cards.forEach { card ->
val (winningNumbers, myNumbers) = card.split(":").last().split("|")
.map { it.trim().split("\\s+".toRegex()).map(String::toInt) }
val count = winningNumbers.count { it in myNumbers }
add(Pair(count, 1))
}
}.toMutableList()
cardsInfo.forEachIndexed { index, pair ->
(index + 1 until index + pair.first + 1).forEach { i ->
cardsInfo[i] = cardsInfo[i].copy(second = cardsInfo[i].second + pair.second)
}
}
println("Part 1 answer: ${cardsInfo.sumOf { (count, _) -> if (count == 0) 0 else 1 shl (count - 1) }}")
println("Part 2 answer: ${cardsInfo.sumOf { it.second }}")
}
Ozioma Ogbe
12/04/2023, 1:11 PMKotlin
val input = File("input1.txt").readText()
val lines = input.split("\n").dropLast(1).map {
it.split(": ")[1].trim()
}
fun main() {
println(lines.mapIndexed { index, s ->
val sum= processLinePart2(s, index)
sum
}.sum())
}
val cache = mutableMapOf<Int, Int>()
fun processLinePart2(line: String, lineNumber: Int): Int {
cache[lineNumber]?.let { return it }
cache[lineNumber] =
getMatchingCardForLine(line).let { numberOfMatchingCards ->
1 + (lineNumber + 1..lineNumber + numberOfMatchingCards).sumOf {
processLinePart2(lines[it], it)
}
}
return cache[lineNumber]!!
}
fun processLinePart1(line: String, lineNumber: Int): Int {
getMatchingCardForLine(line).let {numberOfMatchingCards ->
return 2.0.pow(numberOfMatchingCards.toDouble()-1).toInt()
}
}
fun getMatchingCardForLine(line: String): Int {
return line.split(" | ").let {
it[0].trim().split(Regex("\\s+"))
.map { it.trim().toInt() }.toSet()
.intersect(it[1].trim().split(Regex("\\s+")).map { it.trim().toInt() }.toSet()).size
}
}
Anirudh
12/04/2023, 1:12 PMdid everyone get the same card count in their puzzle input?
I got 204I meant number of cards in the input aka rows 🙂
Now I'm curious about the biggest winner 😄not me then. puzzle answer was only 5,744,979
Jakub Gwóźdź
12/04/2023, 1:18 PMCharles Flynn
12/04/2023, 2:26 PMGrzegorz Aniol
12/04/2023, 3:33 PMNeil Banman
12/04/2023, 5:58 PMTolly Kulczycki
12/04/2023, 8:20 PMDmitry Kandalov
12/04/2023, 9:35 PMfun main() {
File("src/_2023/day4/input.txt")
.readLines()
.sumOf { line ->
val tokens = line.split(Regex(" +")).drop(2)
val winningNumbers = tokens.takeWhile { it != "|" }.map { it.toInt() }
val numbers = tokens.takeLastWhile { it != "|" }.map { it.toInt() }
val count = winningNumbers.count { it in numbers }
2.0.pow(count - 1).toInt()
}
.printed()
}
Dmitry Kandalov
12/04/2023, 9:35 PMfun main() {
File("src/_2023/day4/input.txt")
.readLines()
.map { line ->
val tokens = line.split(Regex(" +")).drop(2)
val winningNumbers = tokens.takeWhile { it != "|" }.map { it.toInt() }
val numbers = tokens.takeLastWhile { it != "|" }.map { it.toInt() }
winningNumbers.count { it in numbers }
}
.reversed()
.fold(emptyList<Int>()) { acc, winCount ->
val count = 1 + (0..<winCount).sumOf { acc[it] }
listOf(count) + acc
}
.sum()
.printed()
}
joney
12/04/2023, 10:45 PMNeil Banman
12/05/2023, 12:16 AMAnirudh
12/05/2023, 3:59 AMsumOf { ... 2.0.pow(count - 1).toInt() }
over sumOf { ... 2.0.pow(count - 1) }.toInt()
is that having an inner .toInt()
converts all the 0.5's to 0's for 2.0.pow(-1)
so we then don't need a count == 0
check 👏ephemient
12/05/2023, 4:01 AM1 shl count shr 1
doesn't need floating point and doesn't need an == 0
check