@@ -6,99 +6,59 @@ import kotlinx.coroutines.*
6
6
import kotlinx.coroutines.channels.Channel
7
7
import kotlinx.coroutines.channels.SendChannel
8
8
import kotlinx.coroutines.selects.select
9
+ import java.math.BigDecimal
9
10
import java.math.BigInteger
11
+ import kotlin.math.log10
10
12
11
13
object Day7: AocDay(2024 , 7 ) {
12
-
13
- private suspend fun bruteForce (goal : BigInteger , parts : List <BigInteger >, current : BigInteger ? = null, withPart2 : Boolean = false, scope : CoroutineScope , channel : SendChannel <Unit >? = null): Boolean {
14
+ private suspend fun bruteForce (goal : BigInteger , parts : List <BigInteger >, current : BigInteger ? = null, withPart2 : Boolean = false): Boolean {
14
15
if (current == null ) {
15
- val channel = Channel <Unit >(Channel .BUFFERED )
16
- val work = scope.launch {
17
- bruteForce(
18
- goal = goal,
19
- parts = parts.subList(1 , parts.size),
20
- current = parts[0 ],
21
- withPart2 = withPart2,
22
- scope = scope,
23
- channel = channel
24
- )
25
- }
26
- return select<Boolean > {
27
- channel.onReceive {
28
- work.cancel()
29
- true
30
- }
31
- work.onJoin {
32
- false
33
- }
34
- }
16
+ return bruteForce(
17
+ goal = goal,
18
+ parts = parts.subList(1 , parts.size),
19
+ current = parts[0 ],
20
+ withPart2 = withPart2,
21
+ )
35
22
}
36
23
37
24
if (current > goal) {
38
25
return false
39
26
}
40
27
41
28
if (parts.isEmpty()) {
42
- if (current == goal) {
43
- channel?.send(Unit )
44
- }
45
29
return current == goal
46
30
}
47
31
48
- val jobs = buildSet<Deferred <Boolean >> {
49
- add(scope.async { bruteForce(goal, parts.subList(1 , parts.size), current + parts[0 ], withPart2 = withPart2, scope = scope, channel = channel)})
50
- add(scope.async { bruteForce(goal, parts.subList(1 , parts.size), current * parts[0 ], withPart2 = withPart2, scope = scope, channel = channel)})
51
- if (withPart2){
52
- add(scope.async { bruteForce(goal, parts.subList(1 , parts.size), (current.toString() + parts[0 ].toString()).toBigInteger(), withPart2 = true , scope = scope, channel = channel)})
53
- }
54
- }.toMutableSet()
55
-
56
- while (jobs.isNotEmpty()) {
57
- select {
58
- jobs.forEach { job ->
59
- job.onAwait { result ->
60
- jobs.remove(job)
61
- if (result) {
62
- channel?.send(Unit )
63
- }
64
- result
65
- }
66
- }
67
- }.let {
68
- if (it) {
69
- jobs.forEach { it.cancel() }
70
- return true
71
- }
72
- }
73
- }
74
-
75
- return false
32
+ return bruteForce(goal, parts.subList(1 , parts.size), current * parts[0 ], withPart2 = withPart2) ||
33
+ (withPart2 && bruteForce(goal, parts.subList(1 , parts.size), current * BigInteger .TEN .pow(log10(parts[0 ].toDouble()).toInt() + 1 ) + parts[0 ], withPart2 = true )) ||
34
+ bruteForce(goal, parts.subList(1 , parts.size), current + parts[0 ], withPart2 = withPart2)
76
35
}
77
36
78
- private val parseRegex = Regex (""" ^(\d+):(?: (\d+))*""" )
79
- override suspend fun part1 (): Any = coroutineScope {
80
- inputLinesList.chunkedParMap(inputLinesList.size / cpu) {lines ->
37
+ override suspend fun part1 (): Any {
38
+ val matching = inputLinesList.chunkedParMap(inputLinesList.size / cpu) {lines ->
81
39
lines.map {
82
40
val colon = it.indexOf(' :' )
83
41
val goal = it.substring(0 , colon).toBigInteger()
84
42
val parts = it.substring(colon + 2 ).split(" " ).map { it.toBigInteger() }
85
43
goal to parts
86
- }.filter { bruteForce(it.first, it.second, scope = this @coroutineScope ) }
44
+ }.filter { bruteForce(it.first, it.second) }
87
45
.map { it.first }
88
46
.fold (BigInteger .ZERO ) { acc, i -> acc + i }
89
47
}.fold(BigInteger .ZERO ) { acc, i -> acc + i }
48
+ return matching
90
49
}
91
50
92
- override suspend fun part2 () = coroutineScope {
93
- inputLinesList.chunkedParMap(inputLinesList.size / cpu) {lines ->
51
+ override suspend fun part2 (): Any {
52
+ val matching = inputLinesList.chunkedParMap(inputLinesList.size / cpu) {lines ->
94
53
lines.map {
95
54
val colon = it.indexOf(' :' )
96
55
val goal = it.substring(0 , colon).toBigInteger()
97
56
val parts = it.substring(colon + 2 ).split(" " ).map { it.toBigInteger() }
98
57
goal to parts
99
- }.filter { bruteForce(it.first, it.second, withPart2 = true , scope = this @coroutineScope ) }
58
+ }.filter { bruteForce(it.first, it.second, withPart2 = true ) }
100
59
.map { it.first }
101
60
.fold (BigInteger .ZERO ) { acc, i -> acc + i }
102
61
}.fold(BigInteger .ZERO ) { acc, i -> acc + i }
62
+ return matching
103
63
}
104
64
}
0 commit comments