package main import ( "bufio" "fmt" "log" "os" "strconv" "strings" ) type bus struct { id int64 index int64 } type schedule struct { timestamp int64 buses []bus } func getIDs(busesString string) ([]bus, error) { buses := []bus{} var index int64 = 0 for _, item := range strings.Split(busesString, ",") { if item != "x" { id, err := strconv.ParseInt(item, 10, 32) if err != nil { return buses, fmt.Errorf("Error parsing busID %s: %s", item, err) } newBus := bus{id: id, index: index} buses = append(buses, newBus) } index++ } return buses, nil } func readData(file *os.File) (schedule, error) { scanner := bufio.NewScanner(file) data := schedule{} if !scanner.Scan() { return data, fmt.Errorf("Error reading timestamp!") } timestampString := scanner.Text() timestamp, err := strconv.ParseInt(timestampString, 10, 32) if err != nil { return data, fmt.Errorf("Error parsing timestamp %s: %s", timestampString, err) } data.timestamp = timestamp if !scanner.Scan() { return data, fmt.Errorf("Error reading buses!") } busesString := scanner.Text() if err := scanner.Err(); err != nil { return data, err } data.buses, err = getIDs(busesString) if err != nil { return data, err } return data, nil } func findEarliestBus(data schedule) int64 { var earliest int64 = data.timestamp var earliestID int64 = 0 for _, item := range data.buses { value := item.id - (data.timestamp % item.id) if value < earliest { earliest = value earliestID = item.id } } return earliest * earliestID } func alignBuses(data schedule) int64 { var advance int64 = 1 var next int64 = 1 var current int64 for _, item := range data.buses { current = next for { current += advance if (current+item.index)%item.id == 0 { next = current break } } advance *= item.id } return current } func main() { if len(os.Args) < 2 { log.Fatal("You need to specify a file!") } file, err := os.Open(os.Args[1]) if err != nil { log.Fatalf("Failed to open %s!\n", os.Args[1]) } data, err := readData(file) if err != nil { log.Fatalf("Failed to read data: %s\n", err) } if err := file.Close(); err != nil { log.Fatalf("Failed to close file: %s\n", err) } fmt.Println("Part1:", findEarliestBus(data)) fmt.Println("Part2:", alignBuses(data)) }