Skip to content

Commit 780a32f

Browse files
committed
Reorder operations to avoid overflow in more cases
1 parent 109c120 commit 780a32f

File tree

2 files changed

+28
-24
lines changed

2 files changed

+28
-24
lines changed

kt/build.gradle.kts

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ val jvmResources by tasks.registering(Sync::class) {
3030
kotlin {
3131
jvm {
3232
compilations.create("bench")
33+
compilations.all {
34+
kotlinOptions.freeCompilerArgs += "-Xassertions=jvm"
35+
}
3336
val jvmTestFixtures by configurations.creating {
3437
val parent = configurations.getByName("jvmTestRuntimeClasspath")
3538
extendsFrom(parent)

kt/src/commonMain/kotlin/com/github/ephemient/aoc2022/Day21.kt

+25-24
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package com.github.ephemient.aoc2022
22

3-
import kotlin.math.abs
4-
53
@Day
64
class Day21(lines: List<String>) {
75
private val monkeys = buildMap {
@@ -83,48 +81,51 @@ class Day21(lines: List<String>) {
8381
private data class Rational(val numerator: Long, val denominator: Long = 1) {
8482
init {
8583
require(denominator > 0)
84+
assert(gcd(numerator, denominator) == 1L)
8685
}
8786

8887
operator fun plus(other: Rational): Rational {
89-
val denominator = this.denominator * other.denominator / gcd(this.denominator, other.denominator)
90-
val numerator = this.numerator * (denominator / this.denominator) +
91-
other.numerator * (denominator / other.denominator)
92-
val gcd = abs(gcd(numerator, denominator))
93-
return Rational(numerator / gcd, denominator / gcd)
88+
val gcd1 = gcd(this.denominator, other.denominator)
89+
val multiplier = this.denominator / gcd1
90+
val denominator = multiplier * other.denominator
91+
val numerator = this.numerator * (other.denominator / gcd1) + other.numerator * multiplier
92+
val gcd2 = gcd(numerator, denominator)
93+
return Rational(numerator / gcd2, denominator / gcd2)
9494
}
9595

9696
operator fun minus(other: Rational): Rational {
97-
val denominator = this.denominator * other.denominator / gcd(this.denominator, other.denominator)
98-
val numerator = this.numerator * (denominator / this.denominator) -
99-
other.numerator * (denominator / other.denominator)
100-
val gcd = abs(gcd(numerator, denominator))
101-
return Rational(numerator / gcd, denominator / gcd)
97+
val gcd1 = gcd(this.denominator, other.denominator)
98+
val multiplier = this.denominator / gcd1
99+
val denominator = multiplier * other.denominator
100+
val numerator = this.numerator * (other.denominator / gcd1) - other.numerator * multiplier
101+
val gcd2 = gcd(numerator, denominator)
102+
return Rational(numerator / gcd2, denominator / gcd2)
102103
}
103104

104105
operator fun times(other: Rational): Rational {
105-
val numerator = this.numerator * other.numerator
106-
val denominator = this.denominator * other.denominator
107-
val gcd = abs(gcd(numerator, denominator))
108-
return Rational(numerator / gcd, denominator / gcd)
106+
val gcd1 = gcd(this.numerator, other.denominator)
107+
val gcd2 = gcd(other.numerator, this.denominator)
108+
val numerator = (this.numerator / gcd1) * (other.numerator / gcd2)
109+
val denominator = (this.denominator / gcd2) * (other.denominator / gcd1)
110+
return Rational(numerator, denominator)
109111
}
110112

111113
operator fun div(other: Rational): Rational {
112114
require(other.numerator != 0L)
113-
val numerator = this.numerator * other.denominator
114-
val denominator = this.denominator * other.numerator
115-
val gcd = gcd(numerator, denominator).let { if (it < 0 != denominator < 0) -it else it }
116-
return Rational(numerator / gcd, denominator / gcd)
115+
val gcd1 = gcd(this.numerator, other.numerator)
116+
val gcd2 = gcd(other.denominator, this.denominator)
117+
val numerator = (this.numerator / gcd1) * (other.denominator / gcd2)
118+
val denominator = (this.denominator / gcd2) * (other.numerator / gcd1)
119+
return Rational(numerator, denominator)
117120
}
118121
}
119122

120123
companion object {
121124
private fun gcd(a: Long, b: Long): Long {
122125
var x = a
123126
var y = b
124-
while (y != 0L) {
125-
x = y.also { y = x % y }
126-
}
127-
return x
127+
while (y != 0L) x = y.also { y = x % y }
128+
return if (x < 0 != b < 0) -x else x
128129
}
129130
}
130131
}

0 commit comments

Comments
 (0)