Watch
1
0
Fork
You've already forked advent-of-code
0

2021 Day 7

This commit is contained in:
Jeremy Kaplan 2021-12-06 21:42:15 -08:00
commit 0f454c5d1f
2 changed files with 121 additions and 0 deletions

View file

@ -84,3 +84,10 @@ func Cut(s, sep string) (before, after string) {
} }
panic("Separator was not found in string") panic("Separator was not found in string")
} }
func Ints(text string) (ns []int) {
for _, n := range strings.Split(text, ",") {
ns = append(ns, MustInt(n))
}
return
}

114
2021/day7/main.go Normal file
View 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
}