package main import ( "bufio" "fmt" "log" "os" "sort" "strings" ) type Stack []string func (s *Stack) push(i string) { *s = append(*s, i) } func (s *Stack) pop() string { ret := s.peek() *s = (*s)[:len(*s)-1] return ret } func (s *Stack) peek() string { return (*s)[len(*s)-1] } func main() { file, err := os.Open("input.txt") if err != nil { log.Fatal(err) } defer file.Close() scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanLines) var errorTotal int var completionTotals []int for scanner.Scan() { line := scanner.Text() errorScore, completionScore := solve(line) errorTotal += errorScore if completionScore > 0 { completionTotals = append(completionTotals, completionScore) } } sort.Ints(completionTotals) fmt.Println(errorTotal, completionTotals[len(completionTotals)/2]) } func solve(line string) (errorScore, completionScore int) { blah := strings.Split(line, "") var s Stack for _, v := range blah { if len(s) == 0 || isOpening(v) { s.push(v) continue } if getClosing(s.peek()) != v { //fmt.Println("Corruption: expected " + getClosing(s.peek()) + " but got " + v) return getErrorScore(v), -1 } else { s.pop() } } for len(s) > 0 { completionScore *= 5 completionScore += getCompletionScore(getClosing(s.pop())) } return } func isOpening(test string) bool { return test == "[" || test == "(" || test == "<" || test == "{" } func getClosing(opening string) string { switch opening { case "[": return "]" case "(": return ")" case "<": return ">" case "{": return "}" default: return "Unhandled chunk" } } func getErrorScore(closing string) int { switch closing { case ")": return 3 case "]": return 57 case "}": return 1197 case ">": return 25137 default: fmt.Println("Unhandled error score for " + closing) return -1 } } func getCompletionScore(closing string) int { switch closing { case ")": return 1 case "]": return 2 case "}": return 3 case ">": return 4 default: fmt.Println("Unhandled completion score for " + closing) return -1 } }