1
0

day5.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package main
  2. import (
  3. "bufio"
  4. "flag"
  5. "fmt"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. func main() {
  11. args := flag.Bool("example", false, "example or input")
  12. flag.Parse()
  13. filename := "input.txt"
  14. if *args {
  15. filename = "example.txt"
  16. }
  17. file, err := os.Open(filename)
  18. if err != nil {
  19. fmt.Println(err)
  20. return
  21. }
  22. defer file.Close()
  23. scanner := bufio.NewScanner(file)
  24. var rules []string
  25. var updates [][]int
  26. readingRules := true
  27. for scanner.Scan() {
  28. line := strings.TrimSpace(scanner.Text())
  29. if line == "" {
  30. readingRules = false
  31. continue
  32. }
  33. if readingRules {
  34. rules = append(rules, line)
  35. } else {
  36. update := parseUpdate(line)
  37. updates = append(updates, update)
  38. }
  39. }
  40. if err := scanner.Err(); err != nil {
  41. fmt.Println(err)
  42. return
  43. }
  44. orderRules := parseRules(rules)
  45. totalSum := 0
  46. totalCorrectedSum := 0
  47. for _, update := range updates {
  48. if isValidUpdate(update, orderRules) {
  49. middle := findMiddlePage(update)
  50. totalSum += middle
  51. } else {
  52. // fmt.Println("us", update)
  53. correctedUpdate := orderUpdate(update, orderRules)
  54. // fmt.Println("cc", correctedUpdate, "\n")
  55. totalCorrectedSum += findMiddlePage(correctedUpdate)
  56. }
  57. }
  58. fmt.Println("Total Sum:", totalSum)
  59. fmt.Println("Total Corrected Sum:", totalCorrectedSum)
  60. }
  61. func parseRules(rules []string) map[int][]int {
  62. ruleMap := make(map[int][]int)
  63. for _, rule := range rules {
  64. parts := strings.Split(rule, "|")
  65. x, _ := strconv.Atoi(parts[0])
  66. y, _ := strconv.Atoi(parts[1])
  67. ruleMap[x] = append(ruleMap[x], y)
  68. }
  69. return ruleMap
  70. }
  71. func parseUpdate(line string) []int {
  72. parts := strings.Split(line, ",")
  73. var update []int
  74. for _, part := range parts {
  75. num, _ := strconv.Atoi(strings.TrimSpace(part))
  76. update = append(update, num)
  77. }
  78. return update
  79. }
  80. func isValidUpdate(update []int, rules map[int][]int) bool {
  81. position := make(map[int]int)
  82. for i, page := range update {
  83. position[page] = i
  84. }
  85. for x, ys := range rules {
  86. for _, y := range ys {
  87. posX, existsX := position[x]
  88. posY, existsY := position[y]
  89. if existsX && existsY && posX >= posY {
  90. return false
  91. }
  92. }
  93. }
  94. return true
  95. }
  96. func orderUpdate(update []int, rules map[int][]int) []int {
  97. // we have overkill topological sort here, fuck yeah.
  98. graph := make(map[int][]int)
  99. inDegree := make(map[int]int)
  100. pageSet := make(map[int]bool)
  101. for _, page := range update {
  102. pageSet[page] = true
  103. inDegree[page] = 0
  104. }
  105. for x, ys := range rules {
  106. if !pageSet[x] {
  107. continue
  108. }
  109. for _, y := range ys {
  110. if pageSet[y] {
  111. graph[x] = append(graph[x], y)
  112. inDegree[y]++
  113. }
  114. }
  115. }
  116. var ordered []int
  117. queue := []int{}
  118. for _, page := range update {
  119. if inDegree[page] == 0 {
  120. queue = append(queue, page)
  121. }
  122. }
  123. for len(queue) > 0 {
  124. current := queue[0]
  125. queue = queue[1:]
  126. ordered = append(ordered, current)
  127. for _, neighbor := range graph[current] {
  128. inDegree[neighbor]--
  129. if inDegree[neighbor] == 0 {
  130. queue = append(queue, neighbor)
  131. }
  132. }
  133. }
  134. if len(ordered) != len(update) {
  135. fmt.Println("len corrected doesn't match", len(ordered), len(update))
  136. return nil
  137. }
  138. return ordered
  139. }
  140. func findMiddlePage(update []int) int {
  141. mid := len(update) / 2
  142. return update[mid]
  143. }