Browse Source

day 19, part 2 and part 1 optimized

Juan José Gutiérrez de Quevedo Pérez 4 months ago
parent
commit
ce00017d2d
3 changed files with 139 additions and 34 deletions
  1. 18 34
      19/1.py
  2. 74 0
      19/2.py
  3. 47 0
      19/einput2

+ 18 - 34
19/1.py

@@ -7,43 +7,26 @@ def parse_rule(rule):
     rules = [x.split(" ") for x in rules]
     return name, rules
 
-def expand_rule(rules, rulename):
-    rule = rules[rulename]
-    for i in range(len(rule)):
-        for x in range(len(rule[i])):
-            if rule[i][x].startswith("\""):
-                yield rule[i][x]
-            else:
-                yield list(expand_rule(rules, rules[rulename][i][x]))
-
-def max_length(rules, rule):
-    if rule[0][0].startswith("\""):
-        return 1
-    elif len(rule) == 2:
-        return max_length(rules, [rule[0]])
-    else:
-        retval = 0
-        for x in rule[0]:
-            retval += max_length(rules, rules[x])
-        return retval
-
-def validate_message(rules, rule, message):
-    if max_length(rules, rule) != len(message):
-        return False
+def validate_message(rules, rule, message, pos):
     if rule[0][0].startswith("\""):
-        return rule[0][0][1] == message
+        return rule[0][0][1] == message[pos], pos + 1
     elif len(rule) == 2:
-        l = max_length(rules, [rule[0]])
-        return (validate_message(rules, [rule[0]], message[:l]) or
-                validate_message(rules, [rule[1]], message[:l]))
+        rv1, pos1 = validate_message(rules, [rule[0]], message, pos)
+        rv2, pos2 = validate_message(rules, [rule[1]], message, pos)
+        if rv1:
+            return rv1, pos1
+        elif rv2:
+            return rv2, pos2
+        else:
+            return False, pos
     else:
-        retval = True
-        pos = 0
+        p = pos
         for x in rule[0]:
-            l = max_length(rules, rules[x])
-            retval &= validate_message(rules, rules[x], message[pos:pos+l])
-            pos += l
-        return retval
+            rv, new_p = validate_message(rules, rules[x], message, p)
+            if not rv:
+                return False, pos
+            p = new_p
+        return True, p
 
 part = 0
 rules = {}
@@ -60,7 +43,8 @@ for c in content:
 
 retval = 0
 for m in messages:
-    if validate_message(rules, rules['0'], m):
+    rv, pos = validate_message(rules, rules['0'], m, 0)
+    if rv and pos == len(m):
         retval += 1
 
 print(retval)

+ 74 - 0
19/2.py

@@ -0,0 +1,74 @@
+with open("input") as f:
+    content = [x.strip() for x in f]
+
+def parse_rule(rule):
+    name, rule = rule.split(": ")
+    rules = rule.split(" | ")
+    rules = [x.split(" ") for x in rules]
+    return name, rules
+
+def validate_message(rules, rule, message, pos):
+#    print(f"validating rule {rule} on {message}:{pos}")
+    if rules['11'] == rule:
+        count = 0
+        retval = True
+        while retval:
+            retval, new_p = validate_message(rules, rules['42'], message, pos)
+            if retval:
+                pos = new_p
+                count += 1
+        if count < 2:
+            return False, pos
+        count2 = 0
+        retval = True
+        while retval:
+            retval, new_p = validate_message(rules, rules['31'], message, pos)
+            if retval:
+                pos = new_p
+                count2 += 1
+        if count2 < 1 or count2 >= count:
+            return False, pos
+        return True, pos
+    elif rule[0][0].startswith("\""):
+        if pos >= len(message):
+            return False, pos
+        return rule[0][0][1] == message[pos], pos + 1
+    elif len(rule) == 2:
+        rv1, pos1 = validate_message(rules, [rule[0]], message, pos)
+        rv2, pos2 = validate_message(rules, [rule[1]], message, pos)
+        if rv1:
+            return rv1, pos1
+        elif rv2:
+            return rv2, pos2
+        else:
+            return False, pos
+    else:
+        p = pos
+        for x in rule[0]:
+            rv, new_p = validate_message(rules, rules[x], message, p)
+            if not rv:
+                return False, new_p
+            p = new_p
+        return True, p
+
+part = 0
+rules = {}
+messages = []
+for c in content:
+    if not c:
+        part += 1
+        continue
+    if part == 0: # parsing rules
+        name, rule = parse_rule(c)
+        rules[name] = rule
+    if part == 1: # reading messages
+        messages.append(c)
+
+retval = 0
+for m in messages:
+    rv, pos = validate_message(rules, rules['11'], m, 0)
+    if rv and pos == len(m):
+        print(m)
+        retval += 1
+
+print(retval)

+ 47 - 0
19/einput2

@@ -0,0 +1,47 @@
+42: 9 14 | 10 1
+9: 14 27 | 1 26
+10: 23 14 | 28 1
+1: "a"
+11: 42 31 | 42 11 31
+5: 1 14 | 15 1
+19: 14 1 | 14 14
+12: 24 14 | 19 1
+16: 15 1 | 14 14
+31: 14 17 | 1 13
+6: 14 14 | 1 14
+2: 1 24 | 14 4
+0: 8 11
+13: 14 3 | 1 12
+15: 1 | 14
+17: 14 2 | 1 7
+23: 25 1 | 22 14
+28: 16 1
+4: 1 1
+20: 14 14 | 1 15
+3: 5 14 | 16 1
+27: 1 6 | 14 18
+14: "b"
+21: 14 1 | 1 14
+25: 1 1 | 1 14
+22: 14 14
+8: 42 | 42 8
+26: 14 22 | 1 20
+18: 15 15
+7: 14 5 | 1 21
+24: 14 1
+
+abbbbbabbbaaaababbaabbbbabababbbabbbbbbabaaaa
+bbabbbbaabaabba
+babbbbaabbbbbabbbbbbaabaaabaaa
+aaabbbbbbaaaabaababaabababbabaaabbababababaaa
+bbbbbbbaaaabbbbaaabbabaaa
+bbbababbbbaaaaaaaabbababaaababaabab
+ababaaaaaabaaab
+ababaaaaabbbaba
+baabbaaaabbaaaababbaababb
+abbbbabbbbaaaababbbbbbaaaababb
+aaaaabbaabaaaaababaa
+aaaabbaaaabbaaa
+aaaabbaabbaaaaaaabbbabbbaaabbaabaaa
+babaaabbbaaabaababbaabababaaab
+aabbbbbaabbbaaaaaabbbbbababaaaaabbaaabba