Compare commits
8
Commits
bd591263f6
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cda0dccc65 | ||
|
|
5e031c27cc | ||
|
|
de3b0795e3 | ||
|
|
2190f9e1ac | ||
|
|
0192b33570 | ||
|
|
a69be406b1 | ||
|
|
7495f9e378 | ||
|
|
ccc3fdad4c |
+101
-1
@@ -1,4 +1,5 @@
|
|||||||
import java.lang.Long.numberOfTrailingZeros
|
import java.lang.Long.numberOfTrailingZeros
|
||||||
|
import java.math.BigInteger
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@@ -187,7 +188,106 @@ fun gcdPositive(aIn: Long, bIn: Long): Long {
|
|||||||
return a shl shift
|
return a shl shift
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calcPrimeFactorsAndPhi(n: Long, primes: MutableList<Long>, allPrimes: MutableSet<Long>): Pair<List<Pair<Long, Int>>, Long> {
|
// ax + by = gcdExtendedPositive(a, b)
|
||||||
|
fun extendedGcd(a: Long, b: Long): Pair<Long, Pair<Long, Long>> {
|
||||||
|
var old_r = a
|
||||||
|
var r = b
|
||||||
|
var old_s = 1L
|
||||||
|
var s = 0L
|
||||||
|
var old_t = 0L
|
||||||
|
var t = 1L
|
||||||
|
while (r != 0L) {
|
||||||
|
val q = old_r / r
|
||||||
|
val rtmp = old_r
|
||||||
|
old_r = r
|
||||||
|
r = rtmp - q * r
|
||||||
|
val stmp = old_s
|
||||||
|
old_s = s
|
||||||
|
s = stmp - q * s
|
||||||
|
val ttmp = old_t
|
||||||
|
old_t = t
|
||||||
|
t = ttmp - q * t
|
||||||
|
}
|
||||||
|
|
||||||
|
return old_r to (old_s to old_t)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun extendedGcd(a: BigInteger, b: BigInteger): Pair<BigInteger, Pair<BigInteger, BigInteger>> {
|
||||||
|
var old_r = a
|
||||||
|
var r = b
|
||||||
|
var old_s = BigInteger.ONE
|
||||||
|
var s = BigInteger.ZERO
|
||||||
|
var old_t = BigInteger.ZERO
|
||||||
|
var t = BigInteger.ONE
|
||||||
|
while (r != BigInteger.ZERO) {
|
||||||
|
val q = old_r / r
|
||||||
|
val rtmp = old_r
|
||||||
|
old_r = r
|
||||||
|
r = rtmp - q * r
|
||||||
|
val stmp = old_s
|
||||||
|
old_s = s
|
||||||
|
s = stmp - q * s
|
||||||
|
val ttmp = old_t
|
||||||
|
old_t = t
|
||||||
|
t = ttmp - q * t
|
||||||
|
}
|
||||||
|
|
||||||
|
return old_r to (old_s to old_t)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun extendedGcd(v: List<Long>): Pair<Long, List<Long>> {
|
||||||
|
if (v.size < 2) throw IllegalArgumentException("Expected at least 2 elements")
|
||||||
|
|
||||||
|
val gcds = ArrayList<Long>(v.size)
|
||||||
|
val coeffs = ArrayList<Long>(v.size)
|
||||||
|
var (gcd, p1) = extendedGcd(v[0], v[1])
|
||||||
|
coeffs.add(p1.first)
|
||||||
|
coeffs.add(p1.second)
|
||||||
|
gcds.add(gcd)
|
||||||
|
gcds.add(gcd)
|
||||||
|
for (i in 2 until v.size) {
|
||||||
|
val (gcdnew, pi) = extendedGcd(gcd, v[i])
|
||||||
|
gcd = gcdnew
|
||||||
|
coeffs.add(pi.second)
|
||||||
|
gcds.add(gcd)
|
||||||
|
}
|
||||||
|
for (i in gcds.indices) {
|
||||||
|
if (gcds[i] != gcd) {
|
||||||
|
coeffs[i] *= gcds[i] / gcd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gcd to coeffs
|
||||||
|
}
|
||||||
|
|
||||||
|
fun extendedGcdBigInteger(v: List<BigInteger>): Pair<BigInteger, List<BigInteger>> {
|
||||||
|
if (v.size < 2) throw IllegalArgumentException("Expected at least 2 elements")
|
||||||
|
|
||||||
|
val gcds = ArrayList<BigInteger>(v.size)
|
||||||
|
val coeffs = ArrayList<BigInteger>(v.size)
|
||||||
|
var (gcd, p1) = extendedGcd(v[0], v[1])
|
||||||
|
coeffs.add(p1.first)
|
||||||
|
coeffs.add(p1.second)
|
||||||
|
gcds.add(gcd)
|
||||||
|
gcds.add(gcd)
|
||||||
|
for (i in 2 until v.size) {
|
||||||
|
val (gcdnew, pi) = extendedGcd(gcd, v[i])
|
||||||
|
gcd = gcdnew
|
||||||
|
coeffs.add(pi.second)
|
||||||
|
gcds.add(gcd)
|
||||||
|
}
|
||||||
|
for (i in gcds.indices) {
|
||||||
|
if (gcds[i] != gcd) {
|
||||||
|
coeffs[i] *= gcds[i] / gcd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gcd to coeffs
|
||||||
|
}
|
||||||
|
|
||||||
|
fun calcPrimeFactorsAndPhi(
|
||||||
|
n: Long,
|
||||||
|
primes: MutableList<Long>,
|
||||||
|
allPrimes: MutableSet<Long>
|
||||||
|
): Pair<List<Pair<Long, Int>>, Long> {
|
||||||
val factors = ArrayList<Pair<Long, Int>>()
|
val factors = ArrayList<Pair<Long, Int>>()
|
||||||
var phi = 1L
|
var phi = 1L
|
||||||
var rem = n
|
var rem = n
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ Prize: X=18641, Y=10279
|
|||||||
|
|
||||||
// Linear Diophantine equations
|
// Linear Diophantine equations
|
||||||
/* The simplest linear Diophantine equation takes the form
|
/* The simplest linear Diophantine equation takes the form
|
||||||
a*x + b*x = c
|
a*x + b*y = c
|
||||||
where a, b and c are given integers.
|
where a, b and c are given integers.
|
||||||
The solutions are described by the following theorem:
|
The solutions are described by the following theorem:
|
||||||
This Diophantine equation has a solution (where x and y are integers),
|
This Diophantine equation has a solution (where x and y are integers),
|
||||||
|
|||||||
+59
-117
@@ -1,9 +1,14 @@
|
|||||||
package aoc2025
|
package aoc2025
|
||||||
|
|
||||||
|
import chineseRemainder
|
||||||
|
import extendedGcdBigInteger
|
||||||
|
import primeFactors
|
||||||
|
import primeSequence
|
||||||
import println
|
import println
|
||||||
import readInput
|
import readInput
|
||||||
|
import sieveOfErastosthenes
|
||||||
import splitInts
|
import splitInts
|
||||||
import java.util.*
|
import java.math.BigInteger
|
||||||
|
|
||||||
/*
|
/*
|
||||||
--- Day 10: Factory ---
|
--- Day 10: Factory ---
|
||||||
@@ -29,7 +34,6 @@ fun main() {
|
|||||||
val toggles =
|
val toggles =
|
||||||
stuff.drop(1).dropLast(1)
|
stuff.drop(1).dropLast(1)
|
||||||
.map { it.removeSurrounding("(", ")").splitInts(",").fold(0) { acc, v -> acc + (1 shl v) } }
|
.map { it.removeSurrounding("(", ")").splitInts(",").fold(0) { acc, v -> acc + (1 shl v) } }
|
||||||
.sortedByDescending { it.countOneBits() }
|
|
||||||
.toIntArray()
|
.toIntArray()
|
||||||
val joltages = stuff.last().removeSurrounding("{", "}").splitInts(",").toIntArray()
|
val joltages = stuff.last().removeSurrounding("{", "}").splitInts(",").toIntArray()
|
||||||
machines.add(Machine(machSize, target, toggles, joltages))
|
machines.add(Machine(machSize, target, toggles, joltages))
|
||||||
@@ -41,138 +45,76 @@ fun main() {
|
|||||||
val machines = parse(input)
|
val machines = parse(input)
|
||||||
var sumButts = 0
|
var sumButts = 0
|
||||||
for (m in machines) {
|
for (m in machines) {
|
||||||
val pq = LinkedList<Pair<Int, Int>>()
|
// look at which different possible sets of toggles need to be pressed to result in the target number
|
||||||
val killArray = BooleanArray(1 shl m.size)
|
// pressing an even time will cancel out the effect, so only look what happens if you press once
|
||||||
pq.add(0 to 0)
|
var minPresses = Int.MAX_VALUE
|
||||||
out@ while (pq.isNotEmpty()) {
|
for (tm in 1 until (1 shl m.toggles.size)) {
|
||||||
val (v, bi) = pq.poll()
|
val odds = m.toggles.filterIndexed { i, v -> (1 shl i) and tm != 0 }
|
||||||
for (t in m.toggles) {
|
val result = odds.fold(0) { acc, iv -> acc xor iv }
|
||||||
val nv = v xor t
|
if (result == m.target) {
|
||||||
if (nv == m.target) {
|
minPresses = minPresses.coerceAtMost(odds.size)
|
||||||
sumButts += bi + 1
|
|
||||||
break@out
|
|
||||||
}
|
|
||||||
if (!killArray[nv]) {
|
|
||||||
killArray[v] = true
|
|
||||||
pq.add(nv to bi + 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sumButts += minPresses
|
||||||
}
|
}
|
||||||
return sumButts
|
return sumButts
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Toggle(val idx: Int, val v: Int, var min: Int = 0, var max: Int = Int.MAX_VALUE)
|
|
||||||
|
|
||||||
fun applyJoltage(jolts: IntArray, toggle: Toggle, times: Int = 1): Boolean {
|
|
||||||
var tt = toggle.v
|
|
||||||
var jp = 0
|
|
||||||
var valid = true
|
|
||||||
while (tt != 0) {
|
|
||||||
if (tt and 1 != 0) {
|
|
||||||
jolts[jp] -= times
|
|
||||||
if (jolts[jp] < 0) {
|
|
||||||
valid = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tt = tt shr 1
|
|
||||||
jp++
|
|
||||||
}
|
|
||||||
return valid
|
|
||||||
}
|
|
||||||
|
|
||||||
fun findMaxButtonPresses(jolts: IntArray, toggle: Toggle): Int {
|
|
||||||
var tt = toggle.v
|
|
||||||
var jp = 0
|
|
||||||
val maxPresses = Int.MAX_VALUE
|
|
||||||
while (tt != 0) {
|
|
||||||
if (tt and 1 != 0) {
|
|
||||||
maxPresses.coerceAtMost(jolts[jp] / 2)
|
|
||||||
}
|
|
||||||
tt = tt shr 1
|
|
||||||
jp++
|
|
||||||
}
|
|
||||||
return maxPresses
|
|
||||||
}
|
|
||||||
|
|
||||||
fun part2(input: List<String>): Int {
|
fun part2(input: List<String>): Int {
|
||||||
val machines = parse(input)
|
val machines = parse(input)
|
||||||
|
|
||||||
|
val sieve = sieveOfErastosthenes(10000)
|
||||||
|
val primes = primeSequence(sieve).take(500).toList()
|
||||||
var sumButts = 0
|
var sumButts = 0
|
||||||
for (m in machines) {
|
for (m in machines) {
|
||||||
// generate toggles and calculate the global maximum of toggle presses for this toggle
|
println()
|
||||||
val toggles = m.toggles.mapIndexed { i, t ->
|
val maxJoltage = m.joltage.max()
|
||||||
Toggle(i,
|
val numBits = 32 - maxJoltage.countLeadingZeroBits()
|
||||||
t,
|
val bigTarget = m.joltage.foldIndexed(BigInteger.ZERO) { index, acc, i ->
|
||||||
max = IntRange(0, m.size).filter { b -> t and (1 shl b) != 0 }.minOf { m.joltage[it] })
|
acc.plus(
|
||||||
}
|
BigInteger.valueOf(i.toLong()).shiftLeft(numBits * index)
|
||||||
// try to calculate a minimum number of toggle presses as the joltage needs to be reached exactly
|
|
||||||
val subsets = Array(m.size) { toggles.filter { v -> (1 shl it) and v.v != 0 }.toTypedArray() }
|
|
||||||
for (v in toggles) {
|
|
||||||
var minT = 0
|
|
||||||
for (b in 0 until m.size) {
|
|
||||||
var rj = m.joltage[b]
|
|
||||||
var found = false
|
|
||||||
for (s in subsets[b]) {
|
|
||||||
if (s === v) {
|
|
||||||
found = true
|
|
||||||
} else {
|
|
||||||
rj -= s.max
|
|
||||||
if (rj < 0) break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found) minT = minT.coerceAtLeast(rj)
|
|
||||||
}
|
|
||||||
if (minT > v.max) throw IllegalStateException()
|
|
||||||
v.min = minT
|
|
||||||
}
|
|
||||||
|
|
||||||
// iterate over the possible odd sets
|
|
||||||
var minPushes = Int.MAX_VALUE
|
|
||||||
val jolts = m.joltage.copyOf()
|
|
||||||
val pressCount = IntArray(m.toggles.size)
|
|
||||||
|
|
||||||
// press all buttons regarding their minimal count (if any)
|
|
||||||
for (t in toggles) {
|
|
||||||
if (pressCount[t.idx] + t.min > t.max || !applyJoltage(
|
|
||||||
jolts,
|
|
||||||
t,
|
|
||||||
times = t.min
|
|
||||||
)
|
)
|
||||||
) throw IllegalStateException()
|
|
||||||
pressCount[t.idx] += t.min
|
|
||||||
}
|
}
|
||||||
// this is the starting point for the exhaustive search
|
val bigToggles = ArrayList<BigInteger>()
|
||||||
val pq = PriorityQueue(compareBy<Pair<IntArray, IntArray>> { it.second.sum() })
|
for (t in m.toggles) {
|
||||||
pq.add(jolts to pressCount)
|
var tt = t
|
||||||
while (pq.isNotEmpty()) {
|
var bigToggle = BigInteger.ZERO
|
||||||
val (j, tc) = pq.poll()
|
var shift = 0
|
||||||
val pushes = tc.sum()
|
while (tt > 0) {
|
||||||
if (pushes >= minPushes) break
|
if (tt and 1 != 0) {
|
||||||
// if the joltage has counted down to zero, we're done
|
bigToggle += BigInteger.ONE.shiftLeft(shift)
|
||||||
if (j.sum() == 0) {
|
}
|
||||||
minPushes = pushes
|
shift += numBits
|
||||||
|
tt = tt shr 1
|
||||||
|
}
|
||||||
|
bigToggles.add(bigToggle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// j0 * bigtoggle[0] + j1 * bigtoggle[1] + ... = bigTarget
|
||||||
|
// is a Linear Diophantine equation that can be solved with the extended Euclidean algorithm
|
||||||
|
|
||||||
|
val (gcd, coeffients) = extendedGcdBigInteger(bigToggles)
|
||||||
|
if (bigTarget % gcd != BigInteger.ZERO) throw IllegalStateException()
|
||||||
|
|
||||||
|
val factorMap = HashMap<Long, Long>()
|
||||||
|
var good = true
|
||||||
|
val primeFactors = primeFactors(bigTarget.toLong(), sieve)
|
||||||
|
for (pf in primeFactors) {
|
||||||
|
val sf = factorMap[pf]
|
||||||
|
val pr = 1000 % pf
|
||||||
|
if (sf != null && sf != pr) {
|
||||||
|
good = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
for (t in toggles) {
|
factorMap[pf] = pr
|
||||||
if (tc[t.idx] + 2 <= t.max) {
|
|
||||||
val maxTimes = findMaxButtonPresses(j, t)
|
|
||||||
if (maxTimes > 0) {
|
|
||||||
val nj = j.copyOf()
|
|
||||||
if (applyJoltage(nj, t, maxTimes)) {
|
|
||||||
val ntc = tc.copyOf()
|
|
||||||
ntc[t.idx] += maxTimes
|
|
||||||
pq.add(nj to ntc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println("$minPushes")
|
|
||||||
sumButts += minPushes
|
|
||||||
}
|
}
|
||||||
|
val reducedPairs = factorMap.map { it.value to it.key }.sortedBy { it.second }
|
||||||
|
val rx = reducedPairs.chineseRemainder()
|
||||||
|
|
||||||
|
val leastFingers = 0
|
||||||
|
println(leastFingers)
|
||||||
|
sumButts += leastFingers
|
||||||
|
}
|
||||||
return sumButts
|
return sumButts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package aoc2025
|
||||||
|
|
||||||
|
import println
|
||||||
|
import readInput
|
||||||
|
|
||||||
|
/*
|
||||||
|
--- Day 11: Reactor ---
|
||||||
|
https://adventofcode.com/2025/day/11
|
||||||
|
*/
|
||||||
|
fun main() {
|
||||||
|
|
||||||
|
val inlineTestInput = """
|
||||||
|
aaa: you hhh
|
||||||
|
you: bbb ccc
|
||||||
|
bbb: ddd eee
|
||||||
|
ccc: ddd eee fff
|
||||||
|
ddd: ggg
|
||||||
|
eee: out
|
||||||
|
fff: out
|
||||||
|
ggg: out
|
||||||
|
hhh: ccc fff iii
|
||||||
|
iii: out
|
||||||
|
"""
|
||||||
|
|
||||||
|
val inlineTestInput2 = """
|
||||||
|
svr: aaa bbb
|
||||||
|
aaa: fft
|
||||||
|
fft: ccc
|
||||||
|
bbb: tty
|
||||||
|
tty: ccc
|
||||||
|
ccc: ddd eee
|
||||||
|
ddd: hub
|
||||||
|
hub: fff
|
||||||
|
eee: dac
|
||||||
|
dac: fff
|
||||||
|
fff: ggg hhh
|
||||||
|
ggg: out
|
||||||
|
hhh: out
|
||||||
|
"""
|
||||||
|
|
||||||
|
fun parseInput(input: List<String>): HashMap<String, MutableSet<String>> {
|
||||||
|
val children = HashMap<String, MutableSet<String>>()
|
||||||
|
for (i in input) {
|
||||||
|
val (n, chs) = i.split(": ")
|
||||||
|
val ch = chs.split(" ")
|
||||||
|
children.getOrPut(n) { HashSet() }.addAll(ch)
|
||||||
|
}
|
||||||
|
return children
|
||||||
|
}
|
||||||
|
|
||||||
|
fun rec(
|
||||||
|
children: HashMap<String, MutableSet<String>>,
|
||||||
|
p: String,
|
||||||
|
stop: String,
|
||||||
|
visited: MutableSet<String> = HashSet(),
|
||||||
|
memo: HashMap<String, Long> = HashMap()
|
||||||
|
): Long {
|
||||||
|
if (p == stop) return 1L
|
||||||
|
return memo.getOrPut(p) {
|
||||||
|
visited.add(p)
|
||||||
|
val res = children[p]?.sumOf { rec(children, it, stop, visited, memo) } ?: 0L
|
||||||
|
visited.remove(p)
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun part1(input: List<String>): Long {
|
||||||
|
return rec(parseInput(input), "you", "out")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun part2(input: List<String>): Long {
|
||||||
|
val children = parseInput(input)
|
||||||
|
|
||||||
|
val srvToDac = rec(children, "svr", "dac")
|
||||||
|
val dacToFft = rec(children, "dac", "fft")
|
||||||
|
val fftToOut = rec(children, "fft", "out")
|
||||||
|
val srvToFft = rec(children, "svr", "fft")
|
||||||
|
val fftToDac = rec(children, "fft", "dac")
|
||||||
|
val dacToOut = rec(children, "dac", "out")
|
||||||
|
|
||||||
|
return srvToDac * dacToFft * fftToOut + srvToFft * fftToDac * dacToOut
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if implementation meets criteria from the description, like:
|
||||||
|
val testInput = inlineTestInput.trim().reader().readLines()
|
||||||
|
val testInput2 = inlineTestInput2.trim().reader().readLines()
|
||||||
|
//val testInput = readInput("aoc2025/Day11_test")
|
||||||
|
val testInputPart1Result = part1(testInput)
|
||||||
|
println("Part 1 Test: $testInputPart1Result")
|
||||||
|
val testInputPart2Result = part2(testInput2)
|
||||||
|
println("Part 2 Test: $testInputPart2Result")
|
||||||
|
check(testInputPart1Result == 5L)
|
||||||
|
check(testInputPart2Result == 2L)
|
||||||
|
|
||||||
|
val input = readInput("aoc2025/Day11")
|
||||||
|
part1(input).println()
|
||||||
|
part2(input).println()
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
package aoc2025
|
||||||
|
|
||||||
|
import CharGrid
|
||||||
|
import println
|
||||||
|
import readInput
|
||||||
|
import splitInts
|
||||||
|
|
||||||
|
/*
|
||||||
|
--- Day 12: Christmas Tree Farm ---
|
||||||
|
https://adventofcode.com/2025/day/12
|
||||||
|
*/
|
||||||
|
fun main() {
|
||||||
|
|
||||||
|
val inlineTestInput = """
|
||||||
|
0:
|
||||||
|
###
|
||||||
|
##.
|
||||||
|
##.
|
||||||
|
|
||||||
|
1:
|
||||||
|
###
|
||||||
|
##.
|
||||||
|
.##
|
||||||
|
|
||||||
|
2:
|
||||||
|
.##
|
||||||
|
###
|
||||||
|
##.
|
||||||
|
|
||||||
|
3:
|
||||||
|
##.
|
||||||
|
###
|
||||||
|
##.
|
||||||
|
|
||||||
|
4:
|
||||||
|
###
|
||||||
|
#..
|
||||||
|
###
|
||||||
|
|
||||||
|
5:
|
||||||
|
###
|
||||||
|
.#.
|
||||||
|
###
|
||||||
|
|
||||||
|
4x4: 0 0 0 0 2 0
|
||||||
|
12x5: 1 0 1 0 2 2
|
||||||
|
12x5: 1 0 1 0 3 2
|
||||||
|
"""
|
||||||
|
|
||||||
|
fun fits(grid: LongArray, x: Int, y: Int, present: Long) =
|
||||||
|
(grid[y] or ((7L and present) shl x) == grid[y]) &&
|
||||||
|
(grid[y + 1] or ((7L and (present shr 3)) shl x) == grid[y + 1]) &&
|
||||||
|
(grid[y + 2] or ((7L and (present shr 6)) shl x) == grid[y + 2])
|
||||||
|
|
||||||
|
fun part1(input: List<String>): Int {
|
||||||
|
var lp = 0
|
||||||
|
val presents = ArrayList<IntArray>()
|
||||||
|
// nothing of this stuff is needed :-(
|
||||||
|
while (!input[lp].contains("x")) {
|
||||||
|
var charGrid = CharGrid(input.subList(lp + 1, lp + 4))
|
||||||
|
lp += 5
|
||||||
|
|
||||||
|
val setRot = HashSet<Int>()
|
||||||
|
for (r in 0..7) {
|
||||||
|
val present = charGrid.generateGridPos().foldIndexed(0) { index, acc, pos -> acc + (if (charGrid[pos] == '#') (1 shl index) else 0) }
|
||||||
|
setRot.add(present)
|
||||||
|
if (r != 3) {
|
||||||
|
// rotate
|
||||||
|
val newGrid = charGrid.copyOf()
|
||||||
|
newGrid.generateGridPos().forEach { (dc, dr) -> newGrid[2 - dr, dc] = charGrid[dc, dr] }
|
||||||
|
charGrid = newGrid
|
||||||
|
} else {
|
||||||
|
// flip
|
||||||
|
val newGrid = charGrid.copyOf()
|
||||||
|
newGrid.generateGridPos().forEach { (dc, dr) -> newGrid[2 - dc, dr] = charGrid[dc, dr] }
|
||||||
|
charGrid = newGrid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
presents.add(setRot.toIntArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
var fitted = 0
|
||||||
|
val presentSizes = presents.map { it[0].countOneBits() }.toIntArray()
|
||||||
|
|
||||||
|
for (p in lp until input.size) {
|
||||||
|
val (dim, pl) = input[p].split(": ")
|
||||||
|
val (width, height) = dim.splitInts("x")
|
||||||
|
val placements = pl.splitInts().toIntArray()
|
||||||
|
val totalSize = placements.mapIndexed { i, v -> v * presentSizes[i] }.sum()
|
||||||
|
if (totalSize > width * height) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val totalPresents = placements.sum()
|
||||||
|
// just assume it will fit if there is enough area
|
||||||
|
if (totalPresents * 9 <= width * height) {
|
||||||
|
fitted++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Oh no!")
|
||||||
|
// here the hard part would have started, but except for the example input,
|
||||||
|
// it never gets here
|
||||||
|
//val grid = LongArray(height) { (1L shl width) - 1L }
|
||||||
|
}
|
||||||
|
return fitted
|
||||||
|
}
|
||||||
|
|
||||||
|
fun part2(input: List<String>): Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if implementation meets criteria from the description, like:
|
||||||
|
val testInput = inlineTestInput.trim().reader().readLines()
|
||||||
|
//val testInput = readInput("aoc2025/Day12_test")
|
||||||
|
val testInputPart1Result = part1(testInput)
|
||||||
|
println("Part 1 Test: $testInputPart1Result")
|
||||||
|
val testInputPart2Result = part2(testInput)
|
||||||
|
println("Part 2 Test: $testInputPart2Result")
|
||||||
|
//check(testInputPart1Result == 2)
|
||||||
|
check(testInputPart2Result == 0)
|
||||||
|
|
||||||
|
val input = readInput("aoc2025/Day12")
|
||||||
|
part1(input).println()
|
||||||
|
part2(input).println()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user