11 "pi7 = \"\"\"lf AND lq -> ls\n",
12 "iu RSHIFT 1 -> jn\n",
14 "gj RSHIFT 1 -> hc\n",
15 "et RSHIFT 2 -> eu\n",
25 "lf RSHIFT 2 -> lg\n",
26 "dd RSHIFT 3 -> df\n",
29 "ip LSHIFT 15 -> it\n",
32 "fj LSHIFT 15 -> fn\n",
37 "et RSHIFT 1 -> fm\n",
39 "dd RSHIFT 2 -> de\n",
43 "jm LSHIFT 1 -> kg\n",
45 "jp RSHIFT 2 -> jq\n",
46 "jp RSHIFT 5 -> js\n",
48 "eo LSHIFT 15 -> es\n",
51 "ci RSHIFT 3 -> ck\n",
55 "jk LSHIFT 15 -> jo\n",
56 "iu RSHIFT 3 -> iw\n",
59 "bn RSHIFT 3 -> bp\n",
66 "gj RSHIFT 5 -> gm\n",
68 "dy RSHIFT 1 -> er\n",
71 "bk LSHIFT 1 -> ce\n",
73 "bi LSHIFT 15 -> bm\n",
76 "as RSHIFT 1 -> bl\n",
77 "lf RSHIFT 3 -> lh\n",
80 "ci RSHIFT 1 -> db\n",
84 "hz RSHIFT 2 -> ia\n",
85 "kh LSHIFT 1 -> lb\n",
91 "gz LSHIFT 15 -> hd\n",
102 "bn RSHIFT 1 -> cg\n",
109 "hz RSHIFT 3 -> ib\n",
112 "dy RSHIFT 2 -> dz\n",
113 "kk RSHIFT 2 -> kl\n",
116 "jp RSHIFT 1 -> ki\n",
122 "as RSHIFT 5 -> av\n",
123 "lf RSHIFT 5 -> li\n",
127 "ge LSHIFT 15 -> gi\n",
131 "cd LSHIFT 15 -> ch\n",
134 "bn RSHIFT 2 -> bo\n",
145 "jp RSHIFT 3 -> jr\n",
148 "gj RSHIFT 2 -> gk\n",
151 "ap LSHIFT 1 -> bj\n",
153 "ir LSHIFT 1 -> jl\n",
155 "lv LSHIFT 15 -> lz\n",
157 "cy LSHIFT 15 -> dc\n",
159 "x RSHIFT 1 -> aq\n",
164 "fl LSHIFT 1 -> gf\n",
167 "et RSHIFT 5 -> ew\n",
168 "iu RSHIFT 2 -> iv\n",
174 "da LSHIFT 1 -> du\n",
175 "fo RSHIFT 2 -> fp\n",
180 "hu LSHIFT 15 -> hy\n",
182 "fo RSHIFT 3 -> fq\n",
184 "hw LSHIFT 1 -> iq\n",
185 "dd RSHIFT 1 -> dw\n",
186 "dt LSHIFT 15 -> dx\n",
188 "an LSHIFT 15 -> ar\n",
193 "et RSHIFT 3 -> ev\n",
201 "iu RSHIFT 5 -> ix\n",
206 "lf RSHIFT 1 -> ly\n",
210 "gg LSHIFT 1 -> ha\n",
213 "he RSHIFT 3 -> hg\n",
216 "dy RSHIFT 5 -> eb\n",
223 "dy RSHIFT 3 -> ea\n",
227 "cf LSHIFT 1 -> cz\n",
232 "x RSHIFT 5 -> aa\n",
233 "dv LSHIFT 1 -> ep\n",
234 "he RSHIFT 2 -> hf\n",
242 "kk RSHIFT 3 -> km\n",
245 "lc LSHIFT 1 -> lw\n",
250 "ci RSHIFT 5 -> cl\n",
251 "hz RSHIFT 1 -> is\n",
259 "eq LSHIFT 1 -> fk\n",
260 "gj RSHIFT 3 -> gl\n",
261 "u LSHIFT 1 -> ao\n",
270 "he RSHIFT 1 -> hx\n",
274 "kk RSHIFT 5 -> kn\n",
278 "s LSHIFT 15 -> w\n",
279 "fo RSHIFT 1 -> gh\n",
281 "bn RSHIFT 5 -> bq\n",
288 "ci RSHIFT 2 -> cj\n",
291 "dd RSHIFT 5 -> dg\n",
299 "kf LSHIFT 15 -> kj\n",
301 "fo RSHIFT 5 -> fr\n",
305 "kk RSHIFT 1 -> ld\n",
306 "hz RSHIFT 5 -> ic\n",
307 "as RSHIFT 2 -> at\n",
314 "la LSHIFT 15 -> le\n",
326 "hb LSHIFT 1 -> hv\n",
335 "as RSHIFT 3 -> au\n",
349 "he RSHIFT 5 -> hh\"\"\""
354 "execution_count": 2,
360 "pi7 = open('advent07.txt').read().strip()"
365 "execution_count": 3,
371 "from collections import namedtuple\n",
373 "Rule = namedtuple('Rule', ['command', 'antecedents', 'consequence'])"
378 "execution_count": 4,
384 "def parse_arg(arg):\n",
386 " # return int(arg)\n",
387 " #except ValueError:\n",
389 " if arg.isnumeric():\n",
390 " return int(arg)\n",
394 "def parse_rule(text):\n",
395 " tokens = text.strip().split(' ')\n",
396 " if tokens[0] == 'NOT':\n",
397 " rule = Rule(command=tokens[0], antecedents=[parse_arg(tokens[1])], consequence=tokens[3])\n",
398 " elif len(tokens) == 3:\n",
399 " rule = Rule(command='ASSIGN', antecedents=[parse_arg(tokens[0])], consequence=tokens[2])\n",
401 " rule = Rule(command=tokens[1], antecedents=[parse_arg(tokens[0]), parse_arg(tokens[2])], consequence=tokens[4])\n",
407 "execution_count": 5,
414 "output_type": "stream",
416 "123 -> x: Rule(command='ASSIGN', antecedents=[123], consequence='x')\n",
417 "456 -> y: Rule(command='ASSIGN', antecedents=[456], consequence='y')\n",
418 "x AND y -> d: Rule(command='AND', antecedents=['x', 'y'], consequence='d')\n",
419 "x OR y -> e: Rule(command='OR', antecedents=['x', 'y'], consequence='e')\n",
420 "x LSHIFT 2 -> f: Rule(command='LSHIFT', antecedents=['x', 2], consequence='f')\n",
421 "y RSHIFT 2 -> g: Rule(command='RSHIFT', antecedents=['y', 2], consequence='g')\n",
422 "NOT x -> h: Rule(command='NOT', antecedents=['x'], consequence='h')\n",
423 "NOT y -> i: Rule(command='NOT', antecedents=['y'], consequence='i')\n",
424 "lx -> zz: Rule(command='ASSIGN', antecedents=['lx'], consequence='zz')\n"
429 "for r in ['123 -> x', '456 -> y', 'x AND y -> d', 'x OR y -> e', 'x LSHIFT 2 -> f', \n",
430 " 'y RSHIFT 2 -> g', 'NOT x -> h', 'NOT y -> i', 'lx -> zz']:\n",
431 " print(r, end=': ')\n",
432 " print(parse_rule(r))"
437 "execution_count": 6,
443 "def rule_can_fire(rule, known_values):\n",
444 " return all(isinstance(a, int) or a in known_values for a in rule.antecedents)"
449 "execution_count": 7,
460 "execution_count": 7,
462 "output_type": "execute_result"
466 "rule_can_fire(parse_rule('NOT y -> f'), {'y': 12})"
471 "execution_count": 8,
477 "def get_value(arg, known_values):\n",
478 " if arg in known_values:\n",
479 " return known_values[arg]\n",
483 "def fire_rule(rule, known_values):\n",
484 " evaluated_args = [get_value(arg, known_values) for arg in rule.antecedents]\n",
485 " if rule.command == 'ASSIGN':\n",
486 " known_values[rule.consequence] = evaluated_args[0]\n",
487 " elif rule.command == 'NOT':\n",
488 " known_values[rule.consequence] = ~evaluated_args[0] % 65536\n",
489 " elif rule.command == 'LSHIFT':\n",
490 " known_values[rule.consequence] = (evaluated_args[0] << evaluated_args[1]) % 65536\n",
491 " elif rule.command == 'RSHIFT':\n",
492 " known_values[rule.consequence] = (evaluated_args[0] >> evaluated_args[1]) % 65536\n",
493 " elif rule.command == 'AND':\n",
494 " known_values[rule.consequence] = (evaluated_args[0] & evaluated_args[1]) % 65536\n",
495 " elif rule.command == 'OR':\n",
496 " known_values[rule.consequence] = (evaluated_args[0] | evaluated_args[1]) % 65536"
501 "execution_count": 9,
512 "execution_count": 9,
514 "output_type": "execute_result"
523 "execution_count": 10,
534 "execution_count": 10,
536 "output_type": "execute_result"
540 "rules = [parse_rule(r) for r in pi7.splitlines()]\n",
546 "execution_count": 11,
557 "execution_count": 11,
559 "output_type": "execute_result"
564 "while 'a' not in known:\n",
565 " for r in rules:\n",
566 " if rule_can_fire(r, known) and r.consequence not in known:\n",
567 " fire_rule(r, known)\n",
573 "execution_count": 12,
584 "execution_count": 12,
586 "output_type": "execute_result"
590 "known = {'b': 16076}\n",
591 "while 'a' not in known:\n",
592 " for r in rules:\n",
593 " if rule_can_fire(r, known) and r.consequence not in known:\n",
594 " fire_rule(r, known)\n",
600 "execution_count": 13,
949 "execution_count": 13,
951 "output_type": "execute_result"
960 "execution_count": null,
970 "display_name": "Python 3",
971 "language": "python",
979 "file_extension": ".py",
980 "mimetype": "text/x-python",
982 "nbconvert_exporter": "python",
983 "pygments_lexer": "ipython3",