This is too common of an optimization to not have this readily accessible. And I kinda like how this worked out, too. Go is fun. Plus this both speeds up and "fixes" day 14's part 2 solution (it was always giving a correct answer, but mostly by chance based on how the input numbers worked out).
27 lines
773 B
Go
27 lines
773 B
Go
package utilities
|
|
|
|
import (
|
|
"math"
|
|
)
|
|
|
|
// Bisect takes a known-good low and known-bad high value as the bounds
|
|
// to bisect, and a function to test each value for success or failure.
|
|
// If the function succeeds, the value is adjusted toward the maximum,
|
|
// and if the function fails, the value is adjusted toward the minimum.
|
|
// The final value is returned when the difference between the success
|
|
// and the failure is less than or equal to the acceptance threshold
|
|
// (usually 1, for integers).
|
|
func Bisect[T Number](low, high, threshold T, tryFunc func(val T) bool) T {
|
|
for T(math.Abs(float64(high-low))) > threshold {
|
|
currVal := low + ((high - low) / 2)
|
|
success := tryFunc(currVal)
|
|
if success {
|
|
low = currVal
|
|
} else {
|
|
high = currVal
|
|
}
|
|
}
|
|
|
|
return low
|
|
}
|