diff --git a/days/14.go b/days/14.go index 87b5224..8b82b17 100644 --- a/days/14.go +++ b/days/14.go @@ -104,26 +104,10 @@ func (d *Day14) Part1() string { func (d *Day14) Part2() string { oreAvailable := int64(1000000000000) estimate := oreAvailable / d.getOreRequiredForFuel(1) - - high := estimate * 2 - low := estimate - - lastSuccess := low - lastFailure := high - fuelProduced := low - - for math.Abs(float64(lastFailure-lastSuccess)) > 1 { - oreConsumed := d.getOreRequiredForFuel(fuelProduced) - adjustment := (lastFailure - lastSuccess) / 2 - if oreConsumed < oreAvailable { - lastSuccess = fuelProduced - } else { - lastFailure = fuelProduced - adjustment = -adjustment - } - - fuelProduced += adjustment - } + lastSuccess := u.Bisect(estimate, estimate*2, 1, func(val int64) bool { + oreConsumed := d.getOreRequiredForFuel(val) + return oreConsumed < oreAvailable + }) return fmt.Sprintf("Maximum fuel we can make from 1 trillion ore: %s%d%s", u.TextBold, lastSuccess, u.TextReset) } diff --git a/utilities/bisect.go b/utilities/bisect.go new file mode 100644 index 0000000..0bd62b1 --- /dev/null +++ b/utilities/bisect.go @@ -0,0 +1,28 @@ +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 { + currVal := low + + for T(math.Abs(float64(high-low))) > threshold { + currVal = low + ((high - low) / 2) + success := tryFunc(currVal) + if success { + low = currVal + } else { + high = currVal + } + } + + return currVal +} diff --git a/utilities/intcode.go b/utilities/intcode.go index f0bf4b4..d037711 100644 --- a/utilities/intcode.go +++ b/utilities/intcode.go @@ -128,9 +128,15 @@ func (p *IntcodeProgram) ensureMemoryCapacity(address int) { } func (p *IntcodeProgram) Reset() { - p.memory = nil + wiped := false + if len(p.memory) != len(p.program) { + wiped = true + p.memory = nil + } p.init() - copy(p.memory, p.program) + if !wiped { + copy(p.memory, p.program) + } p.relativeBase = 0 }