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() }