129 lines
2.4 KiB
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()
|
|
}
|