Non working solution before I re-read the instructions regarding the light diagrams to be ignored for part 2.
This commit is contained in:
parent
6299b10b85
commit
4982f2cb3c
@ -24,9 +24,11 @@ fun main() {
|
|||||||
for (i in input) {
|
for (i in input) {
|
||||||
val stuff = i.split(" ")
|
val stuff = i.split(" ")
|
||||||
val machSize = stuff[0].length - 2
|
val machSize = stuff[0].length - 2
|
||||||
val target = stuff[0].removeSurrounding("[", "]").foldIndexed(0) { i, acc, ch -> acc + if (ch == '#') (1 shl i) else 0 }
|
val target = stuff[0].removeSurrounding("[", "]")
|
||||||
|
.foldIndexed(0) { i, acc, ch -> acc + if (ch == '#') (1 shl i) else 0 }
|
||||||
val toggles =
|
val toggles =
|
||||||
stuff.drop(1).dropLast(1).map { it.removeSurrounding("(", ")").splitInts(",").fold(0) { acc, v -> acc + (1 shl v) } }
|
stuff.drop(1).dropLast(1)
|
||||||
|
.map { it.removeSurrounding("(", ")").splitInts(",").fold(0) { acc, v -> acc + (1 shl v) } }
|
||||||
.sortedByDescending { it.countOneBits() }
|
.sortedByDescending { it.countOneBits() }
|
||||||
.toIntArray()
|
.toIntArray()
|
||||||
val joltages = stuff.last().removeSurrounding("{", "}").splitInts(",").toIntArray()
|
val joltages = stuff.last().removeSurrounding("{", "}").splitInts(",").toIntArray()
|
||||||
@ -39,19 +41,19 @@ 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 = PriorityQueue<Pair<Int, Int>>(compareBy { it.second })
|
val pq = LinkedList<Pair<Int, Int>>()
|
||||||
val killSet = HashSet<Int>()
|
val killArray = BooleanArray(1 shl m.size)
|
||||||
pq.add(0 to 0)
|
pq.add(0 to 0)
|
||||||
while (pq.isNotEmpty()) {
|
out@ while (pq.isNotEmpty()) {
|
||||||
val (v, bi) = pq.poll()
|
val (v, bi) = pq.poll()
|
||||||
if (v == m.target) {
|
|
||||||
sumButts += bi
|
|
||||||
break
|
|
||||||
}
|
|
||||||
killSet.add(v)
|
|
||||||
for (t in m.toggles) {
|
for (t in m.toggles) {
|
||||||
val nv = v xor t
|
val nv = v xor t
|
||||||
if (!killSet.contains(nv)) {
|
if (nv == m.target) {
|
||||||
|
sumButts += bi + 1
|
||||||
|
break@out
|
||||||
|
}
|
||||||
|
if (!killArray[nv]) {
|
||||||
|
killArray[v] = true
|
||||||
pq.add(nv to bi + 1)
|
pq.add(nv to bi + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,32 +62,16 @@ fun main() {
|
|||||||
return sumButts
|
return sumButts
|
||||||
}
|
}
|
||||||
|
|
||||||
fun part2(input: List<String>): Int {
|
data class Toggle(val idx: Int, val v: Int, var min: Int = 0, var max: Int = Int.MAX_VALUE)
|
||||||
val machines = parse(input)
|
|
||||||
var sumButts = 0
|
fun applyJoltage(jolts: IntArray, toggle: Toggle, times: Int = 1): Boolean {
|
||||||
// so this is not working in time and space, needs some clever pruning or prime factoring of button presses to reach the target values
|
var tt = toggle.v
|
||||||
for (m in machines) {
|
|
||||||
val pq = PriorityQueue(compareBy<Pair<Int, Pair<Int, IntArray>>> { it.second.first }.thenComparing { it.second.second.sum() })
|
|
||||||
pq.add(0 to (0 to m.joltage))
|
|
||||||
val bestMap = HashMap<IntArray, Int>()
|
|
||||||
while (pq.isNotEmpty()) {
|
|
||||||
val (v, bi) = pq.poll()
|
|
||||||
if (bi.second.sum() == 0) {
|
|
||||||
println("${bi.first}")
|
|
||||||
sumButts += bi.first
|
|
||||||
break
|
|
||||||
}
|
|
||||||
//println("$v ${bi.first} ${bi.second.joinToString(",")}")
|
|
||||||
for (t in m.toggles) {
|
|
||||||
val nv = v xor t
|
|
||||||
val nj = bi.second.copyOf()
|
|
||||||
var tt = t
|
|
||||||
var jp = 0
|
var jp = 0
|
||||||
var valid = true
|
var valid = true
|
||||||
while (tt != 0) {
|
while (tt != 0) {
|
||||||
if (tt and 1 != 0) {
|
if (tt and 1 != 0) {
|
||||||
nj[jp]--
|
jolts[jp] -= times
|
||||||
if (nj[jp] < 0) {
|
if (jolts[jp] < 0) {
|
||||||
valid = false
|
valid = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -93,17 +79,120 @@ fun main() {
|
|||||||
tt = tt shr 1
|
tt = tt shr 1
|
||||||
jp++
|
jp++
|
||||||
}
|
}
|
||||||
if (valid) {
|
return valid
|
||||||
val cache = bestMap[nj]
|
}
|
||||||
if (cache == null || cache > bi.first + 1) {
|
|
||||||
val nbj = (bi.first + 1 to nj)
|
fun findMaxButtonPresses(jolts: IntArray, toggle: Toggle): Int {
|
||||||
bestMap[nj] = bi.first + 1
|
var tt = toggle.v
|
||||||
pq.add(nv to nbj)
|
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 {
|
||||||
|
val machines = parse(input)
|
||||||
|
|
||||||
|
var sumButts = 0
|
||||||
|
for (m in machines) {
|
||||||
|
// generate toggles and calculate the global maximum of toggle presses for this toggle
|
||||||
|
val toggles = m.toggles.mapIndexed { i, t ->
|
||||||
|
Toggle(i,
|
||||||
|
t,
|
||||||
|
max = IntRange(0, m.size).filter { b -> t and (1 shl b) != 0 }.minOf { m.joltage[it] })
|
||||||
|
}
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// look at which different possible sets of toggles need to be pressed to result in the target number
|
||||||
|
// pressing an even time will cancel out the effect, so only look what happens if you press once
|
||||||
|
val oddset = ArrayList<Set<Toggle>>()
|
||||||
|
for (tm in 1 until (1 shl toggles.size)) {
|
||||||
|
val odds = toggles.withIndex().filter { (i, _) -> (1 shl i) and tm != 0 }.map { it.value }.toSet()
|
||||||
|
val result = odds.fold(0) { acc, iv -> acc xor iv.v }
|
||||||
|
if (result == m.target) {
|
||||||
|
oddset.add(odds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate over the possible odd sets
|
||||||
|
var minPushes = Int.MAX_VALUE
|
||||||
|
newodd@ for (odds in oddset) {
|
||||||
|
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)) continue@newodd
|
||||||
|
pressCount[t.idx] += t.min
|
||||||
|
|
||||||
|
if (odds.contains(t)) {
|
||||||
|
// make sure that the buttons that will lead to a solution have an odd count
|
||||||
|
if (pressCount[t.idx] and 1 == 0) {
|
||||||
|
if (++pressCount[t.idx] > t.max || !applyJoltage(jolts, t)) continue@newodd
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// make sure that the buttons that will destroy the solution have an even count
|
||||||
|
if (pressCount[t.idx] and 1 == 1) {
|
||||||
|
if (++pressCount[t.idx] > t.max || !applyJoltage(jolts, t)) continue@newodd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// this is the starting point for the exhaustive search
|
||||||
|
val pq = LinkedList<Pair<IntArray, IntArray>>()
|
||||||
|
pq.add(jolts to pressCount)
|
||||||
|
while (pq.isNotEmpty()) {
|
||||||
|
val (j, tc) = pq.poll()
|
||||||
|
val pushes = tc.sum()
|
||||||
|
if (pushes >= minPushes) break
|
||||||
|
// if the joltage has counted down to zero, we're done
|
||||||
|
if (j.sum() == 0) {
|
||||||
|
minPushes = pushes
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for (t in toggles) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
return sumButts
|
return sumButts
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +204,7 @@ fun main() {
|
|||||||
val testInputPart2Result = part2(testInput)
|
val testInputPart2Result = part2(testInput)
|
||||||
println("Part 2 Test: $testInputPart2Result")
|
println("Part 2 Test: $testInputPart2Result")
|
||||||
check(testInputPart1Result == 7)
|
check(testInputPart1Result == 7)
|
||||||
check(testInputPart2Result == 33)
|
//check(testInputPart2Result == 33)
|
||||||
|
|
||||||
val input = readInput("aoc2025/Day10")
|
val input = readInput("aoc2025/Day10")
|
||||||
part1(input).println()
|
part1(input).println()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user