This one's part 1 destroyed me. I had a very difficult time, trying 3 separate approaches, each one of which worked for most cases but eventually fell apart on the 5th sample or my actual puzzle input. I ended up tweaking and rewriting until I landed on this which wasn't far off from what I was trying to do previously, but I had been overcomplicating things. Part 2 surprised me in that I expected a simple "ore available divided by ore needed for 1 fuel" would solve it, but of course the excess chemicals produced in any given reaction meant that it wasn't that simple. So this approach uses that estimate as a lower bound, since it always underestimates, and then bisects its way to the solution (starting at the lower bound and adding 1 each time took too long). I'm sure a smarter upper bound choice could lower the runtime of this by a bit, but runtime isn't bad enough right now for me to try any additional optimizations.
50 lines
733 B
Go
50 lines
733 B
Go
package utilities
|
|
|
|
import "math"
|
|
|
|
func GCD[T Integer](a, b T) T {
|
|
if b == 0 {
|
|
return a
|
|
}
|
|
return GCD(b, a%b)
|
|
}
|
|
|
|
func LCM[T Integer](nums ...T) uint64 {
|
|
num := len(nums)
|
|
if num == 0 {
|
|
return 0
|
|
} else if num == 1 {
|
|
return uint64(nums[0])
|
|
}
|
|
|
|
ret := lcm(nums[0], nums[1])
|
|
for i := 2; i < len(nums); i++ {
|
|
ret = lcm(uint64(nums[i]), ret)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func lcm[T Integer](a, b T) uint64 {
|
|
return uint64(a*b) / uint64(GCD(a, b))
|
|
}
|
|
|
|
func Min[T Number](nums ...T) T {
|
|
numNums := len(nums)
|
|
if numNums == 2 {
|
|
return T(math.Min(float64(nums[0]), float64(nums[1])))
|
|
}
|
|
|
|
if numNums == 0 {
|
|
return 0
|
|
}
|
|
|
|
least := nums[0]
|
|
for i := 1; i < numNums; i++ {
|
|
if nums[i] < least {
|
|
least = nums[i]
|
|
}
|
|
}
|
|
|
|
return least
|
|
}
|