This commit is contained in:
Chris Hodges 2025-12-15 09:55:01 +01:00
parent de3b0795e3
commit 5e031c27cc
2 changed files with 63 additions and 16 deletions

View File

@ -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
@ -211,6 +212,29 @@ fun extendedGcd(a: Long, b: Long): Pair<Long, Pair<Long, Long>> {
return old_r to (old_s to old_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>> { fun extendedGcd(v: List<Long>): Pair<Long, List<Long>> {
if (v.size < 2) throw IllegalArgumentException("Expected at least 2 elements") if (v.size < 2) throw IllegalArgumentException("Expected at least 2 elements")
@ -235,6 +259,30 @@ fun extendedGcd(v: List<Long>): Pair<Long, List<Long>> {
return gcd to coeffs 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( fun calcPrimeFactorsAndPhi(
n: Long, n: Long,
primes: MutableList<Long>, primes: MutableList<Long>,

View File

@ -1,13 +1,14 @@
package aoc2025 package aoc2025
import chineseRemainder import chineseRemainder
import extendedGcd import extendedGcdBigInteger
import primeFactors import primeFactors
import primeSequence import primeSequence
import println import println
import readInput import readInput
import sieveOfErastosthenes import sieveOfErastosthenes
import splitInts import splitInts
import java.math.BigInteger
/* /*
--- Day 10: Factory --- --- Day 10: Factory ---
@ -68,24 +69,22 @@ fun main() {
for (m in machines) { for (m in machines) {
println() println()
val maxJoltage = m.joltage.max() val maxJoltage = m.joltage.max()
val primefactors = primes.dropWhile { it <= maxJoltage }.take(m.size).map { it.toLong() } val numBits = 32 - maxJoltage.countLeadingZeroBits()
if (primefactors.size != m.size) throw IllegalStateException() val bigTarget = m.joltage.foldIndexed(BigInteger.ZERO) { index, acc, i ->
val primePow = LongArray(m.size) acc.plus(
primePow[0] = primefactors[0] BigInteger.valueOf(i.toLong()).shiftLeft(numBits * index)
for (i in 1 until m.size) { )
primePow[i] = primePow[i - 1] * primefactors[i]
} }
val bigTarget = m.joltage.foldIndexed(0L) { index, acc, i -> acc.plus(i.toLong() * primePow[index]) } val bigToggles = ArrayList<BigInteger>()
val bigToggles = ArrayList<Long>()
for (t in m.toggles) { for (t in m.toggles) {
var tt = t var tt = t
var bigToggle = 0L var bigToggle = BigInteger.ZERO
var idx = 0 var shift = 0
while (tt > 0) { while (tt > 0) {
if (tt and 1 != 0) { if (tt and 1 != 0) {
bigToggle += primePow[idx] bigToggle += BigInteger.ONE.shiftLeft(shift)
} }
idx++ shift += numBits
tt = tt shr 1 tt = tt shr 1
} }
bigToggles.add(bigToggle) bigToggles.add(bigToggle)
@ -94,12 +93,12 @@ fun main() {
// j0 * bigtoggle[0] + j1 * bigtoggle[1] + ... = bigTarget // j0 * bigtoggle[0] + j1 * bigtoggle[1] + ... = bigTarget
// is a Linear Diophantine equation that can be solved with the extended Euclidean algorithm // is a Linear Diophantine equation that can be solved with the extended Euclidean algorithm
val (gcd, coeffients) = extendedGcd(bigToggles) val (gcd, coeffients) = extendedGcdBigInteger(bigToggles)
if (bigTarget % gcd != 0L) throw IllegalStateException() if (bigTarget % gcd != BigInteger.ZERO) throw IllegalStateException()
val factorMap = HashMap<Long, Long>() val factorMap = HashMap<Long, Long>()
var good = true var good = true
val primeFactors = primeFactors(bigTarget, sieve) val primeFactors = primeFactors(bigTarget.toLong(), sieve)
for (pf in primeFactors) { for (pf in primeFactors) {
val sf = factorMap[pf] val sf = factorMap[pf]
val pr = 1000 % pf val pr = 1000 % pf