Day 10 solution
This commit is contained in:
134
ten/navigation.go
Normal file
134
ten/navigation.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package ten
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"sort"
|
||||
)
|
||||
|
||||
var syntaxScores = map[rune]int{
|
||||
')': 3,
|
||||
']': 57,
|
||||
'}': 1197,
|
||||
'>': 25137,
|
||||
}
|
||||
|
||||
var autoCompleteScores = map[rune]int{
|
||||
'(': 1,
|
||||
'[': 2,
|
||||
'{': 3,
|
||||
'<': 4,
|
||||
}
|
||||
|
||||
var pairs = map[rune]rune{
|
||||
')': '(',
|
||||
'}': '{',
|
||||
']': '[',
|
||||
'>': '<',
|
||||
}
|
||||
|
||||
type errorType string
|
||||
|
||||
const (
|
||||
corrupted errorType = "corrupted"
|
||||
incomplete errorType = "incomplete"
|
||||
)
|
||||
|
||||
type syntaxError struct {
|
||||
line string
|
||||
symbol rune
|
||||
violation errorType
|
||||
stack []rune
|
||||
}
|
||||
|
||||
type navigation struct {
|
||||
input []string
|
||||
validInput []string
|
||||
errors []syntaxError
|
||||
}
|
||||
|
||||
func (n *navigation) load(filename string) error {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
n.input = append(n.input, scanner.Text())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *navigation) parse() {
|
||||
for _, input := range n.input {
|
||||
stack := []rune{}
|
||||
var e *syntaxError
|
||||
for _, r := range input {
|
||||
switch r {
|
||||
case '(', '{', '[', '<':
|
||||
stack = append(stack, r)
|
||||
continue
|
||||
case ')', '}', ']', '>':
|
||||
if len(stack) < 1 || stack[len(stack)-1] != pairs[r] {
|
||||
e = &syntaxError{
|
||||
line: input,
|
||||
symbol: r,
|
||||
violation: corrupted,
|
||||
}
|
||||
} else {
|
||||
stack = stack[:len(stack)-1]
|
||||
}
|
||||
}
|
||||
|
||||
if e != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if e == nil && len(stack) > 0 {
|
||||
e = &syntaxError{
|
||||
line: input,
|
||||
symbol: stack[0],
|
||||
violation: incomplete,
|
||||
}
|
||||
}
|
||||
|
||||
if e != nil {
|
||||
e.stack = stack
|
||||
n.errors = append(n.errors, *e)
|
||||
} else {
|
||||
n.validInput = append(n.validInput, input)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (n *navigation) syntaxScore() (score int) {
|
||||
for _, e := range n.errors {
|
||||
if e.violation == corrupted {
|
||||
score += syntaxScores[e.symbol]
|
||||
}
|
||||
}
|
||||
|
||||
return score
|
||||
}
|
||||
|
||||
func (n *navigation) autoCompleteScore() int {
|
||||
scores := []int{}
|
||||
for _, e := range n.errors {
|
||||
if e.violation == incomplete {
|
||||
total := 0
|
||||
for i := len(e.stack) - 1; i >= 0; i-- {
|
||||
total = (total * 5) + autoCompleteScores[e.stack[i]]
|
||||
}
|
||||
scores = append(scores, total)
|
||||
}
|
||||
}
|
||||
|
||||
// Find the middle value
|
||||
sort.Ints(scores)
|
||||
medianIndex := int(len(scores)/2) + 1
|
||||
|
||||
return scores[medianIndex-1]
|
||||
}
|
Reference in New Issue
Block a user