Day 19.2 solved.

This commit is contained in:
Anna Rose 2020-12-20 04:00:20 +00:00
parent 817a08aba7
commit f09b1fc787

View File

@ -9,16 +9,16 @@ import (
"git.annabunch.es/annabunches/adventofcode/2020/lib/util" "git.annabunch.es/annabunches/adventofcode/2020/lib/util"
) )
type Node struct {
name string
children [][]*Node
}
const ( const (
STATE_RULES = iota STATE_RULES = iota
STATE_DATA STATE_DATA
) )
type Node struct {
name string
children [][]*Node
}
func NewRule(name string) *Node { func NewRule(name string) *Node {
return &Node{ return &Node{
name: name, name: name,
@ -26,8 +26,6 @@ func NewRule(name string) *Node {
} }
} }
var expandRe = regexp.MustCompile("[0-9]+")
func parseRule(name string, rules map[string]string) *Node { func parseRule(name string, rules map[string]string) *Node {
ruleString := rules[name] ruleString := rules[name]
rule := NewRule(name) rule := NewRule(name)
@ -50,12 +48,11 @@ func parseRule(name string, rules map[string]string) *Node {
return rule return rule
} }
func parseInput(input []string) (map[string]bool, []string) { func parseInput(input []string) (map[string]string, []string) {
stateRe := regexp.MustCompile("^([0-9]+): (.*)$") stateRe := regexp.MustCompile("^([0-9]+): (.*)$")
state := STATE_RULES state := STATE_RULES
data := make([]string, 0) data := make([]string, 0)
var root *Node
rules := make(map[string]string) // unparsed rules rules := make(map[string]string) // unparsed rules
for _, line := range input { for _, line := range input {
@ -75,8 +72,11 @@ func parseInput(input []string) (map[string]bool, []string) {
} }
} }
// now parse the rules we stored return rules, data
root = parseRule("0", rules) }
func createLanguage(rules map[string]string, rootName string) map[string]bool {
root := parseRule(rootName, rules)
// now we expand the grammar - generate all possible strings in the language // now we expand the grammar - generate all possible strings in the language
rawLanguage := expand(root) rawLanguage := expand(root)
@ -85,7 +85,7 @@ func parseInput(input []string) (map[string]bool, []string) {
language[term] = true language[term] = true
} }
return language, data return language
} }
// Expand the list of all possible substrings starting with node // Expand the list of all possible substrings starting with node
@ -133,14 +133,62 @@ func combine(terms [][]string, acc string) []string {
} }
func main() { func main() {
// step := os.Args[1] step := os.Args[1]
values := util.InputParserStrings(os.Args[2]) values := util.InputParserStrings(os.Args[2])
language, data := parseInput(values) rules, data := parseInput(values)
count := 0 count := 0
switch step {
case "1":
language := createLanguage(rules, "0")
for _, item := range data { for _, item := range data {
if language[item] { if language[item] {
count++ count++
} }
} }
case "2":
// stub
// for step 2, our base rule expands to 0: 42{N} 31{M}, for N > M and N > 2
// we exploit this, along with the fact that all valid strings for 42 and 31 are
// 8 characters long, to "cheat" a little
matchLength := 8
left := createLanguage(rules, "42")
right := createLanguage(rules, "31")
for _, item := range data {
leftCount := 0
rightCount := 0
onLeft := true
valid := true // valid until proven otherwise
for index := 0; index < len(item); index += matchLength {
if len(item[index:]) < matchLength {
fmt.Println("Bad Length")
valid = false // wrong length alignment
break
}
subString := item[index : index+matchLength]
if onLeft {
if left[subString] {
leftCount++
} else {
onLeft = false
}
}
if !onLeft {
if right[subString] {
rightCount++
} else {
valid = false
break
}
}
}
if valid && leftCount > 1 && rightCount > 0 && leftCount > rightCount {
count++
}
}
}
fmt.Println(count) fmt.Println(count)
} }