-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathDay15.scala
60 lines (49 loc) · 1.86 KB
/
Day15.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package com.lmat.adventofcode.year2017
import com.lmat.adventofcode.SimpleCommonPuzzle
import com.lmat.util.Files.readResource
import com.lmat.util.Strings.leftPad
import scala.annotation.tailrec
object Day15 extends SimpleCommonPuzzle[(Long, Long), Long, Long] {
override def parse(resource: String): (Long, Long) = {
val starts = readResource(resource).map(_.split(" ").last)
(starts.head.toLong, starts(1).toLong)
}
override def part1(starts: (Long, Long)): Long = {
val (startA, startB) = starts
val generatorA = generate(16807L, 2147483647L)(_)
val generatorB = generate(48271L, 2147483647L)(_)
val n = 40000000
judge(generatorA, generatorB, startA, startB, n)
}
override def part2(starts: (Long, Long)): Long = {
val (startA, startB) = starts
val generatorA = generateWithTest(16807L, 2147483647L, 4)(_)
val generatorB = generateWithTest(48271L, 2147483647L, 8)(_)
val n = 5000000
judge(generatorA, generatorB, startA, startB, n)
}
def judge(genA: Long => Long, genB: Long => Long, startA: Long, startB: Long, n: Long): Long = {
@tailrec
def count(a: Long, b: Long, n: Long, c: Long): Long =
if (n == 0) c
else {
val newA = genA(a)
val newB = genB(b)
val newC = if (lowestNBits(newA, 16) == lowestNBits(newB, 16)) c + 1 else c
count(newA, newB, n - 1, newC)
}
count(startA, startB, n, 0)
}
def lowestNBits(value: Long, n: Int): String = {
val binary = value.toBinaryString
leftPad(binary.drop(binary.length - n))('0', n)
}
def generate(factor: Long, mod: Long)(value: Long): Long =
value * factor % mod
@tailrec
def generateWithTest(factor: Long, mod: Long, test: Long)(value: Long): Long = {
val newValue = generate(factor, mod)(value)
if (newValue % test == 0) newValue
else generateWithTest(factor, mod, test)(newValue)
}
}