87 lines
1.5 KiB
Go
87 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"cmp"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"math"
|
|
"os"
|
|
)
|
|
|
|
func main() {
|
|
debug := flag.Bool("debug", false, "Debug.")
|
|
flag.Parse()
|
|
|
|
f := os.Stdin
|
|
if flag.NArg() > 0 {
|
|
var err error
|
|
f, err = os.Open(flag.Arg(0))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer f.Close()
|
|
}
|
|
|
|
banks, err := readBatteries(f)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
var sum1, sum2 uint
|
|
for _, bank := range banks {
|
|
power1 := bestPowerPart1(bank)
|
|
power2 := bestPowerPart2(bank)
|
|
if *debug {
|
|
for _, b := range bank {
|
|
fmt.Print(b)
|
|
}
|
|
fmt.Println(":", power1, power2)
|
|
}
|
|
sum1 += power1
|
|
sum2 += power2
|
|
}
|
|
|
|
fmt.Println("sum (part 1):", sum1)
|
|
fmt.Println("sum (part 2):", sum2)
|
|
}
|
|
|
|
func bestPowerPart1(bank []uint8) uint {
|
|
// i := maxIndex(bank[:len(bank)-1])
|
|
// j := maxIndex(bank[i+1:]) + i + 1
|
|
// return uint(bank[i])*10 + uint(bank[j])
|
|
return bestPower(bank, 2)
|
|
}
|
|
|
|
func bestPowerPart2(bank []uint8) uint {
|
|
return bestPower(bank, 12)
|
|
}
|
|
|
|
func bestPower(bank []uint8, batteries int) uint {
|
|
if len(bank) < batteries {
|
|
panic(fmt.Sprintf("bank (%d) is smaller than requested batteries (%d)", len(bank), batteries))
|
|
}
|
|
var joltage uint
|
|
var i int
|
|
for j := batteries - 1; j >= 0; j-- {
|
|
k := maxIndex(bank[i : len(bank)-j])
|
|
k += i
|
|
i = k + 1
|
|
joltage += uint(bank[k]) * uint(math.Pow10(j))
|
|
}
|
|
return joltage
|
|
}
|
|
|
|
func maxIndex[S ~[]E, E cmp.Ordered](x S) int {
|
|
if len(x) < 1 {
|
|
panic("maxIndex: empty list")
|
|
}
|
|
i := 0
|
|
for j := 1; j < len(x); j++ {
|
|
if x[j] > x[i] {
|
|
i = j
|
|
}
|
|
}
|
|
return i
|
|
}
|