day13.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 calculate(buses []bus) int64 {
  85. num := []int64{}
  86. var prod int64 = 1
  87. pp := []int64{}
  88. inv := []int64{}
  89. rem := []int64{}
  90. for i, current := range buses {
  91. if current.id == "x" {
  92. continue
  93. }
  94. num = append(num, current.idValue)
  95. rem = append(rem, int64(i))
  96. prod *= current.idValue
  97. }
  98. for i, _ := range num {
  99. pp = append(pp, prod/num[i])
  100. }
  101. for i, _ := range num {
  102. var x int64 = 1
  103. for {
  104. if (pp[i]*x)%num[i] == 1 {
  105. inv = append(inv, x)
  106. break
  107. }
  108. x++
  109. }
  110. }
  111. var sub int64
  112. for i, _ := range num {
  113. sub += rem[i] * pp[i] * inv[i]
  114. }
  115. return sub % prod
  116. }
  117. func main() {
  118. if len(os.Args) < 2 {
  119. log.Fatal("You need to specify a file!")
  120. }
  121. file, err := os.Open(os.Args[1])
  122. if err != nil {
  123. log.Fatalf("Failed to open %s!\n", os.Args[1])
  124. }
  125. data, err := readData(file)
  126. if err != nil {
  127. log.Fatalf("Failed to read data: %s\n", err)
  128. }
  129. data = calculateTimes(data)
  130. fmt.Println("Part1:", findEarliestBus(data))
  131. fmt.Println("Part2:", calculate(data.buses))
  132. }