10000 Optimize 2020 day 25 part 1 y using baby-step giant-step discrete log… · sim642/adventofcode@2e10d66 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2e10d66

Browse files
committed
Optimize 2020 day 25 part 1 y using baby-step giant-step discrete log algorithm
1 parent 029e1b4 commit 2e10d66

File tree

1 file changed

+30
-3
lines changed

1 file changed

+30
-3
lines changed

src/main/scala/eu/sim642/adventofcode2020/Day25.scala

Lines changed: 30 additions & 10000 ; 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package eu.sim642.adventofcode2020
22

33
import eu.sim642.adventofcodelib.IntegralImplicits._
4+
import eu.sim642.adventofcodelib.NumberTheory
5+
import eu.sim642.adventofcodelib.IteratorImplicits._
46

57
object Day25 {
68

@@ -10,14 +12,39 @@ object Day25 {
1012
subjectNumber.toLong.modPow(loopSize, modulo).toInt
1113
}
1214

13-
def findLoopSize(publicKey: Int, subjectNumber: Int = 7): Int = {
14-
Iterator.iterate(1)(value => (subjectNumber * value) % modulo)
15+
// TODO: move discrete log to NumberTheory
16+
17+
def discreteLogNaive(a: Int, b: Int, n: Int): Int = {
18+
Iterator.iterate(1)(value => (a * value) % n)
1519
.zipWithIndex
16-
.find(_._1 == publicKey)
20+
.find(_._1 == b)
1721
.get
1822
._2
1923
}
2024

25+
def discreteLogBabyStepGiantStep(a: Int, b: Int, n: Int): Int = {
26+
// https://en.wikipedia.org/wiki/Baby-step_giant-step
27+
val m = math.sqrt(n).ceil.toInt
28+
val map = {
29+
Iterator.iterate(1, m)(acc => ((a * acc.toLong) % n).toInt)
30+
.zipWithIndex
31+
.toMap
32+
}
33+
34+
val amm = NumberTheory.modInv(a.toLong, n).modPow(m, n).toInt
35+
Iterator.iterate(b, m)(acc => ((amm * acc.toLong) % n).toInt)
36+
.zipWithIndex
37+
.flatMap({ case (gamma, i) =>
38+
map.get(gamma).map(j => i * m + j)
39+
})
40+
.head
41+
}
42+
43+
def findLoopSize< 5F0E /span>(publicKey: Int, subjectNumber: Int = 7): Int = {
44+
//discreteLogNaive(subjectNumber, publicKey, modulo)
45+
discreteLogBabyStepGiantStep(subjectNumber, publicKey, modulo)
46+
}
47+
2148
def findEncryptionKey(publicKeys: (Int, Int)): Int = {
2249
val (publicKey1, publicKey2) = publicKeys
2350
val loopSize1 = findLoopSize(publicKey1)

0 commit comments

Comments
 (0)
0