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) {
|
||||
val stuff = i.split(" ")
|
||||
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 =
|
||||
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() }
|
||||
.toIntArray()
|
||||
val joltages = stuff.last().removeSurrounding("{", "}").splitInts(",").toIntArray()
|
||||
@ -39,19 +41,19 @@ fun main() {
|
||||
val machines = parse(input)
|
||||
var sumButts = 0
|
||||
for (m in machines) {
|
||||
val pq = PriorityQueue<Pair<Int, Int>>(compareBy { it.second })
|
||||
val killSet = HashSet<Int>()
|
||||
val pq = LinkedList<Pair<Int, Int>>()
|
||||
val killArray = BooleanArray(1 shl m.size)
|
||||
pq.add(0 to 0)
|
||||
while (pq.isNotEmpty()) {
|
||||
out@ while (pq.isNotEmpty()) {
|
||||
val (v, bi) = pq.poll()
|
||||
if (v == m.target) {
|
||||
sumButts += bi
|
||||
break
|
||||
}
|
||||
killSet.add(v)
|
||||
for (t in m.toggles) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -60,50 +62,137 @@ fun main() {
|
||||
return sumButts
|
||||
}
|
||||
|
||||
fun part2(input: List<String>): Int {
|
||||
val machines = parse(input)
|
||||
var sumButts = 0
|
||||
// so this is not working in time and space, needs some clever pruning or prime factoring of button presses to reach the target values
|
||||
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
|
||||
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
|
||||
}
|
||||
//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 valid = true
|
||||
while (tt != 0) {
|
||||
if (tt and 1 != 0) {
|
||||
nj[jp]--
|
||||
if (nj[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 {
|
||||
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
|
||||
}
|
||||
tt = tt shr 1
|
||||
jp++
|
||||
}
|
||||
if (valid) {
|
||||
val cache = bestMap[nj]
|
||||
if (cache == null || cache > bi.first + 1) {
|
||||
val nbj = (bi.first + 1 to nj)
|
||||
bestMap[nj] = bi.first + 1
|
||||
pq.add(nv to nbj)
|
||||
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
|
||||
}
|
||||
|
||||
@ -115,7 +204,7 @@ fun main() {
|
||||
val testInputPart2Result = part2(testInput)
|
||||
println("Part 2 Test: $testInputPart2Result")
|
||||
check(testInputPart1Result == 7)
|
||||
check(testInputPart2Result == 33)
|
||||
//check(testInputPart2Result == 33)
|
||||
|
||||
val input = readInput("aoc2025/Day10")
|
||||
part1(input).println()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user