aoc-2020/d05/main.go

129 lines
2.4 KiB
Go

package main
import (
"bufio"
"fmt"
"log"
"os"
"sort"
)
func proccessLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
type seat struct {
row, column, id int
}
func paritionSearch(partitions string, start, end float64, lower, upper string) (int, error) {
if start == end {
return int(start), nil
}
if partitions == "" {
return 0, fmt.Errorf("empty partitions are invalid")
}
if start > end {
return 0, fmt.Errorf("start cannot be greater than end")
}
if lower == "" || upper == "" {
return 0, fmt.Errorf("invalid upper and lower bounds")
}
mid := (end - start) / 2.0
direction := string(partitions[0])
switch direction {
case lower:
return paritionSearch(partitions[1:], start, mid+start-.5, lower, upper)
case upper:
return paritionSearch(partitions[1:], mid+start+.5, end, lower, upper)
}
return 0, fmt.Errorf("unknown direction %s", direction)
}
func parseSeat(code string) (seat, error) {
totalRows, totalCols := 128, 8
if len(code) != 10 {
return seat{}, fmt.Errorf("invalid code length %s", code)
}
row, err := paritionSearch(code[:7], 0.0, float64(totalRows-1), "F", "B")
if err != nil {
return seat{}, err
}
col, err := paritionSearch(code[7:], 0.0, float64(totalCols-1), "L", "R")
if err != nil {
return seat{}, err
}
return seat{
row: row,
column: col,
id: row*8 + col,
}, nil
}
func part1() {
max := -1
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
s, err := parseSeat(line)
if err != nil {
return
}
if s.id > max {
max = s.id
}
return
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Max id is %d\n", max)
}
func part2() {
seatIds := []int{}
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
s, err := parseSeat(line)
if err != nil {
return
}
seatIds = append(seatIds, s.id)
return
})
if err != nil {
log.Fatal(err)
}
sort.Ints(seatIds)
lastID := -3
for _, id := range seatIds {
if id == lastID+2 {
fmt.Printf("Found my seat! %d", lastID+1)
break
}
lastID = id
}
}
func main() {
part1()
part2()
}