Day 19.2 solved.
This commit is contained in:
parent
817a08aba7
commit
f09b1fc787
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user