Advertisement
itai-nelken

AOC-2021/day-10-part2

Dec 12th, 2021
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 7.64 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.         "bufio"
  5.         "fmt"
  6.         "os"
  7.         "errors"
  8. )
  9.  
  10. type Stack struct {
  11.         data       []int
  12.         sp         uint
  13.         size, step uint
  14. }
  15.  
  16. func NewStack(size, step uint) (stack *Stack, err error) {
  17.         if step == 0 {
  18.                 err = errors.New("step can't be 0")
  19.         } else {
  20.                 err = nil
  21.                 stack = &Stack{
  22.                         data: make([]int, size),
  23.                         size: size,
  24.                         step: step,
  25.                         sp:   0}
  26.         }
  27.         return
  28. }
  29.  
  30. func grow(s *Stack) {
  31.         tmp := make([]int, s.size)
  32.         copy(tmp, s.data)
  33.         s.size += s.step
  34.         s.data = make([]int, s.size)
  35.         copy(s.data, tmp)
  36. }
  37.  
  38. func (s *Stack) Push(data int) {
  39.         if s.sp >= s.size {
  40.                 grow(s)
  41.         }
  42.         s.data[s.sp] = data
  43.         s.sp++
  44. }
  45.  
  46. func (s *Stack) Pop() (popped int) {
  47.         s.sp--
  48.         popped = s.data[s.sp]
  49.         return
  50. }
  51.  
  52. func (s Stack) Peek() int {
  53.         return s.data[s.sp-1]
  54. }
  55.  
  56. func (s Stack) Dump() {
  57.         for i := uint(0); i < s.sp; i++ {
  58.                 fmt.Printf("[%d] %d\n", i, s.data[i])
  59.         }
  60. }
  61.  
  62.  
  63. const INITIAL_STACK_SIZE = 5000
  64.  
  65. const (
  66.         PAREN_OPEN    = iota // 0
  67.         PAREN_CLOSE          // 1
  68.         BRACKET_OPEN         // 2
  69.         BRACKET_CLOSE        // 3
  70.         BRACE_OPEN           // 4
  71.         BRACE_CLOSE          // 5
  72.         AB_OPEN              // AB == angle bracket
  73.         AB_CLOSE             // 7
  74. )
  75.  
  76. type TokenType int8
  77.  
  78. func t2s(t TokenType) (str string) {
  79.         switch t {
  80.         case PAREN_OPEN:
  81.                 str = "PAREN_OPEN"
  82.         case PAREN_CLOSE:
  83.                 str = "PAREN_CLOSE"
  84.         case BRACKET_OPEN:
  85.                 str = "BRACKET_OPEN"
  86.         case BRACKET_CLOSE:
  87.                 str = "BRACKET_CLOSE"
  88.         case BRACE_OPEN:
  89.                 str = "BRACE_OPEN"
  90.         case BRACE_CLOSE:
  91.                 str = "BRACE_CLOSE"
  92.         case AB_OPEN:
  93.                 str = "AB_OPEN"
  94.         case AB_CLOSE:
  95.                 str = "AB_CLOSE"
  96.         default:
  97.                 str = "UNKNOWN"
  98.         }
  99.         return
  100. }
  101.  
  102. func Printfln(format string, a ...interface{}) {
  103.         fmt.Printf(format+"\n", a...)
  104. }
  105.  
  106. func Printerrfln(format string, a ...interface{}) {
  107.         fmt.Fprintf(os.Stderr, format+"\n", a...)
  108. }
  109.  
  110. func assert_err(err error) {
  111.         if err != nil {
  112.                 panic(err.Error())
  113.         }
  114. }
  115.  
  116. func scanLine(txt string, linenum int) (l Line) {
  117.         for _, c := range txt {
  118.                 switch c {
  119.                 case '(':
  120.                         l.types = append(l.types, PAREN_OPEN)
  121.                 case ')':
  122.                         l.types = append(l.types, PAREN_CLOSE)
  123.                 case '[':
  124.                         l.types = append(l.types, BRACKET_OPEN)
  125.                 case ']':
  126.                         l.types = append(l.types, BRACKET_CLOSE)
  127.                 case '{':
  128.                         l.types = append(l.types, BRACE_OPEN)
  129.                 case '}':
  130.                         l.types = append(l.types, BRACE_CLOSE)
  131.                 case '<':
  132.                         l.types = append(l.types, AB_OPEN)
  133.                 case '>':
  134.                         l.types = append(l.types, AB_CLOSE)
  135.                 default:
  136.                         Printerrfln("ERROR: unknown character '%c' in line %d!", c, linenum)
  137.                         os.Exit(1)
  138.                 }
  139.         }
  140.         l.line = linenum
  141.         return
  142. }
  143.  
  144. func ReadInput(filename string) (lines []Line) {
  145.         f, err := os.Open(filename)
  146.         assert_err(err)
  147.         defer f.Close()
  148.  
  149.         sc := bufio.NewScanner(f)
  150.  
  151.         line := 0
  152.         for sc.Scan() {
  153.                 txt := sc.Text()
  154.                 if txt != "" {
  155.                         lines = append(lines, scanLine(txt, line))
  156.                         line++
  157.                 }
  158.         }
  159.         return
  160. }
  161.  
  162. type Line struct {
  163.         types []TokenType
  164.         line  int
  165. }
  166.  
  167. func (l Line) Len() int {
  168.         return len(l.types)
  169. }
  170.  
  171. func (l Line) DumpRaw() {
  172.         Printfln("== line %d ==", l.line)
  173.         for _, t := range l.types {
  174.                 fmt.Printf("| %d ", t)
  175.         }
  176.         fmt.Print("|\n")
  177. }
  178.  
  179. func (l Line) Dump() {
  180.         Printfln("== line %d ==", l.line)
  181.         for _, t := range l.types {
  182.                 fmt.Printf("| %s ", t2s(t))
  183.         }
  184.         fmt.Print("|\n")
  185. }
  186.  
  187. func (l Line) Check() (score int64, ok bool) {
  188.         s, err := NewStack(INITIAL_STACK_SIZE, 2)
  189.         assert_err(err)
  190.         score = 0
  191.  
  192.         s.Push(-1) // BEGIN
  193.         for _, t := range l.types {
  194.                 switch t {
  195.                 case PAREN_OPEN:
  196.                         s.Push(PAREN_OPEN)
  197.                 case BRACKET_OPEN:
  198.                         s.Push(BRACKET_OPEN)
  199.                 case BRACE_OPEN:
  200.                         s.Push(BRACE_OPEN)
  201.                 case AB_OPEN:
  202.                         s.Push(AB_OPEN)
  203.  
  204.                 case PAREN_CLOSE:
  205.                         if TokenType(s.Pop()) != PAREN_OPEN {
  206.                                 //Printerrfln("ERROR (")
  207.                                 ok = false
  208.                                 return
  209.                         }
  210.                 case BRACKET_CLOSE:
  211.                         if TokenType(s.Pop()) != BRACKET_OPEN {
  212.                                 //Printerrfln("ERROR [")
  213.                                 ok = false
  214.                                 return
  215.                         }
  216.                 case BRACE_CLOSE:
  217.                         if TokenType(s.Pop()) != BRACE_OPEN {
  218.                                 //Printerrfln("ERROR {")
  219.                                 ok = false
  220.                                 return
  221.                         }
  222.                 case AB_CLOSE:
  223.                         if TokenType(s.Pop()) != AB_OPEN {
  224.                                 //Printerrfln("ERROR <")
  225.                                 ok = false
  226.                                 return
  227.                         }
  228.                 }
  229.         }
  230.  
  231.         t := TokenType(s.Pop())
  232.         for t != -1 {
  233.                 //Printfln("pop(): %s", t2s(t))
  234.                 score *= 5
  235.                 switch t {
  236.                 case PAREN_OPEN:
  237.                         score += 1
  238.                 case BRACKET_OPEN:
  239.                         score += 2
  240.                 case BRACE_OPEN:
  241.                         score += 3
  242.                 case AB_OPEN:
  243.                         score += 4
  244.                 }
  245.                 t = TokenType(s.Pop())
  246.         }
  247.  
  248.         ok = true
  249.         return
  250. }
  251.  
  252. func sort(scores []int64) int64 {
  253.         for i := 0; i < len(scores); i++ {
  254.                 //fmt.Printf("%ld\n", scores[i]);
  255.                 for j := 1; j < len(scores)-i; j++ {
  256.                         if scores[j-1] > scores[j] {
  257.                                 tmp := scores[j-1]
  258.                                 scores[j-1] = scores[j]
  259.                                 scores[j] = tmp
  260.                         }
  261.                 }
  262.         }
  263.         for i := 0; i < len(scores); i++ {
  264.                 //Printfln("[%d]: %d", i, scores[i])
  265.         }
  266.         return scores[(len(scores)-1)/2]
  267. }
  268.  
  269. func main() {
  270.         input := ReadInput("input.txt")
  271.         scores := []int64{}
  272.  
  273.         for i := 0; i < len(input); i++ {
  274.                 //input[i].Dump()
  275.                 //input[i].DumpRaw()
  276.                 if s, ok := input[i].Check(); ok {
  277.                         scores = append(scores, s)
  278.                 }
  279.                 //fmt.Print("=============\n")
  280.         }
  281.         Printfln("Answer: %d", sort(scores))
  282. }
  283.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement