-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathy24day19.kt
More file actions
50 lines (46 loc) · 1.92 KB
/
Copy pathy24day19.kt
File metadata and controls
50 lines (46 loc) · 1.92 KB
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
import kotlin.math.min
import kotlin.time.measureTimedValue
fun main() {
val patterns = readln().split(", ")
readln()
val designs = generateSequence { readlnOrNull() }.toList()
val minPrefix = patterns.minOf { it.length }
val maxPrefix = min(8, patterns.maxOf { it.length })
fun CharSequence.prefixHash(len: Int) =
asSequence().take(len).fold(0L) { a, c -> a shl 8 xor c.code.toLong() }
val patternsByHash = patterns.groupBy { it.prefixHash(maxPrefix) }
measureTimedValue { // part 1
val memo = HashMap<String, Boolean>()
fun possible(str: String): Boolean = memo.getOrPut(str) {
if (str.isEmpty()) true
else {
val len = min(maxPrefix, str.length)
var hash = str.prefixHash(len)
(len downTo minPrefix).any {
patternsByHash[hash.also { hash = hash ushr 8 }]?.any { pattern ->
(pattern.length <= maxPrefix || str.startsWith(pattern))
&& possible(str.substring(pattern.length, str.length))
} ?: false
}
}
}
designs.count { possible(it) }
}.also(::println)
measureTimedValue { // part 2
val memo = HashMap<String, Long>()
fun countPossible(str: String): Long = memo.getOrPut(str) {
if (str.isEmpty()) 1L
else {
val len = min(maxPrefix, str.length)
var hash = str.prefixHash(len)
(len downTo minPrefix).sumOf {
patternsByHash[hash.also { hash = hash ushr 8 }]?.sumOf { pattern ->
if (pattern.length > maxPrefix && !str.startsWith(pattern)) 0
else countPossible(str.substring(pattern.length, str.length))
} ?: 0
}
}
}
designs.sumOf { countPossible(it) }
}.also(::println)
}