code.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "log"
  6. "os"
  7. "strconv"
  8. "strings"
  9. )
  10. type Node struct {
  11. isExpression bool
  12. greater bool
  13. id string
  14. value int
  15. wrong *Node
  16. right *Node
  17. }
  18. type Workflow struct {
  19. id string
  20. expression *Node
  21. }
  22. func parseExpression(text string) []Node {
  23. var nodes []Node
  24. if !strings.Contains(text, ",") {
  25. var node Node
  26. var parts []string
  27. if strings.Contains(text, ">") {
  28. node.greater = true
  29. parts = strings.Split(text, ">")
  30. } else if strings.Contains(text, "<") {
  31. parts = strings.Split(text, "<")
  32. } else {
  33. node.id = text
  34. nodes = append(nodes, node)
  35. return nodes
  36. }
  37. if len(parts) != 2 {
  38. log.Fatalf("Can't parse expression: %s", text)
  39. }
  40. node.id = parts[0]
  41. n, err := strconv.Atoi(parts[1])
  42. if err != nil {
  43. log.Fatalf("Can't parse a number %s: %s", parts[1], err)
  44. }
  45. node.value = n
  46. nodes = append(nodes, node)
  47. } else {
  48. parts := strings.Split(text, ",")
  49. if len(parts) != 2 {
  50. log.Fatalf("Wrong number of parts from: %s", text)
  51. }
  52. for i := range parts {
  53. if strings.ContainsAny(parts[i], "<>") {
  54. nodes = append(nodes, parseExpression(parts[i])...)
  55. } else {
  56. nodes = append(nodes, Node{id: parts[i]})
  57. }
  58. }
  59. }
  60. return nodes
  61. }
  62. func parseWorkflow(line string) Workflow {
  63. var workflow Workflow
  64. idAndExpression := strings.Split(line, "{")
  65. if len(idAndExpression) != 2 {
  66. log.Fatalf("Can't extract id and expression from: %s", line)
  67. }
  68. workflow.id = idAndExpression[0]
  69. expressions := strings.Split(strings.TrimRight(idAndExpression[1], "}"), ":")
  70. if len(expressions) < 2 {
  71. log.Fatalf("Can't extract expressions from: %s", idAndExpression[1])
  72. }
  73. first := parseExpression(expressions[0])
  74. if len(first) != 1 {
  75. log.Fatalf("First expression should be single one: %s", expressions[0])
  76. }
  77. workflow.expression = &first[0]
  78. current := workflow.expression
  79. for i := 1; i < len(expressions); i++ {
  80. ex := parseExpression(expressions[i])
  81. if len(ex) != 2 {
  82. log.Fatalf("Need two: %s", expressions[i])
  83. }
  84. current.right = &ex[0]
  85. if current.right.isExpression {
  86. current = current.right
  87. }
  88. current.wrong = &ex[1]
  89. if current.wrong.isExpression {
  90. current = current.wrong
  91. }
  92. }
  93. return workflow
  94. }
  95. func readInput(file *os.File) map[string]Workflow {
  96. scanner := bufio.NewScanner(file)
  97. workflows := make(map[string]Workflow)
  98. for scanner.Scan() {
  99. line := scanner.Text()
  100. if line == "" {
  101. break
  102. }
  103. workflow := parseWorkflow(line)
  104. workflows[workflow.id] = workflow
  105. }
  106. return workflows
  107. }
  108. func main() {
  109. if len(os.Args) < 2 {
  110. log.Fatal("You need to specify a file!")
  111. }
  112. filePath := os.Args[1]
  113. file, err := os.Open(filePath)
  114. if err != nil {
  115. log.Fatalf("Failed to open %s!\n", filePath)
  116. }
  117. workflows := readInput(file)
  118. fmt.Println(workflows)
  119. }