2021 Day 7
This commit is contained in:
parent
01699081b4
commit
0f454c5d1f
2 changed files with 121 additions and 0 deletions
114
2021/day7/main.go
Normal file
114
2021/day7/main.go
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jdkaplan/advent-of-code/aoc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
text := aoc.Input().ReadFile("day7.txt")
|
||||
fmt.Println(part1(text))
|
||||
fmt.Println(part2(text))
|
||||
}
|
||||
|
||||
func part1(text string) int {
|
||||
ps := aoc.Ints(text)
|
||||
argmin := ps[0]
|
||||
min := cost1(argmin, ps)
|
||||
for _, p := range ps[1:] {
|
||||
c := cost1(p, ps)
|
||||
if c < min {
|
||||
argmin, min = p, c
|
||||
}
|
||||
}
|
||||
fmt.Println("Pos:", argmin)
|
||||
return min
|
||||
}
|
||||
|
||||
func part2(text string) int {
|
||||
ps := aoc.Ints(text)
|
||||
lo, hi := minmax(ps)
|
||||
cost, pos := bisect(func(p int) int { return cost2(p, ps) }, lo, hi)
|
||||
fmt.Println("Pos:", pos)
|
||||
return cost
|
||||
}
|
||||
|
||||
func cost1(x int, ns []int) (cost int) {
|
||||
for _, n := range ns {
|
||||
cost += abs(n - x)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cost2(x int, ns []int) (cost int) {
|
||||
for _, n := range ns {
|
||||
d := abs(n - x)
|
||||
cost += tri(d)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func abs(n int) int {
|
||||
if n < 0 {
|
||||
return -n
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func tri(n int) int {
|
||||
return n * (n + 1) / 2
|
||||
}
|
||||
|
||||
func bisect(f func(int) int, lo, hi int) (min int, argmin int) {
|
||||
if lo == hi {
|
||||
return f(lo), lo
|
||||
}
|
||||
if hi-lo == 1 {
|
||||
flo, fhi := f(lo), f(hi)
|
||||
if flo < fhi {
|
||||
return flo, lo
|
||||
}
|
||||
return fhi, hi
|
||||
}
|
||||
md := (hi + lo) / 2
|
||||
switch md {
|
||||
case lo:
|
||||
return f(lo), lo
|
||||
case hi:
|
||||
return f(hi), hi
|
||||
default:
|
||||
s := slope(f, md)
|
||||
if s == 0 {
|
||||
return f(md), md
|
||||
}
|
||||
if s < 0 {
|
||||
return bisect(f, md, hi)
|
||||
}
|
||||
return bisect(f, lo, md)
|
||||
}
|
||||
}
|
||||
|
||||
func slope(f func(int) int, n int) int {
|
||||
var (
|
||||
lo = n - 1
|
||||
hi = n + 1
|
||||
flo = f(lo)
|
||||
fhi = f(hi)
|
||||
)
|
||||
return fhi - flo
|
||||
}
|
||||
|
||||
func minmax(ns []int) (min int, max int) {
|
||||
min = ns[0]
|
||||
max = ns[0]
|
||||
for _, n := range ns[1:] {
|
||||
if n < min {
|
||||
min = n
|
||||
}
|
||||
if n > max {
|
||||
max = n
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
Loading…
Reference in a new issue