day13.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. type bus struct {
  11. id string
  12. idValue int64
  13. value int64
  14. }
  15. type schedule struct {
  16. timestamp int64
  17. buses []bus
  18. }
  19. func getIDs(busesString string) ([]bus, error) {
  20. buses := []bus{}
  21. for _, item := range strings.Split(busesString, ",") {
  22. newBus := bus{id: item, value: 0}
  23. if newBus.id == "x" {
  24. newBus.idValue = 0
  25. } else {
  26. var err error
  27. newBus.idValue, err = strconv.ParseInt(item, 10, 32)
  28. if err != nil {
  29. return buses, fmt.Errorf("Error parsing busID %s: %s", item, err)
  30. }
  31. }
  32. buses = append(buses, newBus)
  33. }
  34. return buses, nil
  35. }
  36. func readData(file *os.File) (schedule, error) {
  37. scanner := bufio.NewScanner(file)
  38. data := schedule{}
  39. if !scanner.Scan() {
  40. return data, fmt.Errorf("Error reading timestamp!")
  41. }
  42. timestampString := scanner.Text()
  43. timestamp, err := strconv.ParseInt(timestampString, 10, 32)
  44. if err != nil {
  45. return data, fmt.Errorf("Error parsing timestamp %s: %s", timestampString, err)
  46. }
  47. data.timestamp = timestamp
  48. if !scanner.Scan() {
  49. return data, fmt.Errorf("Error reading buses!")
  50. }
  51. busesString := scanner.Text()
  52. if err := scanner.Err(); err != nil {
  53. return data, err
  54. }
  55. data.buses, err = getIDs(busesString)
  56. if err != nil {
  57. return data, err
  58. }
  59. return data, nil
  60. }
  61. func calculateTimes(data schedule) schedule {
  62. for i, item := range data.buses {
  63. if item.id == "x" {
  64. continue
  65. }
  66. data.buses[i].value = item.idValue - (data.timestamp % item.idValue)
  67. }
  68. return data
  69. }
  70. func findEarliestBus(data schedule) int64 {
  71. var earliest int64 = data.timestamp
  72. var earliestID int64 = 0
  73. for _, item := range data.buses {
  74. if item.value < earliest {
  75. if item.id == "x" {
  76. continue
  77. }
  78. earliest = item.value
  79. earliestID = item.idValue
  80. }
  81. }
  82. return earliest * earliestID
  83. }
  84. func main() {
  85. if len(os.Args) < 2 {
  86. log.Fatal("You need to specify a file!")
  87. }
  88. file, err := os.Open(os.Args[1])
  89. if err != nil {
  90. log.Fatalf("Failed to open %s!\n", os.Args[1])
  91. }
  92. data, err := readData(file)
  93. if err != nil {
  94. log.Fatalf("Failed to read data: %s\n", err)
  95. }
  96. data = calculateTimes(data)
  97. fmt.Println("Part1:", findEarliestBus(data))
  98. }