Compare commits

...

480 commits

Author SHA1 Message Date
Bruno BELANYI eb9c25af5a nix: simplify direnv integration
Rely on my having installed `nix-direnv`.
2024-11-23 19:22:06 +00:00
Bruno BELANYI 120a42f1b0 nix: migrate to 'ruff' formatting
Having just the one tool is better.

Incidentally, this fixes the ternary formatting, which was messed up in
recent `black` versions.
2024-11-23 18:45:57 +00:00
Bruno BELANYI 8618c81b2f nix: bump flake inputs 2024-11-23 18:42:21 +00:00
Bruno BELANYI 67ef6227dc 2023: d25: ex2: add solution 2023-12-25 17:20:40 +01:00
Bruno BELANYI c1ef85e59b 2023: d25: ex2: add input 2023-12-25 17:20:34 +01:00
Bruno BELANYI b80a75858d 2023: d25: ex1: add solution 2023-12-25 17:20:26 +01:00
Bruno BELANYI 061af7c1d1 2023: d25: ex1: add input 2023-12-25 17:20:09 +01:00
Bruno BELANYI b004a8fae7 2023: d24: ex2: add solution 2023-12-24 13:35:25 +01:00
Bruno BELANYI 0c23bd9eee 2023: d24: ex2: add input 2023-12-24 13:35:20 +01:00
Bruno BELANYI 03d3cf2210 2023: d24: ex1: add solution 2023-12-24 13:35:15 +01:00
Bruno BELANYI eca3f7bd59 2023: d24: ex1: add input 2023-12-24 13:35:10 +01:00
Bruno BELANYI 4047f428e1 2023: d23: ex2: add solution 2023-12-23 10:57:23 +01:00
Bruno BELANYI a42da85f1f 2023: d23: ex2: add input 2023-12-23 10:57:18 +01:00
Bruno BELANYI 1204116d6f 2023: d23: ex1: add solution 2023-12-23 10:57:13 +01:00
Bruno BELANYI 7017b91d91 2023: d23: ex1: add input 2023-12-23 10:57:08 +01:00
Bruno BELANYI 8b58cedff2 2023: d22: ex2: add solution 2023-12-22 15:30:25 +01:00
Bruno BELANYI a734b0d292 2023: d22: ex2: add input 2023-12-22 15:30:19 +01:00
Bruno BELANYI a69212b0ee 2023: d22: ex1: add solution 2023-12-22 15:29:36 +01:00
Bruno BELANYI 6fbc38b565 2023: d22: ex1: add input 2023-12-22 15:29:27 +01:00
Bruno BELANYI 0f949820e1 2023: d21: ex2: add solution 2023-12-21 10:54:01 +01:00
Bruno BELANYI 5e8eb3d7f2 2023: d21: ex2: add input 2023-12-21 10:53:56 +01:00
Bruno BELANYI 4c11e798bd 2023: d21: ex1: add solution 2023-12-21 10:53:48 +01:00
Bruno BELANYI 3837f06467 2023: d21: ex1: add input 2023-12-21 10:53:43 +01:00
Bruno BELANYI 1a0a231bd7 2023: d20: ex2: add solution 2023-12-20 11:18:49 +01:00
Bruno BELANYI 781e51b3a0 2023: d20: ex2: add input 2023-12-20 11:18:43 +01:00
Bruno BELANYI c8e0e82c12 2023: d20: ex1: add solution 2023-12-20 11:18:38 +01:00
Bruno BELANYI 70cbe0d6f2 2023: d20: ex1: add input 2023-12-20 11:18:33 +01:00
Bruno BELANYI 06f3c8f169 2023: d19: ex2: add solution 2023-12-19 19:12:22 +01:00
Bruno BELANYI a18f882c1a 2023: d19: ex2: add input 2023-12-19 17:58:03 +00:00
Bruno BELANYI e795c9cee8 2023: d19: ex1: add solution 2023-12-19 17:57:57 +00:00
Bruno BELANYI 8f8e37b42d 2023: d19: ex1: add input 2023-12-19 17:57:51 +00:00
Bruno BELANYI 57f28d6411 2023: d18: ex2: add solution 2023-12-18 08:03:12 +00:00
Bruno BELANYI 7e2489f5f9 2023: d18: ex2: add input 2023-12-18 08:03:06 +00:00
Bruno BELANYI f9c1e152c3 2023: d18: ex1: add solution 2023-12-18 08:02:58 +00:00
Bruno BELANYI bb2bee9c6e 2023: d18: ex1: add input 2023-12-18 08:02:53 +00:00
Bruno BELANYI 122b81ed15 2023: d17: ex2: add solution 2023-12-17 12:00:41 +00:00
Bruno BELANYI d5694f2bd3 2023: d17: ex2: add input 2023-12-17 11:59:21 +00:00
Bruno BELANYI 5215e97077 2023: d17: ex1: add solution 2023-12-17 11:59:15 +00:00
Bruno BELANYI 1be0b68503 2023: d17: ex1: add input 2023-12-17 11:59:10 +00:00
Bruno BELANYI 8f6fc416fb 2023: d16: ex2: add solution 2023-12-16 11:13:00 +00:00
Bruno BELANYI 61e32bde3d 2023: d16: ex2: add input 2023-12-16 11:12:54 +00:00
Bruno BELANYI 97b4a3c7b3 2023: d16: ex1: add solution 2023-12-16 11:12:48 +00:00
Bruno BELANYI f62c625850 2023: d16: ex1: add input 2023-12-16 11:12:42 +00:00
Bruno BELANYI d15f807bd1 2023: d15: ex2: add solution 2023-12-15 10:59:09 +00:00
Bruno BELANYI 90ebcbebd8 2023: d15: ex2: add input 2023-12-15 10:59:05 +00:00
Bruno BELANYI 38dc59b16d 2023: d15: ex1: add solution 2023-12-15 10:58:59 +00:00
Bruno BELANYI 1e7d41b861 2023: d15: ex1: add input 2023-12-15 10:58:54 +00:00
Bruno BELANYI 572d03ae1d 2023: d14: ex2: add solution 2023-12-14 10:43:13 +00:00
Bruno BELANYI f8b27ddff8 2023: d14: ex2: add input 2023-12-14 10:43:09 +00:00
Bruno BELANYI 3f2c16d8a8 2023: d14: ex1: add solution 2023-12-14 10:43:03 +00:00
Bruno BELANYI 307381a434 2023: d14: ex1: add input 2023-12-14 10:42:55 +00:00
Bruno BELANYI d8f472ec43 2023: d13: ex2: add solution 2023-12-13 10:10:51 +00:00
Bruno BELANYI 21986b1148 2023: d13: ex2: add input 2023-12-13 10:10:51 +00:00
Bruno BELANYI 9f7c2a6448 2023: d13: ex1: add solution 2023-12-13 10:10:51 +00:00
Bruno BELANYI bd396f32d7 2023: d13: ex1: add input 2023-12-13 10:10:51 +00:00
Bruno BELANYI d2e2d79d71 2023: d12: ex2: add solution 2023-12-12 19:29:49 +01:00
Bruno BELANYI 15b8b5aaeb 2023: d12: ex2: add input 2023-12-12 19:29:49 +01:00
Bruno BELANYI 70fdb4e606 2023: d12: ex1: add solution 2023-12-12 19:29:49 +01:00
Bruno BELANYI f8c387c5a6 2023: d12: ex1: add input 2023-12-12 10:23:56 +00:00
Bruno BELANYI f31434d9c6 2023: d11: ex2: add solution 2023-12-11 07:18:35 +00:00
Bruno BELANYI abf3b5e66c 2023: d11: ex2: add input 2023-12-11 07:18:35 +00:00
Bruno BELANYI c46be2b190 2023: d11: ex1: add solution 2023-12-11 07:18:35 +00:00
Bruno BELANYI 933fc2da0b 2023: d11: ex1: add input 2023-12-11 07:05:49 +00:00
Bruno BELANYI 9bbb769a9b 2023: d10: ex2: add solution 2023-12-10 19:27:44 +00:00
Bruno BELANYI 7cf50212b4 2023: d10: ex2: add input 2023-12-10 12:48:14 +00:00
Bruno BELANYI 8692f6c401 2023: d10: ex1: add solution 2023-12-10 12:48:09 +00:00
Bruno BELANYI a4e14d1245 2023: d10: ex1: add input 2023-12-10 12:48:03 +00:00
Bruno BELANYI 8e5433a642 2023: d09: ex2: add solution 2023-12-09 09:51:32 +00:00
Bruno BELANYI f4e3d977c2 2023: d09: ex2: add input 2023-12-09 09:47:19 +00:00
Bruno BELANYI d5842f92be 2023: d09: ex1: add solution 2023-12-09 09:47:13 +00:00
Bruno BELANYI 6f31630af7 2023: d09: ex1: add input 2023-12-09 09:47:07 +00:00
Bruno BELANYI a310f24d8e 2023: d08: ex2: add solution 2023-12-08 08:23:16 +00:00
Bruno BELANYI 348ce5b369 2023: d08: ex2: add input 2023-12-08 08:23:11 +00:00
Bruno BELANYI 34e16218b8 2023: d08: ex1: add solution 2023-12-08 08:23:05 +00:00
Bruno BELANYI dcce8c1eec 2023: d08: ex1: add input 2023-12-08 08:22:59 +00:00
Bruno BELANYI ad9ddd69e5 2023: d07: ex2: add solution 2023-12-07 08:56:49 +00:00
Bruno BELANYI 4f5138adb8 2023: d07: ex2: add input 2023-12-07 08:56:44 +00:00
Bruno BELANYI 73ee756062 2023: d07: ex1: add solution 2023-12-07 08:56:39 +00:00
Bruno BELANYI 245a07bbdd 2023: d07: ex1: add input 2023-12-07 08:56:34 +00:00
Bruno BELANYI 13437c7bd6 2023: d06: ex2: add solution 2023-12-06 09:16:14 +00:00
Bruno BELANYI dda2adcb6e 2023: d06: ex2: add input 2023-12-06 09:16:09 +00:00
Bruno BELANYI c329b034a6 2023: d06: ex1: add solution 2023-12-06 09:16:02 +00:00
Bruno BELANYI bacc167481 2023: d06: ex1: add input 2023-12-06 09:15:54 +00:00
Bruno BELANYI 3afecbf47e 2023: d05: ex2: add solution 2023-12-05 20:06:23 +00:00
Bruno BELANYI 0a65ff5789 2023: d05: ex2: add input 2023-12-05 20:06:18 +00:00
Bruno BELANYI 7a7ba0b454 2023: d05: ex1: add solution 2023-12-05 20:06:13 +00:00
Bruno BELANYI d45398d1e9 2023: d05: ex1: add input 2023-12-05 20:06:07 +00:00
Bruno BELANYI 10faba0e78 2023: d04: ex2: add solution 2023-12-04 11:10:54 +00:00
Bruno BELANYI 3e34da7b31 2023: d04: ex2: add input 2023-12-04 11:10:48 +00:00
Bruno BELANYI 831b3606b4 2023: d04: ex1: add solution 2023-12-04 11:10:40 +00:00
Bruno BELANYI f659487d80 2023: d04: ex1: add input 2023-12-04 11:10:34 +00:00
Bruno BELANYI bdd585fec7 2023: d03: ex2: add solution 2023-12-04 11:10:05 +00:00
Bruno BELANYI 3d6780146b 2023: d03: ex2: add input 2023-12-04 11:10:05 +00:00
Bruno BELANYI d52a3a1e59 2023: d03: ex1: add solution 2023-12-04 11:10:05 +00:00
Bruno BELANYI 2923fd5dcc 2023: d03: ex1: add input 2023-12-03 15:16:50 +00:00
Bruno BELANYI 1193810e57 2023: d02: ex2: add solution 2023-12-02 09:41:43 +00:00
Bruno BELANYI 8ab447e917 2023: d02: ex2: add input 2023-12-02 09:41:43 +00:00
Bruno BELANYI 65c087a68b 2023: d02: ex1: add solution 2023-12-02 09:41:43 +00:00
Bruno BELANYI 078dfd94e7 2023: d02: ex1: add input 2023-12-02 09:21:39 +00:00
Bruno BELANYI 52ecb598bc 2023: d01: ex2: add solution 2023-12-01 19:28:29 +00:00
Bruno BELANYI 8df335ba05 2023: d01: ex2: add input 2023-12-01 19:28:29 +00:00
Bruno BELANYI 447467ef6e 2023: d01: ex1: add solution 2023-12-01 19:28:29 +00:00
Bruno BELANYI 1039b4c0ac 2023: d01: ex1: add input 2023-12-01 19:28:29 +00:00
Bruno BELANYI a53f99d841 nix: bump flake inputs 2023-12-01 19:28:29 +00:00
Bruno BELANYI 37d878da27 nix: use 'main' branch for 'flake-utils' 2023-12-01 19:28:29 +00:00
Bruno BELANYI 53c344b223 2022: d25: ex2: add solution 2022-12-25 11:25:25 +01:00
Bruno BELANYI 5bbf42ef1b 2022: d25: ex2: add input 2022-12-25 11:25:20 +01:00
Bruno BELANYI 92cabbda8f 2022: d25: ex1: add solution 2022-12-25 11:24:28 +01:00
Bruno BELANYI addda451ef 2022: d25: ex1: add input 2022-12-25 11:24:20 +01:00
Bruno BELANYI d1194e8c5f 2022: d24: ex2: add solution 2022-12-24 14:54:26 +01:00
Bruno BELANYI 7759412af3 2022: d24: ex2: add input 2022-12-24 14:54:21 +01:00
Bruno BELANYI 4211451deb 2022: d24: ex1: add solution 2022-12-24 14:54:13 +01:00
Bruno BELANYI 1562f97efc 2022: d24: ex1: add input 2022-12-24 14:53:14 +01:00
Bruno BELANYI 1c57181989 2022: d23: ex2: add solution 2022-12-23 10:00:35 +01:00
Bruno BELANYI e8cbc17839 2022: d23: ex2: add input 2022-12-23 10:00:30 +01:00
Bruno BELANYI 2ce03834e4 2022: d23: ex1: add solution 2022-12-23 10:00:24 +01:00
Bruno BELANYI f3af387265 2022: d23: ex1: add input 2022-12-23 10:00:19 +01:00
Bruno BELANYI 43b78a23c5 2022: d22: ex2: add solution 2022-12-22 16:23:41 +01:00
Bruno BELANYI a4d483e01c 2022: d22: ex2: add input 2022-12-22 16:23:36 +01:00
Bruno BELANYI eeaf6956e5 2022: d22: ex1: add solution 2022-12-22 16:23:29 +01:00
Bruno BELANYI b819e62da4 2022: d22: ex1: add input 2022-12-22 16:23:23 +01:00
Bruno BELANYI 992cbd34f4 2022: d21: ex2: add solution 2022-12-21 12:54:43 +01:00
Bruno BELANYI c7bb07d13a 2022: d21: ex2: add input 2022-12-21 12:54:39 +01:00
Bruno BELANYI 810101024f 2022: d21: ex1: add solution 2022-12-21 12:54:33 +01:00
Bruno BELANYI e1dc373b69 2022: d21: ex1: add input 2022-12-21 12:54:28 +01:00
Bruno BELANYI 3e5502e3d8 2022: d20: ex2: add solution 2022-12-20 13:45:09 +01:00
Bruno BELANYI 5d6ef372de 2022: d20: ex2: add input 2022-12-20 13:45:02 +01:00
Bruno BELANYI 8881d00b55 2022: d20: ex1: add solution 2022-12-20 13:44:56 +01:00
Bruno BELANYI 31fbfaaead 2022: d20: ex1: add input 2022-12-20 13:44:51 +01:00
Bruno BELANYI 1392358ada 2022: d19: ex2: add solution 2022-12-19 12:20:55 +01:00
Bruno BELANYI 076126ec41 2022: d19: ex2: add input 2022-12-19 12:20:49 +01:00
Bruno BELANYI 64ae3b2a59 2022: d19: ex1: add solution 2022-12-19 12:20:44 +01:00
Bruno BELANYI 69055425f0 2022: d19: ex1: add input 2022-12-19 12:20:39 +01:00
Bruno BELANYI 8e8e26f2d6 2022: d18: ex2: add solution 2022-12-18 12:47:06 +01:00
Bruno BELANYI 1743b72d82 2022: d18: ex2: add input 2022-12-18 12:44:45 +01:00
Bruno BELANYI a57da6fcfe 2022: d18: ex1: add solution 2022-12-18 12:44:40 +01:00
Bruno BELANYI ef8b11d2d3 2022: d18: ex1: add input 2022-12-18 12:44:35 +01:00
Bruno BELANYI e18d783d39 2022: d17: ex2: add solution 2022-12-17 12:52:34 +01:00
Bruno BELANYI e509e6fd4b 2022: d17: ex2: add input 2022-12-17 12:52:29 +01:00
Bruno BELANYI ce88300254 2022: d17: ex1: add solution 2022-12-17 12:52:24 +01:00
Bruno BELANYI fa883c71c0 2022: d17: ex1: add input 2022-12-17 12:52:18 +01:00
Bruno BELANYI 1cee160cad 2022: d16: ex2: add solution 2022-12-16 10:38:09 +01:00
Bruno BELANYI 7009315b66 2022: d16: ex2: add input 2022-12-16 10:38:04 +01:00
Bruno BELANYI 6355c9c84d 2022: d16: ex1: add solution 2022-12-16 10:37:59 +01:00
Bruno BELANYI 0587294ccf 2022: d16: ex1: add input 2022-12-16 10:37:52 +01:00
Bruno BELANYI 14e8b539c6 2022: d15: ex2: add solution 2022-12-15 17:15:57 +01:00
Bruno BELANYI 0f91c37d6d 2022: d15: ex2: add input 2022-12-15 17:15:57 +01:00
Bruno BELANYI 1ce063154e 2022: d15: ex1: add solution 2022-12-15 17:15:57 +01:00
Bruno BELANYI da042bea7d 2022: d15: ex1: add input 2022-12-15 11:14:21 +01:00
Bruno BELANYI a9c325ce14 2022: d14: ex2: add solution 2022-12-14 15:00:48 +01:00
Bruno BELANYI e457aaed44 2022: d14: ex2: add input 2022-12-14 15:00:48 +01:00
Bruno BELANYI 2c486e5984 2022: d14: ex1: add solution 2022-12-14 15:00:48 +01:00
Bruno BELANYI 7eb906cd17 2022: d14: ex1: add input 2022-12-14 14:41:48 +01:00
Bruno BELANYI e5f1d74b08 2022: d13: ex2: add solution 2022-12-13 10:03:37 +01:00
Bruno BELANYI 73c97eb7ce 2022: d13: ex2: add input 2022-12-13 10:03:32 +01:00
Bruno BELANYI 3d45fe8501 2022: d13: ex1: add solution 2022-12-13 10:03:25 +01:00
Bruno BELANYI 98f58280fa 2022: d13: ex1: add input 2022-12-13 10:03:17 +01:00
Bruno BELANYI 977dbcbd93 2022: d12: ex2: add solution 2022-12-12 16:16:26 +01:00
Bruno BELANYI 644f29a79d 2022: d12: ex2: add input 2022-12-12 16:14:52 +01:00
Bruno BELANYI 5f55835edf 2022: d12: ex1: add solution 2022-12-12 16:14:46 +01:00
Bruno BELANYI 300502a05f 2022: d12: ex1: add input 2022-12-12 16:14:39 +01:00
Bruno BELANYI 93cac379e0 2022: d11: ex2: add solution 2022-12-11 12:13:38 +01:00
Bruno BELANYI efb846e460 2022: d11: ex2: add input 2022-12-11 12:08:11 +01:00
Bruno BELANYI a03da090dc 2022: d11: ex1: add solution 2022-12-11 12:08:05 +01:00
Bruno BELANYI 19d6374476 2022: d11: ex1: add input 2022-12-11 12:08:00 +01:00
Bruno BELANYI 44dafef243 2022: d10: ex2: add solution 2022-12-10 11:16:01 +01:00
Bruno BELANYI 5731ff8e82 2022: d10: ex2: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI 426deae1ce 2022: d10: ex1: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 63bbd74790 2022: d10: ex1: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI 20779b5e2e 2022: d09: ex2: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 912e8e6edb 2022: d09: ex2: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI a505c9de49 2022: d09: ex1: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 71280e082d 2022: d09: ex1: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI f6fbf6d6e6 2022: d08: ex2: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 8b63d66750 2022: d08: ex2: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI 637b7e64c2 2022: d08: ex1: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI a45e00083c 2022: d08: ex1: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI a6f1d09f91 2022: d07: ex2: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 02a0c87f74 2022: d07: ex2: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI 5270736a28 2022: d07: ex1: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 761a37e8fe 2022: d07: ex1: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI 0c2712d7db 2022: d06: ex2: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 20fcfe32b2 2022: d06: ex2: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI 6c4ead5e1b 2022: d06: ex1: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 65cb34a16a 2022: d06: ex1: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI 5ad92f1585 2022: d05: ex2: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI fd66f79400 2022: d05: ex2: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI e2d1a5f74d 2022: d05: ex1: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI cea94a22fb 2022: d05: ex1: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI c2cfef5e30 2022: d04: ex2: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 9b01dc5723 2022: d04: ex2: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI d43d8c0cf1 2022: d04: ex1: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 32ccf155df 2022: d04: ex1: add input 2022-12-10 10:32:40 +01:00
Bruno BELANYI 3030162e09 2022: d03: ex2: add solution 2022-12-10 10:32:40 +01:00
Bruno BELANYI 035b00e5cf 2022: d03: ex2: add input 2022-12-03 07:50:28 +01:00
Bruno BELANYI 96b6c799e7 2022: d03: ex1: add solution 2022-12-03 07:50:28 +01:00
Bruno BELANYI 4c8667879d 2022: d03: ex1: add input 2022-12-03 07:48:55 +01:00
Bruno BELANYI 787381537b 2022: d02: ex2: add solution 2022-12-02 08:06:13 +01:00
Bruno BELANYI ca0ff2f0b9 2022: d02: ex2: add input 2022-12-02 08:05:47 +01:00
Bruno BELANYI a710ad0217 2022: d02: ex1: add solution 2022-12-02 08:05:39 +01:00
Bruno BELANYI a06d490eef 2022: d02: ex1: add input 2022-12-02 08:05:33 +01:00
Bruno BELANYI 6f0ffd34db 2022: d01: ex2: add solution 2022-12-01 11:49:28 +01:00
Bruno BELANYI a064fe7199 2022: d01: ex2: add input 2022-12-01 11:49:28 +01:00
Bruno BELANYI 24610576bb 2022: d01: ex1: add solution 2022-12-01 11:49:28 +01:00
Bruno BELANYI 8c13d5954e 2022: d01: ex1: add input 2022-12-01 10:02:48 +01:00
Bruno BELANYI 31c0f09981 nix: use 'nixpkgs-unstable' 2022-12-01 10:02:48 +01:00
Bruno BELANYI 46864fc490 nix: bump flake inputs 2022-12-01 10:02:48 +01:00
Bruno BELANYI fcb74b375f nix: fix 'pyright' 2022-12-01 10:02:48 +01:00
Bruno BELANYI 6a6552f6fc 2021: d25: ex2: add solution 2021-12-26 18:35:57 +01:00
Bruno BELANYI a6560adc6a 2021: d25: ex2: add input 2021-12-26 18:35:57 +01:00
Bruno BELANYI 709ad10ae2 2021: d25: ex1: add solution 2021-12-26 18:35:57 +01:00
Bruno BELANYI 5266bd7cd7 2021: d25: ex1: add input 2021-12-26 18:35:57 +01:00
Bruno BELANYI 068ce3366a 2021: d24: ex2: add solution 2021-12-26 18:35:57 +01:00
Bruno BELANYI a8b2046162 2021: d24: ex2: add input 2021-12-26 18:35:57 +01:00
Bruno BELANYI 84ee4c57f0 2021: d24: ex1: add solution 2021-12-26 18:35:57 +01:00
Bruno BELANYI bf830af1ae 2021: d24: ex1: add input 2021-12-26 17:46:51 +01:00
Bruno BELANYI d35e1d43d6 nix: add z3 to python environment 2021-12-26 17:46:51 +01:00
Bruno BELANYI 289b1ce455 nix: use proper python environment 2021-12-26 17:46:51 +01:00
Bruno BELANYI ac9f1f2d6d 2021: d23: ex2: add solution 2021-12-26 17:46:51 +01:00
Bruno BELANYI 04589c89b8 2021: d23: ex2: add input 2021-12-26 17:46:51 +01:00
Bruno BELANYI 05fdbcc303 2021: d23: ex1: add solution 2021-12-26 17:46:51 +01:00
Bruno BELANYI 130e417c62 2021: d23: ex1: add input 2021-12-26 17:39:08 +01:00
Bruno BELANYI 61936793e3 2021: d22: ex2: add solution 2021-12-22 16:41:20 +01:00
Bruno BELANYI f8d2551280 2021: d22: ex2: add input 2021-12-22 16:41:13 +01:00
Bruno BELANYI 9ab9b3bd08 2021: d22: ex1: add solution 2021-12-22 16:41:07 +01:00
Bruno BELANYI 3152b281e2 2021: d22: ex1: add input 2021-12-22 16:41:00 +01:00
Bruno BELANYI d85baf2a6d 2021: d21: ex2: add solution 2021-12-21 15:04:56 +01:00
Bruno BELANYI 16e9f6eb9c 2021: d21: ex2: add input 2021-12-21 15:04:49 +01:00
Bruno BELANYI ee48bb409a 2021: d21: ex1: add solution 2021-12-21 15:04:43 +01:00
Bruno BELANYI a791595c4e 2021: d21: ex1: add input 2021-12-21 15:04:37 +01:00
Bruno BELANYI 65328ff90d 2021: d20: ex2: add solution 2021-12-20 15:24:05 +01:00
Bruno BELANYI 74e53e919c 2021: d20: ex2: add input 2021-12-20 15:24:00 +01:00
Bruno BELANYI 820d358803 2021: d20: ex1: add solution 2021-12-20 15:23:53 +01:00
Bruno BELANYI 98deed16ed 2021: d20: ex1: add input 2021-12-20 15:23:47 +01:00
Bruno BELANYI 05a02c63fd 2021: d19: ex2: add solution 2021-12-19 14:23:37 +01:00
Bruno BELANYI f561c94209 2021: d19: ex2: add input 2021-12-19 14:23:30 +01:00
Bruno BELANYI 549a806bd6 2021: d19: ex1: add solution 2021-12-19 14:23:21 +01:00
Bruno BELANYI 030f680090 2021: d19: ex1: add input 2021-12-19 14:23:16 +01:00
Bruno BELANYI 8bf78654a5 2021: d18: ex2: add solution 2021-12-18 16:05:53 +01:00
Bruno BELANYI c0bf6fe213 2021: d18: ex2: add input 2021-12-18 16:05:48 +01:00
Bruno BELANYI 2be3cf4327 2021: d18: ex1: add solution 2021-12-18 16:05:38 +01:00
Bruno BELANYI 38902d9a64 2021: d18: ex1: add input 2021-12-18 16:05:30 +01:00
Bruno BELANYI 87dd721d47 2021: d17: ex2: add solution 2021-12-17 17:40:43 +01:00
Bruno BELANYI bbb6b33406 2021: d17: ex2: add input 2021-12-17 17:40:43 +01:00
Bruno BELANYI b8e0bc7db7 2021: d17: ex1: add solution 2021-12-17 17:40:43 +01:00
Bruno BELANYI b41103b3a8 2021: d17: ex1: add input 2021-12-17 17:38:20 +01:00
Bruno BELANYI 44d90b4153 2021: d16: ex2: add solution 2021-12-16 13:16:45 +01:00
Bruno BELANYI b42fd7e459 2021: d16: ex2: add input 2021-12-16 12:59:29 +01:00
Bruno BELANYI ae66ae03d6 2021: d16: ex1: add solution 2021-12-16 12:59:21 +01:00
Bruno BELANYI bf5053d865 2021: d16: ex1: add input 2021-12-16 12:59:15 +01:00
Bruno BELANYI 643286ca25 2021: d15: ex2: add solution 2021-12-15 10:21:46 +01:00
Bruno BELANYI cb03ef9b2b 2021: d15: ex2: add input 2021-12-15 10:21:39 +01:00
Bruno BELANYI ee4c12e081 2021: d15: ex1: add solution 2021-12-15 10:21:33 +01:00
Bruno BELANYI 68219cf710 2021: d15: ex1: add input 2021-12-15 10:21:27 +01:00
Bruno BELANYI 03565ed812 2021: d14: ex2: add solution 2021-12-14 13:52:53 +01:00
Bruno BELANYI 420d4a8f7a 2021: d14: ex2: add input 2021-12-14 13:46:29 +01:00
Bruno BELANYI a1520e437e 2021: d14: ex1: add solution 2021-12-14 13:46:23 +01:00
Bruno BELANYI 235f8cd29b 2021: d14: ex1: add input 2021-12-14 13:46:09 +01:00
Bruno BELANYI b1f325432c nix: add tools to devShell 2021-12-13 18:06:02 +01:00
Bruno BELANYI 5f332cc4fa 2019: d07: ex1: quieten Mypy 2021-12-13 18:03:31 +01:00
Bruno BELANYI df66079060 2021: d13: ex2: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 8794333d64 2021: d13: ex2: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 4b19161d71 2021: d13: ex1: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 6dbdba8a46 2021: d13: ex1: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 64651f1be9 2021: d12: ex2: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI b2c5e732f5 2021: d12: ex2: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 3feee209e3 2021: d12: ex1: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 85fd510ec9 2021: d12: ex1: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 6434bbca1b 2021: d11: ex2: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI c7f1e0c57c 2021: d11: ex2: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 9c1b1bc4a5 2021: d11: ex1: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 3fb206b0e5 2021: d11: ex1: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI cef3c2fa8d 2021: d10: ex2: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 5e1b3b095c 2021: d10: ex2: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 97ce6eb8b5 2021: d10: ex1: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 00df99ac05 2021: d10: ex1: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 531bbda3d5 2021: d09: ex2: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI fc8af0d5ce 2021: d09: ex2: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 3b0f1c8882 2021: d09: ex1: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 4a99cd11bd 2021: d09: ex1: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI f535c7c129 2021: d08: ex2: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 2ab20607e1 2021: d08: ex2: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI ab86a2dce7 2021: d08: ex1: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI e05173e73b 2021: d08: ex1: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 6d778ff545 2021: d07: ex2: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI c341ad6eee 2021: d07: ex2: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI b8d6bc9b4f 2021: d07: ex1: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 7793f65af4 2021: d07: ex1: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 4794a6269a 2021: d06: ex2: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 7f9758eb0c 2021: d06: ex2: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI 10abc46e11 2021: d06: ex1: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 330a8d64d0 2021: d06: ex1: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI d474708fc8 2021: d05: ex2: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 55e08af4b1 2021: d05: ex2: add input 2021-12-13 17:52:37 +01:00
Bruno BELANYI ce04fb589b 2021: d05: ex1: add solution 2021-12-13 17:52:37 +01:00
Bruno BELANYI 039e7f5214 2021: d05: ex1: add input 2021-12-13 14:33:15 +01:00
Bruno BELANYI ea66011fef 2021: d04: ex2: add solution 2021-12-13 14:33:15 +01:00
Bruno BELANYI daa87d923d 2021: d04: ex2: add input 2021-12-13 14:33:15 +01:00
Bruno BELANYI 2177287e01 2021: d04: ex1: add solution 2021-12-13 14:33:15 +01:00
Bruno BELANYI 484a9722ad 2021: d04: ex1: add input 2021-12-13 14:33:15 +01:00
Bruno BELANYI 614d3447c5 2021: d03: ex2: add solution 2021-12-13 14:33:15 +01:00
Bruno BELANYI 8acf8aadaf 2021: d03: ex2: add input 2021-12-13 14:33:15 +01:00
Bruno BELANYI b15c1a0d57 2021: d03: ex1: add solution 2021-12-13 14:33:15 +01:00
Bruno BELANYI cba9dd02f8 2021: d03: ex1: add input 2021-12-13 14:33:15 +01:00
Bruno BELANYI 7956b96baa 2021: d02: ex2: add solution 2021-12-13 14:33:15 +01:00
Bruno BELANYI 4b03030ed6 2021: d02: ex2: add input 2021-12-13 14:33:15 +01:00
Bruno BELANYI a21310895c 2021: d02: ex1: add solution 2021-12-13 14:33:15 +01:00
Bruno BELANYI 05a6845e83 2021: d02: ex1: add input 2021-12-13 14:33:15 +01:00
Bruno BELANYI 357c18a5fa 2021: d01: ex2: add solution 2021-12-13 14:33:15 +01:00
Bruno BELANYI 175706ca68 2021: d01: ex2: add input 2021-12-13 14:33:15 +01:00
Bruno BELANYI b1bec40137 2021: d01: ex1: add solution 2021-12-13 14:33:15 +01:00
Bruno BELANYI 2f661fa8a8 2021: d01: ex1: add input 2021-12-13 14:28:59 +01:00
Bruno BELANYI 0c925ae943 git: ignore generated files 2021-12-13 14:28:59 +01:00
Bruno BELANYI 50b46506ee nix: add direnv integration 2021-12-13 14:28:59 +01:00
Bruno BELANYI 01750a9c39 isort: use 'black' compatible style 2021-12-13 14:28:59 +01:00
Bruno BELANYI 1337f92ef3 nix: add flake 2021-12-13 14:28:59 +01:00
Bruno BELANYI e2acd44936 2020: d25: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 5dfe49a98d 2020: d25: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 6183509703 2020: d25: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 7ce292eb33 2020: d25: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 56b37a3e4f 2020: d24: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 3270cf77aa 2020: d24: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 0e09148689 2020: d24: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI aab1b0d7e8 2020: d24: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI fe4d2f5c1f 2020: d23: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 6158f55f42 2020: d23: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI cd827923c3 2020: d23: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 3e7dc177ff 2020: d23: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 8c30df4da9 2020: d22: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI bd8b216cf2 2020: d22: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 810aee2aed 2020: d22: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 987cdd56c5 2020: d22: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI c8b9636957 2020: d21: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 5cb2e01a2f 2020: d21: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI b2e5775014 2020: d21: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 9171fe1ae2 2020: d21: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 16e0da1a2c 2020: d20: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 37bc234a8a 2020: d20: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 8a2bbc38b6 2020: d20: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 9baeadebee 2020: d20: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI f0658a7c81 2020: d19: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 1480e095c5 2020: d19: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 9b09b7f5f3 2020: d19: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI f7bf6d1058 2020: d19: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI b2b051837f 2020: d18: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 9d2ad5dce4 2020: d18: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI e802aea353 2020: d18: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 711cb4724b 2020: d18: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI ee985f7151 2020: d17: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 886e96349a 2020: d17: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 57cd081712 2020: d17: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 1ce8bd45b3 2020: d17: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI a2d966926b 2020: d16: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI e9b6af3754 2020: d16: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 54b5f45c5a 2020: d16: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 2c134402dc 2020: d16: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI d3f00411f4 2020: d15: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 717d495d89 2020: d15: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI d3da5495c9 2020: d15: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 1c4bec86ef 2020: d15: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 258e8a568b 2020: d15: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 8544842253 2020: d15: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI b5042767c6 2020: d14: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 5d6ea97234 2020: d14: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI f071afb02b 2020: d13: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI b26314c942 2020: d13: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI f157debb7b 2020: d13: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 3afd466d83 2020: d13: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 72cd094e0c 2020: d12: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI ff956922aa 2020: d12: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI a6110aaa7f 2020: d12: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 07198e85d3 2020: d12: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 687b0a848d 2020: d11: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI e171f3953b 2020: d11: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 0eefd66d10 2020: d11: ex1: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI 9202d31fa8 2020: d11: ex1: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI d2abd31795 2020: d10: ex2: add solution 2021-12-06 13:58:37 +01:00
Bruno BELANYI d6c0be03f0 2020: d10: ex2: add input 2021-12-06 13:58:37 +01:00
Bruno BELANYI 49feb648c1 2020: d10: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI bd842fd6f8 2020: d10: ex1: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 7a599b5139 2020: d09: ex2: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI 93b884fef3 2020: d09: ex2: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI aeddad4f38 2020: d09: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI e843016596 2020: d09: ex1: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 13a1532871 2020: d08: ex2: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI 2a281d1857 2020: d08: ex2: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 632a4b004f 2020: d08: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI be6b51f20f 2020: d08: ex1: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI d3d35e2001 2020: d07: ex2: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI e28d9faeef 2020: d07: ex2: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI ac365651d3 2020: d07: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI f3647021be 2020: d07: ex1: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI f31334b438 2020: d06: ex2: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI 57b1172146 2020: d06: ex2: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 84b83d27a0 2020: d06: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI a8de8b9a3f 2020: d06: ex1: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 5012cbfcb1 2020: d05: ex2: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI c2c3ad7c32 2020: d05: ex2: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI a8ffb5bf66 2020: d05: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI 359dfe5d54 2020: d05: ex1: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 91dabb5b6a 2020: d04: ex2: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI 2b84e1c6f1 2020: d04: ex2: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 4f2385a8ba 2020: d04: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI fdac3b73af 2020: d04: ex1: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI a67fd01204 2020: d03: ex2: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI 1108caab20 2020: d03: ex2: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI c13206f5aa 2020: d03: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI b9199f86f5 2020: d03: ex1: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 3c766f31dd 2019: d19: ex2: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI 121678cd81 2019: d19: ex2: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI d7e663cd0c 2019: d19: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI 2375649653 2019: d19: ex1: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 5297e0bafe 2019: d18: ex2: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI b8dfe0d149 2019: d18: ex2: add input 2021-12-06 13:58:36 +01:00
Bruno BELANYI 5178c58a5a 2019: d18: ex1: add solution 2021-12-06 13:58:36 +01:00
Bruno BELANYI 5f9288aa5f 2019: d18: ex1: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 0d175c824f 2020: d02: ex2: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI 776577c118 2020: d02: ex2: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI a304a38046 2020: d02: ex1: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI 17a4286307 2020: d02: ex1: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 6d30ed5992 2020: d01: ex2: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI 30a7a7da33 2020: d01: ex2: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 82f57ddea5 2020: d01: ex1: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI dad9912dd2 2020: d01: ex1: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 07223f9d30 2019: d17: ex2: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI 254093a24d 2019: d17: ex2: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI ffe7fa42d5 2019: d17: ex1: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI 035b8b5a0f 2019: d17: ex1: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 704cf451cb 2019: d16: ex2: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI c1c5abc0a4 2019: d16: ex2: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 78954b23e5 2019: d16: ex1: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI e4699300b0 2019: d16: ex1: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 3fc73336a4 2019: d15: ex2: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI ac39fe2abb 2019: d15: ex2: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 1b8f5bc5e0 2019: d15: ex1: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI ed9ba2c14a 2019: d15: ex1: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI d3445b2ef1 2019: d14: ex2: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI 2b15ae7552 2019: d14: ex2: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 213575d822 2019: d14: ex1: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI 030f45af6c 2019: d14: ex1: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 3a19846717 2019: d13: ex2: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI 94dffe573c 2019: d13: ex2: add input 2021-12-01 10:42:02 +01:00
Bruno BELANYI 20d47b0048 2019: d13: ex1: add solution 2021-12-01 10:42:02 +01:00
Bruno BELANYI aee22cd938 2019: d13: ex1: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 9b842e321c 2019: d12: ex2: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI ce998da2e2 2019: d12: ex2: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 968562f2c9 2019: d12: ex1: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI 2866dc88c9 2019: d12: ex1: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 3ffe51992d 2019: d11: ex2: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI 31090e26d3 2019: d11: ex2: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 53ce8a1258 2019: d11: ex1: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI 97f8ebd006 2019: d11: ex1: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 405fb690a7 2019: d10: ex2: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI b7754cbafb 2019: d10: ex2: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 20546f5e81 2019: d10: ex1: clean-up solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI b42bf6c526 2019: d10: ex1: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI c8ae320cc3 2019: d10: ex1: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 87ba3e1726 2019: d09: ex2: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI d39f649c64 2019: d09: ex2: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 0f964aaeab 2019: d09: ex1: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI 524e3711ae 2019: d09: ex1: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI f2a968616f 2019: d08: ex2: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI cac131629d 2019: d08: ex2: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 76deb52857 2019: d08: ex1: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI 3978e39554 2019: d08: ex1: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 3d9b48a237 2019: d07: ex2: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI 91621b3394 2019: d07: ex2: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI f8127cba7a 2019: d07: ex1: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI a4ac7ea2aa 2019: d07: ex1: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 402e014d4d 2019: d06: ex2: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI 160d779f3e 2019: d06: ex2: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 026ec029b3 2019: d06: ex1: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI 625590f31a 2019: d06: ex1: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI e91fc23ca1 2019: d05: ex2: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI be24ef1771 2019: d05: ex2: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI 9b1d63fd54 2019: d05: ex1: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI 1a96ae91b1 2019: d05: ex1: add input 2020-11-09 11:52:18 +01:00
Bruno BELANYI c7203e4a59 2019: d04: ex2: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI a71bb20141 2019: d04: ex1: add solution 2020-11-09 11:52:18 +01:00
Bruno BELANYI bd040e8594 2019: d03: ex2: add solution 2020-11-09 11:52:18 +01:00
467 changed files with 129112 additions and 0 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
# Generated by Nix
/.pre-commit-config.yaml

108
2019/d03/ex2/ex2.py Executable file
View file

@ -0,0 +1,108 @@
#!/usr/bin/env python
import sys
from fractions import Fraction
from typing import Dict, List, NamedTuple, Optional
class Point(NamedTuple):
x: int
y: int
class Line(NamedTuple):
p1: Point
p2: Point
def manhattan_dist(p1: Point, p2: Point = Point(0, 0)) -> int:
dx = p2.x - p1.x if p1.x < p2.x else p1.x - p2.x
dy = p2.y - p1.y if p1.y < p2.y else p1.y - p2.y
return dx + dy
def intersect(l1: Line, l2: Line) -> Optional[Point]:
(x1, y1), (x2, y2) = l1.p1, l1.p2
(x3, y3), (x4, y4) = l2.p1, l2.p2
den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
if den == 0: # Parallel lines
return None
t = Fraction((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4), den)
if t < 0 or t > 1: # Out of l1
return None
u = -Fraction((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3), den)
if u < 0 or u > 1: # Out of l2
return None
dx = t * (x2 - x1)
dy = t * (y2 - y1)
assert int(dx) == dx and int(dy) == dy # Sanity checks
ix = x1 + int(dx)
iy = y1 + int(dy)
return Point(ix, iy)
def is_on(p: Point, l: Line) -> bool:
# Assume that l is horizontal or vertical
if l.p1.x == l.p2.x:
if l.p1.y < l.p2.y:
return p.x == l.p1.x and l.p1.y <= p.y <= l.p2.y
elif l.p2.y < l.p1.y:
return p.x == l.p1.x and l.p2.y <= p.y <= l.p1.y
elif l.p1.y == l.p2.y:
if l.p1.x < l.p2.x:
return p.y == l.p1.y and l.p1.x <= p.x <= l.p2.x
elif l.p2.x < l.p1.x:
return p.y == l.p1.y and l.p2.x <= p.x <= l.p1.x
assert False # Sanity checks
def parse_line(directions: str) -> List[Line]:
prev = Point(0, 0)
ans = []
for inst in directions.split(","):
direction, length = inst[0], int(inst[1:])
new_x, new_y = prev
if direction == "U":
new_y += length
elif direction == "R":
new_x += length
if direction == "D":
new_y -= length
elif direction == "L":
new_x -= length
new = Point(new_x, new_y)
ans.append(Line(prev, new))
prev = new
return ans
def compute_delay(p: Point, lines: List[Line]) -> int:
dist = 0
for l in lines:
if is_on(p, l):
return dist + manhattan_dist(l.p1, p)
dist += manhattan_dist(l.p1, l.p2)
assert False # Sanity check
def main() -> None:
wire1, wire2 = tuple(parse_line(l) for l in sys.stdin)
intersections = [intersect(l1, l2) for l1 in wire1 for l2 in wire2]
print(
min(
compute_delay(x, wire1) + compute_delay(x, wire2)
for x in intersections
if x is not None and x != Point(0, 0) # Discard origin
)
)
if __name__ == "__main__":
main()

34
2019/d04/ex1/ex1.py Executable file
View file

@ -0,0 +1,34 @@
#!/usr/bin/env python
from typing import Iterator
def is_valid_password(p: int) -> bool:
digits = str(p)
def has_adjacent_digit():
for a, b in zip(digits, digits[1:]):
if a == b:
return True
return False
def digits_never_decrease():
return all(a == b for a, b in zip(sorted(digits), digits))
return has_adjacent_digit() and digits_never_decrease()
def compute_pass(begin: int, end: int) -> Iterator[int]:
for p in range(begin, end + 1):
if is_valid_password(p):
yield p
def main() -> None:
begin = 264793
end = 803935
print(sum(1 for p in compute_pass(begin, end)))
if __name__ == "__main__":
main()

35
2019/d04/ex2/ex2.py Executable file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env python
from typing import Iterator
def is_valid_password(p: int) -> bool:
digits = str(p)
def has_unique_adjacent_digit():
counts = {d: 0 for d in range(10)}
for a, b in zip(digits, digits[1:]):
if a == b:
counts[int(a)] += 1
return any(count == 1 for count in counts.values())
def digits_never_decrease():
return all(a == b for a, b in zip(sorted(digits), digits))
return has_unique_adjacent_digit() and digits_never_decrease()
def compute_pass(begin: int, end: int) -> Iterator[int]:
for p in range(begin, end + 1):
if is_valid_password(p):
yield p
def main() -> None:
begin = 264793
end = 803935
print(sum(1 for p in compute_pass(begin, end)))
if __name__ == "__main__":
main()

103
2019/d05/ex1/ex1.py Executable file
View file

@ -0,0 +1,103 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
def do_addition(instr: Instruction, memory: List[int]) -> int:
lhs, rhs, dest = memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = memory[lhs]
if instr.p2_mode == ParameterMode.POSITION:
rhs = memory[rhs]
assert instr.p3_mode != ParameterMode.IMMEDIATE # Sanity check
memory[dest] = lhs + rhs
return 4 # Length of the instruction
def do_multiplication(instr: Instruction, memory: List[int]) -> int:
lhs, rhs, dest = memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = memory[lhs]
if instr.p2_mode == ParameterMode.POSITION:
rhs = memory[rhs]
assert instr.p3_mode != ParameterMode.IMMEDIATE # Sanity check
memory[dest] = lhs * rhs
return 4 # Length of the instruction
def do_input(instr: Instruction, memory: List[int]) -> int:
value = int(input())
param = memory[instr.address + 1]
assert instr.p1_mode == ParameterMode.POSITION # Sanity check
memory[param] = value
return 2 # Length of the instruction
def do_output(instr: Instruction, memory: List[int]) -> int:
value = memory[instr.address + 1]
if instr.p1_mode == ParameterMode.POSITION:
value = memory[value]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
print(value)
return 2 # Length of the instruction
def run_op(memory: List[int]) -> None:
index = 0
while True:
instr = lookup_ops(index, memory)
if instr.op == 99: # Halt
return
elif instr.op == 1: # Sum
index += do_addition(instr, memory)
elif instr.op == 2: # Multiplication
index += do_multiplication(instr, memory)
elif instr.op == 3: # Load from input
index += do_input(instr, memory)
elif instr.op == 4: # Store to output
index += do_output(instr, memory)
def main() -> None:
with open("input") as mem_f:
memory = [int(n) for n in mem_f.read().split(",")]
run_op(memory)
if __name__ == "__main__":
main()

1
2019/d05/ex1/input Normal file
View file

@ -0,0 +1 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1002,114,46,224,1001,224,-736,224,4,224,1002,223,8,223,1001,224,3,224,1,223,224,223,1,166,195,224,1001,224,-137,224,4,224,102,8,223,223,101,5,224,224,1,223,224,223,1001,169,83,224,1001,224,-90,224,4,224,102,8,223,223,1001,224,2,224,1,224,223,223,101,44,117,224,101,-131,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,1101,80,17,225,1101,56,51,225,1101,78,89,225,1102,48,16,225,1101,87,78,225,1102,34,33,224,101,-1122,224,224,4,224,1002,223,8,223,101,7,224,224,1,223,224,223,1101,66,53,224,101,-119,224,224,4,224,102,8,223,223,1001,224,5,224,1,223,224,223,1102,51,49,225,1101,7,15,225,2,110,106,224,1001,224,-4539,224,4,224,102,8,223,223,101,3,224,224,1,223,224,223,1102,88,78,225,102,78,101,224,101,-6240,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1107,226,677,224,102,2,223,223,1006,224,329,101,1,223,223,1108,226,677,224,1002,223,2,223,1005,224,344,101,1,223,223,8,226,677,224,102,2,223,223,1006,224,359,1001,223,1,223,1007,226,677,224,1002,223,2,223,1005,224,374,101,1,223,223,1008,677,677,224,1002,223,2,223,1005,224,389,1001,223,1,223,1108,677,226,224,1002,223,2,223,1006,224,404,1001,223,1,223,1007,226,226,224,1002,223,2,223,1005,224,419,1001,223,1,223,1107,677,226,224,1002,223,2,223,1006,224,434,101,1,223,223,108,677,677,224,1002,223,2,223,1005,224,449,1001,223,1,223,1107,677,677,224,102,2,223,223,1005,224,464,1001,223,1,223,108,226,226,224,1002,223,2,223,1006,224,479,1001,223,1,223,1008,226,226,224,102,2,223,223,1005,224,494,101,1,223,223,108,677,226,224,102,2,223,223,1005,224,509,1001,223,1,223,8,677,226,224,1002,223,2,223,1006,224,524,101,1,223,223,7,226,677,224,1002,223,2,223,1006,224,539,101,1,223,223,7,677,226,224,102,2,223,223,1006,224,554,1001,223,1,223,7,226,226,224,1002,223,2,223,1006,224,569,101,1,223,223,107,677,677,224,102,2,223,223,1006,224,584,101,1,223,223,1108,677,677,224,102,2,223,223,1006,224,599,1001,223,1,223,1008,677,226,224,1002,223,2,223,1005,224,614,1001,223,1,223,8,677,677,224,1002,223,2,223,1006,224,629,1001,223,1,223,107,226,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,677,677,224,102,2,223,223,1006,224,659,101,1,223,223,107,226,226,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226

199
2019/d05/ex2/ex2.py Executable file
View file

@ -0,0 +1,199 @@
#!/usr/bin/env python
from dataclasses import dataclass
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
def run(self):
while True:
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
return
elif instr.op == 1: # Sum
self.do_addition(instr)
elif instr.op == 2: # Multiplication
self.do_multiplication(instr)
elif instr.op == 3: # Load from input
self.do_input(instr)
elif instr.op == 4: # Store to output
self.do_output(instr)
elif instr.op == 5: # Jump if true
self.do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self.do_jump_if_false(instr)
elif instr.op == 7: # Less than
self.do_less_than(instr)
elif instr.op == 8: # Equal to
self.do_equal_to(instr)
else:
assert False # Sanity check
def do_addition(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs + rhs
self.rip += 4 # Length of the instruction
def do_multiplication(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs * rhs
self.rip += 4 # Length of the instruction
def do_input(self, instr: Instruction) -> None:
value = int(input())
param = self.memory[instr.address + 1]
assert instr.p1_mode == ParameterMode.POSITION # Sanity check
self.memory[param] = value
self.rip += 2 # Length of the instruction
def do_output(self, instr: Instruction) -> None:
value = self.memory[instr.address + 1]
if instr.p1_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
print(value)
self.rip += 2 # Length of the instruction
def do_jump_if_true(self, instr: Instruction) -> None:
cond, value = self.memory[instr.address + 1 : instr.address + 3]
if instr.p1_mode == ParameterMode.POSITION:
cond = self.memory[cond]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def do_jump_if_false(self, instr: Instruction) -> None:
cond, value = self.memory[instr.address + 1 : instr.address + 3]
if instr.p1_mode == ParameterMode.POSITION:
cond = self.memory[cond]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def do_less_than(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs < rhs else 0
self.rip += 4 # Length of the instruction
def do_equal_to(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs == rhs else 0
self.rip += 4 # Length of the instruction
def main() -> None:
with open("input") as mem_f:
memory = [int(n) for n in mem_f.read().split(",")]
computer = Computer(memory)
computer.run()
if __name__ == "__main__":
main()

1
2019/d05/ex2/input Normal file
View file

@ -0,0 +1 @@
3,225,1,225,6,6,1100,1,238,225,104,0,1002,114,46,224,1001,224,-736,224,4,224,1002,223,8,223,1001,224,3,224,1,223,224,223,1,166,195,224,1001,224,-137,224,4,224,102,8,223,223,101,5,224,224,1,223,224,223,1001,169,83,224,1001,224,-90,224,4,224,102,8,223,223,1001,224,2,224,1,224,223,223,101,44,117,224,101,-131,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,1101,80,17,225,1101,56,51,225,1101,78,89,225,1102,48,16,225,1101,87,78,225,1102,34,33,224,101,-1122,224,224,4,224,1002,223,8,223,101,7,224,224,1,223,224,223,1101,66,53,224,101,-119,224,224,4,224,102,8,223,223,1001,224,5,224,1,223,224,223,1102,51,49,225,1101,7,15,225,2,110,106,224,1001,224,-4539,224,4,224,102,8,223,223,101,3,224,224,1,223,224,223,1102,88,78,225,102,78,101,224,101,-6240,224,224,4,224,1002,223,8,223,101,5,224,224,1,224,223,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1107,226,677,224,102,2,223,223,1006,224,329,101,1,223,223,1108,226,677,224,1002,223,2,223,1005,224,344,101,1,223,223,8,226,677,224,102,2,223,223,1006,224,359,1001,223,1,223,1007,226,677,224,1002,223,2,223,1005,224,374,101,1,223,223,1008,677,677,224,1002,223,2,223,1005,224,389,1001,223,1,223,1108,677,226,224,1002,223,2,223,1006,224,404,1001,223,1,223,1007,226,226,224,1002,223,2,223,1005,224,419,1001,223,1,223,1107,677,226,224,1002,223,2,223,1006,224,434,101,1,223,223,108,677,677,224,1002,223,2,223,1005,224,449,1001,223,1,223,1107,677,677,224,102,2,223,223,1005,224,464,1001,223,1,223,108,226,226,224,1002,223,2,223,1006,224,479,1001,223,1,223,1008,226,226,224,102,2,223,223,1005,224,494,101,1,223,223,108,677,226,224,102,2,223,223,1005,224,509,1001,223,1,223,8,677,226,224,1002,223,2,223,1006,224,524,101,1,223,223,7,226,677,224,1002,223,2,223,1006,224,539,101,1,223,223,7,677,226,224,102,2,223,223,1006,224,554,1001,223,1,223,7,226,226,224,1002,223,2,223,1006,224,569,101,1,223,223,107,677,677,224,102,2,223,223,1006,224,584,101,1,223,223,1108,677,677,224,102,2,223,223,1006,224,599,1001,223,1,223,1008,677,226,224,1002,223,2,223,1005,224,614,1001,223,1,223,8,677,677,224,1002,223,2,223,1006,224,629,1001,223,1,223,107,226,677,224,1002,223,2,223,1006,224,644,101,1,223,223,1007,677,677,224,102,2,223,223,1006,224,659,101,1,223,223,107,226,226,224,1002,223,2,223,1006,224,674,1001,223,1,223,4,223,99,226

53
2019/d06/ex1/ex1.py Executable file
View file

@ -0,0 +1,53 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from typing import Dict, List
@dataclass
class OrbitGraph:
name: str
children: List["OrbitGraph"] = field(default_factory=list)
def make_orbits(description: List[str]) -> OrbitGraph:
orbits: Dict[str, OrbitGraph] = {}
def find_or_add(name: str) -> OrbitGraph:
if name in orbits:
return orbits[name]
orbit = OrbitGraph(name)
orbits[name] = orbit
return orbit
for l in description:
parent, child = map(find_or_add, map(lambda x: x.strip(), l.split(")")))
parent.children.append(child)
return orbits["COM"] # Assume common root is named 'COM'
def count_orbits(root: OrbitGraph) -> int:
ans = 0
stack = 0 # Count the number of direct and indirect orbits to the current root
def helper(root: OrbitGraph):
nonlocal ans
nonlocal stack
ans += stack # Count the number of orbits to this node
stack += 1 # Add the current root to stack of parents
for child in root.children:
helper(child) # Count those orbits for each child
stack -= 1 # Remove the current root from the stack of parents
helper(root)
return ans
def main() -> None:
print(count_orbits(make_orbits(sys.stdin.readlines())))
if __name__ == "__main__":
main()

1069
2019/d06/ex1/input Normal file

File diff suppressed because it is too large Load diff

86
2019/d06/ex2/ex2.py Executable file
View file

@ -0,0 +1,86 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from typing import Dict, List, Optional
@dataclass
class OrbitGraph:
name: str
children: List["OrbitGraph"] = field(default_factory=list)
def make_orbits(description: List[str]) -> OrbitGraph:
orbits: Dict[str, OrbitGraph] = {}
def find_or_add(name: str) -> OrbitGraph:
if name in orbits:
return orbits[name]
orbit = OrbitGraph(name)
orbits[name] = orbit
return orbit
for l in description:
parent, child = map(find_or_add, map(lambda x: x.strip(), l.split(")")))
parent.children.append(child)
return orbits["COM"] # Assume common root is named 'COM'
def count_orbits_hop(root: OrbitGraph) -> int:
nodes: List[OrbitGraph] = []
def ind_node(node: OrbitGraph) -> int:
return nodes.index(node)
def fill_nodes(root: OrbitGraph) -> None:
nodes.append(root)
for child in root.children:
fill_nodes(child)
fill_nodes(root)
n = len(nodes)
dist: List[List[int]] = [[2 * n] * len(nodes) for __ in range(len(nodes))]
next_nodes: List[List[Optional[OrbitGraph]]] = [[None] * n for __ in range(n)]
def fill_mat(root: OrbitGraph) -> None:
# From root to itself
dist[ind_node(root)][ind_node(root)] = 0
next_nodes[ind_node(root)][ind_node(root)] = root
for child in root.children:
# From root to child
dist[ind_node(root)][ind_node(child)] = 1
next_nodes[ind_node(root)][ind_node(child)] = child
# The other way
dist[ind_node(child)][ind_node(root)] = 1
next_nodes[ind_node(child)][ind_node(root)] = root
# Do it again
fill_mat(child)
fill_mat(root)
for k in range(n):
print(f"{k} / {n} rounds")
for i in range(n):
for j in range(n):
new_dist = dist[i][k] + dist[k][j]
if dist[i][j] > new_dist:
dist[i][j] = new_dist
next_nodes[i][j] = next_nodes[i][k]
useful_indices: Dict[str, int] = {}
for index, node in enumerate(nodes):
if node.name in ("YOU", "SAN"):
useful_indices[node.name] = index
return (
dist[useful_indices["YOU"]][useful_indices["SAN"]] - 2
) # Because we are in orbit
def main() -> None:
print(count_orbits_hop(make_orbits(sys.stdin.readlines())))
if __name__ == "__main__":
main()

1069
2019/d06/ex2/input Normal file

File diff suppressed because it is too large Load diff

263
2019/d07/ex1/ex1.py Executable file
View file

@ -0,0 +1,263 @@
#!/usr/bin/env python
# Mypy has issues with assigning Callable to fields of objects
# See https://github.com/python/mypy/issues/708
# type: ignore
import itertools
import sys
from copy import deepcopy
from dataclasses import dataclass
from enum import IntEnum
from typing import Callable, List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
read_input: Callable[[], str] = input
print_output: Callable[[int], None] = print
def run(self) -> None:
is_halted = self.run_single()
while not is_halted:
is_halted = self.run_single()
def run_single(self) -> bool: # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
return True # Halted
elif instr.op == 1: # Sum
self.do_addition(instr)
elif instr.op == 2: # Multiplication
self.do_multiplication(instr)
elif instr.op == 3: # Load from input
self.do_input(instr)
elif instr.op == 4: # Store to output
self.do_output(instr)
elif instr.op == 5: # Jump if true
self.do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self.do_jump_if_false(instr)
elif instr.op == 7: # Less than
self.do_less_than(instr)
elif instr.op == 8: # Equal to
self.do_equal_to(instr)
else:
assert False # Sanity check
return False # Not halted
def do_addition(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs + rhs
self.rip += 4 # Length of the instruction
def do_multiplication(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs * rhs
self.rip += 4 # Length of the instruction
def do_input(self, instr: Instruction) -> None:
value = int(self.read_input())
param = self.memory[instr.address + 1]
assert instr.p1_mode == ParameterMode.POSITION # Sanity check
self.memory[param] = value
self.rip += 2 # Length of the instruction
def do_output(self, instr: Instruction) -> None:
value = self.memory[instr.address + 1]
if instr.p1_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
self.print_output(value)
self.rip += 2 # Length of the instruction
def do_jump_if_true(self, instr: Instruction) -> None:
cond, value = self.memory[instr.address + 1 : instr.address + 3]
if instr.p1_mode == ParameterMode.POSITION:
cond = self.memory[cond]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def do_jump_if_false(self, instr: Instruction) -> None:
cond, value = self.memory[instr.address + 1 : instr.address + 3]
if instr.p1_mode == ParameterMode.POSITION:
cond = self.memory[cond]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
value = self.memory[value]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def do_less_than(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs < rhs else 0
self.rip += 4 # Length of the instruction
def do_equal_to(self, instr: Instruction) -> None:
lhs, rhs, dest = self.memory[instr.address + 1 : instr.address + 4]
if instr.p1_mode == ParameterMode.POSITION:
lhs = self.memory[lhs]
else:
assert instr.p1_mode == ParameterMode.IMMEDIATE # Sanity check
if instr.p2_mode == ParameterMode.POSITION:
rhs = self.memory[rhs]
else:
assert instr.p2_mode == ParameterMode.IMMEDIATE # Sanity check
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs == rhs else 0
self.rip += 4 # Length of the instruction
def main() -> None:
def get_input_fun(phase: int, last_output: List[int]) -> Callable[[], str]:
has_been_called = False
def _input() -> str:
nonlocal has_been_called
if has_been_called:
return str(last_output.pop(0))
has_been_called = True
return str(phase)
return _input
memory = [int(n) for n in sys.stdin.read().split(",")]
max = 0
ans = tuple(-1 for __ in range(5))
for a, b, c, d, e in itertools.permutations(range(5)):
amp1 = Computer(deepcopy(memory))
amp1_output: List[int] = []
amp1.read_input = get_input_fun(a, [0])
amp1.print_output = lambda x: amp1_output.append(int(x))
amp2 = Computer(deepcopy(memory))
amp2_output: List[int] = []
amp2.read_input = get_input_fun(b, amp1_output)
amp2.print_output = lambda x: amp2_output.append(int(x))
amp3 = Computer(deepcopy(memory))
amp3_output: List[int] = []
amp3.read_input = get_input_fun(c, amp2_output)
amp3.print_output = lambda x: amp3_output.append(int(x))
amp4 = Computer(deepcopy(memory))
amp4_output: List[int] = []
amp4.read_input = get_input_fun(d, amp3_output)
amp4.print_output = lambda x: amp4_output.append(int(x))
amp5 = Computer(deepcopy(memory))
amp5_output: List[int] = []
amp5.read_input = get_input_fun(e, amp4_output)
amp5.print_output = lambda x: amp5_output.append(int(x))
amp1.run()
amp2.run()
amp3.run()
amp4.run()
amp5.run()
res = amp5_output.pop(0)
if res > max:
max = res
ans = (a, b, c, d, e)
print(f"Max: {max}, res: {ans}")
print(f"Final one: {max}, with {ans}")
if __name__ == "__main__":
main()

1
2019/d07/ex1/input Normal file
View file

@ -0,0 +1 @@
3,8,1001,8,10,8,105,1,0,0,21,46,55,76,89,106,187,268,349,430,99999,3,9,101,4,9,9,1002,9,2,9,101,5,9,9,1002,9,2,9,101,2,9,9,4,9,99,3,9,1002,9,5,9,4,9,99,3,9,1001,9,2,9,1002,9,4,9,101,2,9,9,1002,9,3,9,4,9,99,3,9,1001,9,3,9,1002,9,2,9,4,9,99,3,9,1002,9,4,9,1001,9,4,9,102,5,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,99

196
2019/d07/ex2/ex2.py Executable file
View file

@ -0,0 +1,196 @@
#!/usr/bin/env python
import itertools
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Callable, List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
else:
assert False # Sanity check
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs + rhs
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = lhs * rhs
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
assert instr.p1_mode == ParameterMode.POSITION # Sanity check
self.memory[param] = value
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs < rhs else 0
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
assert instr.p3_mode == ParameterMode.POSITION # Sanity check
self.memory[dest] = 1 if lhs == rhs else 0
self.rip += 4 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
max = 0
ans = tuple(-1 for __ in range(5))
for perm in itertools.permutations(range(5, 10)):
amps = [Computer(deepcopy(memory), input_list=[phase]) for phase in perm]
amp1 = amps[0] # Keep track of this guy for the output solution
amp1.input_list.append(0) # Initial input
while not all(amp.is_halted for amp in amps):
# Put a non halted comuter to the front
while amps[0].is_halted:
amps.append(amps.pop(0))
# Run it until exhaustion or input/output interrupt
try:
amps[0].run()
except InputInterrupt:
amps.append(amps.pop(0))
except OutputInterrupt:
amps[1].input_list.append(amps[0].output_list.pop())
res = amp1.input_list.pop(0) # Amplifier 5 output to amplifier 1 at the end
if res > max:
max = res
ans = perm
print(f"Max: {max}, res: {ans}")
print(f"Final one: {max}, with {ans}")
if __name__ == "__main__":
main()

1
2019/d07/ex2/input Normal file
View file

@ -0,0 +1 @@
3,8,1001,8,10,8,105,1,0,0,21,46,55,76,89,106,187,268,349,430,99999,3,9,101,4,9,9,1002,9,2,9,101,5,9,9,1002,9,2,9,101,2,9,9,4,9,99,3,9,1002,9,5,9,4,9,99,3,9,1001,9,2,9,1002,9,4,9,101,2,9,9,1002,9,3,9,4,9,99,3,9,1001,9,3,9,1002,9,2,9,4,9,99,3,9,1002,9,4,9,1001,9,4,9,102,5,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,99,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1002,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,101,1,9,9,4,9,99

25
2019/d08/ex1/ex1.py Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env python
import sys
def main() -> None:
COLUMNS = 25
ROWS = 6
digits = [int(d) for d in str(int(sys.stdin.read()))]
assert len(digits) % (COLUMNS * ROWS) == 0 # Sanity check
LAYERS = int(len(digits) / (COLUMNS * ROWS))
layers = [
[digits.pop(0) for __ in range(COLUMNS) for __ in range(ROWS)]
for __ in range(LAYERS)
]
least_zeros = min(layers, key=lambda l: sum(1 for d in l if d == 0))
print(sum(1 for d in least_zeros if d == 1) * sum(1 for d in least_zeros if d == 2))
if __name__ == "__main__":
main()

1
2019/d08/ex1/input Normal file

File diff suppressed because one or more lines are too long

32
2019/d08/ex2/ex2.py Executable file
View file

@ -0,0 +1,32 @@
#!/usr/bin/env python
import sys
def main() -> None:
COLUMNS = 25
ROWS = 6
digits = [int(d) for d in str(int(sys.stdin.read()))]
assert len(digits) % (COLUMNS * ROWS) == 0 # Sanity check
LAYERS = int(len(digits) / (COLUMNS * ROWS))
layers = [
[digits.pop(0) for __ in range(COLUMNS) for __ in range(ROWS)]
for __ in range(LAYERS)
]
ans = []
for pixels in zip(*(layer for layer in layers)):
ans.append(next(color for color in pixels if color != 2))
print(
"\n".join(
"".join("" if ans.pop(0) == 0 else " " for __ in range(COLUMNS))
for __ in range(ROWS)
)
)
if __name__ == "__main__":
main()

1
2019/d08/ex2/input Normal file

File diff suppressed because one or more lines are too long

211
2019/d09/ex1/ex1.py Executable file
View file

@ -0,0 +1,211 @@
#!/usr/bin/env python
import itertools
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Callable, List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
computer = Computer(deepcopy(memory), input_list=[1])
computer.run_no_output_interrupt()
print(computer.output_list.pop())
assert len(computer.output_list) == 0 # Sanity check
if __name__ == "__main__":
main()

1
2019/d09/ex1/input Normal file
View file

@ -0,0 +1 @@
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,1,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,26,1,1005,1101,0,24,1019,1102,1,32,1007,1101,0,704,1027,1102,0,1,1020,1101,0,348,1029,1102,28,1,1002,1101,34,0,1016,1102,29,1,1008,1102,1,30,1013,1102,25,1,1012,1101,0,33,1009,1102,1,37,1001,1101,31,0,1017,1101,245,0,1022,1102,39,1,1000,1101,27,0,1011,1102,770,1,1025,1101,0,22,1015,1102,1,1,1021,1101,711,0,1026,1101,20,0,1004,1101,0,23,1018,1101,242,0,1023,1102,21,1,1003,1101,38,0,1010,1101,0,35,1014,1101,0,36,1006,1101,0,357,1028,1102,1,775,1024,109,-3,2102,1,9,63,1008,63,36,63,1005,63,203,4,187,1105,1,207,1001,64,1,64,1002,64,2,64,109,8,21101,40,0,5,1008,1010,41,63,1005,63,227,1106,0,233,4,213,1001,64,1,64,1002,64,2,64,109,16,2105,1,2,1105,1,251,4,239,1001,64,1,64,1002,64,2,64,109,1,21107,41,40,-4,1005,1018,271,1001,64,1,64,1105,1,273,4,257,1002,64,2,64,109,-18,1207,0,21,63,1005,63,295,4,279,1001,64,1,64,1105,1,295,1002,64,2,64,109,-3,1207,0,36,63,1005,63,311,1105,1,317,4,301,1001,64,1,64,1002,64,2,64,109,6,2108,20,-3,63,1005,63,339,4,323,1001,64,1,64,1106,0,339,1002,64,2,64,109,28,2106,0,-7,4,345,1001,64,1,64,1106,0,357,1002,64,2,64,109,-18,1206,4,373,1001,64,1,64,1105,1,375,4,363,1002,64,2,64,109,-6,2107,31,-4,63,1005,63,397,4,381,1001,64,1,64,1105,1,397,1002,64,2,64,109,1,21102,42,1,-1,1008,1011,39,63,1005,63,421,1001,64,1,64,1106,0,423,4,403,1002,64,2,64,109,-2,2108,26,-2,63,1005,63,439,1106,0,445,4,429,1001,64,1,64,1002,64,2,64,109,6,21102,43,1,-5,1008,1011,43,63,1005,63,467,4,451,1105,1,471,1001,64,1,64,1002,64,2,64,109,6,21101,44,0,-3,1008,1019,44,63,1005,63,493,4,477,1105,1,497,1001,64,1,64,1002,64,2,64,109,-9,1206,7,511,4,503,1105,1,515,1001,64,1,64,1002,64,2,64,109,14,1205,-7,531,1001,64,1,64,1106,0,533,4,521,1002,64,2,64,109,-27,1201,0,0,63,1008,63,39,63,1005,63,555,4,539,1105,1,559,1001,64,1,64,1002,64,2,64,109,10,2101,0,-5,63,1008,63,24,63,1005,63,583,1001,64,1,64,1105,1,585,4,565,1002,64,2,64,109,-11,2107,21,5,63,1005,63,601,1105,1,607,4,591,1001,64,1,64,1002,64,2,64,109,10,1208,0,36,63,1005,63,627,1001,64,1,64,1106,0,629,4,613,1002,64,2,64,109,15,21108,45,45,-9,1005,1015,647,4,635,1105,1,651,1001,64,1,64,1002,64,2,64,109,-19,2101,0,-4,63,1008,63,37,63,1005,63,677,4,657,1001,64,1,64,1106,0,677,1002,64,2,64,109,22,1205,-6,695,4,683,1001,64,1,64,1105,1,695,1002,64,2,64,109,-10,2106,0,10,1001,64,1,64,1105,1,713,4,701,1002,64,2,64,109,-9,1201,-8,0,63,1008,63,36,63,1005,63,733,1105,1,739,4,719,1001,64,1,64,1002,64,2,64,109,7,21107,46,47,0,1005,1015,757,4,745,1106,0,761,1001,64,1,64,1002,64,2,64,109,14,2105,1,-5,4,767,1105,1,779,1001,64,1,64,1002,64,2,64,109,-34,2102,1,6,63,1008,63,39,63,1005,63,799,1105,1,805,4,785,1001,64,1,64,1002,64,2,64,109,25,21108,47,49,-4,1005,1016,825,1001,64,1,64,1106,0,827,4,811,1002,64,2,64,109,-6,1208,-8,36,63,1005,63,845,4,833,1106,0,849,1001,64,1,64,1002,64,2,64,109,-10,1202,2,1,63,1008,63,36,63,1005,63,875,4,855,1001,64,1,64,1105,1,875,1002,64,2,64,109,-5,1202,10,1,63,1008,63,30,63,1005,63,895,1106,0,901,4,881,1001,64,1,64,4,64,99,21101,27,0,1,21101,0,915,0,1105,1,922,21201,1,65916,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1105,1,922,21201,1,0,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1106,0,968,22102,1,-2,-2,109,-3,2105,1,0

211
2019/d09/ex2/ex2.py Executable file
View file

@ -0,0 +1,211 @@
#!/usr/bin/env python
import itertools
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Callable, List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
computer = Computer(deepcopy(memory), input_list=[2])
computer.run_no_output_interrupt()
print(computer.output_list.pop())
assert len(computer.output_list) == 0 # Sanity check
if __name__ == "__main__":
main()

1
2019/d09/ex2/input Normal file
View file

@ -0,0 +1 @@
1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,1,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,26,1,1005,1101,0,24,1019,1102,1,32,1007,1101,0,704,1027,1102,0,1,1020,1101,0,348,1029,1102,28,1,1002,1101,34,0,1016,1102,29,1,1008,1102,1,30,1013,1102,25,1,1012,1101,0,33,1009,1102,1,37,1001,1101,31,0,1017,1101,245,0,1022,1102,39,1,1000,1101,27,0,1011,1102,770,1,1025,1101,0,22,1015,1102,1,1,1021,1101,711,0,1026,1101,20,0,1004,1101,0,23,1018,1101,242,0,1023,1102,21,1,1003,1101,38,0,1010,1101,0,35,1014,1101,0,36,1006,1101,0,357,1028,1102,1,775,1024,109,-3,2102,1,9,63,1008,63,36,63,1005,63,203,4,187,1105,1,207,1001,64,1,64,1002,64,2,64,109,8,21101,40,0,5,1008,1010,41,63,1005,63,227,1106,0,233,4,213,1001,64,1,64,1002,64,2,64,109,16,2105,1,2,1105,1,251,4,239,1001,64,1,64,1002,64,2,64,109,1,21107,41,40,-4,1005,1018,271,1001,64,1,64,1105,1,273,4,257,1002,64,2,64,109,-18,1207,0,21,63,1005,63,295,4,279,1001,64,1,64,1105,1,295,1002,64,2,64,109,-3,1207,0,36,63,1005,63,311,1105,1,317,4,301,1001,64,1,64,1002,64,2,64,109,6,2108,20,-3,63,1005,63,339,4,323,1001,64,1,64,1106,0,339,1002,64,2,64,109,28,2106,0,-7,4,345,1001,64,1,64,1106,0,357,1002,64,2,64,109,-18,1206,4,373,1001,64,1,64,1105,1,375,4,363,1002,64,2,64,109,-6,2107,31,-4,63,1005,63,397,4,381,1001,64,1,64,1105,1,397,1002,64,2,64,109,1,21102,42,1,-1,1008,1011,39,63,1005,63,421,1001,64,1,64,1106,0,423,4,403,1002,64,2,64,109,-2,2108,26,-2,63,1005,63,439,1106,0,445,4,429,1001,64,1,64,1002,64,2,64,109,6,21102,43,1,-5,1008,1011,43,63,1005,63,467,4,451,1105,1,471,1001,64,1,64,1002,64,2,64,109,6,21101,44,0,-3,1008,1019,44,63,1005,63,493,4,477,1105,1,497,1001,64,1,64,1002,64,2,64,109,-9,1206,7,511,4,503,1105,1,515,1001,64,1,64,1002,64,2,64,109,14,1205,-7,531,1001,64,1,64,1106,0,533,4,521,1002,64,2,64,109,-27,1201,0,0,63,1008,63,39,63,1005,63,555,4,539,1105,1,559,1001,64,1,64,1002,64,2,64,109,10,2101,0,-5,63,1008,63,24,63,1005,63,583,1001,64,1,64,1105,1,585,4,565,1002,64,2,64,109,-11,2107,21,5,63,1005,63,601,1105,1,607,4,591,1001,64,1,64,1002,64,2,64,109,10,1208,0,36,63,1005,63,627,1001,64,1,64,1106,0,629,4,613,1002,64,2,64,109,15,21108,45,45,-9,1005,1015,647,4,635,1105,1,651,1001,64,1,64,1002,64,2,64,109,-19,2101,0,-4,63,1008,63,37,63,1005,63,677,4,657,1001,64,1,64,1106,0,677,1002,64,2,64,109,22,1205,-6,695,4,683,1001,64,1,64,1105,1,695,1002,64,2,64,109,-10,2106,0,10,1001,64,1,64,1105,1,713,4,701,1002,64,2,64,109,-9,1201,-8,0,63,1008,63,36,63,1005,63,733,1105,1,739,4,719,1001,64,1,64,1002,64,2,64,109,7,21107,46,47,0,1005,1015,757,4,745,1106,0,761,1001,64,1,64,1002,64,2,64,109,14,2105,1,-5,4,767,1105,1,779,1001,64,1,64,1002,64,2,64,109,-34,2102,1,6,63,1008,63,39,63,1005,63,799,1105,1,805,4,785,1001,64,1,64,1002,64,2,64,109,25,21108,47,49,-4,1005,1016,825,1001,64,1,64,1106,0,827,4,811,1002,64,2,64,109,-6,1208,-8,36,63,1005,63,845,4,833,1106,0,849,1001,64,1,64,1002,64,2,64,109,-10,1202,2,1,63,1008,63,36,63,1005,63,875,4,855,1001,64,1,64,1105,1,875,1002,64,2,64,109,-5,1202,10,1,63,1008,63,30,63,1005,63,895,1106,0,901,4,881,1001,64,1,64,4,64,99,21101,27,0,1,21101,0,915,0,1105,1,922,21201,1,65916,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21101,942,0,0,1105,1,922,21201,1,0,-1,21201,-2,-3,1,21102,1,957,0,1105,1,922,22201,1,-1,-2,1106,0,968,22102,1,-2,-2,109,-3,2105,1,0

51
2019/d10/ex1/ex1.py Executable file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env python
import sys
from math import gcd
from typing import NamedTuple, Set
class Position(NamedTuple):
x: int
y: int
def main() -> None:
asteroids = [
Position(x, y)
for y, line in enumerate(sys.stdin.readlines())
for x, c in enumerate(line.rstrip())
if c == "#"
]
def count_spotted(x: int, y: int) -> int:
seen: Set[Position] = set()
ans = 0
radius = 1
while True:
def is_r_away(pos: Position) -> bool:
return max(abs(pos.x - x), abs(pos.y - y)) == radius
to_visit = list(filter(is_r_away, asteroids))
radius += 1
if len(to_visit) == 0:
break
for pos in to_visit:
rel = (pos.x - x, pos.y - y)
common = gcd(*rel)
rel = Position(*(a // common for a in rel))
if rel in seen:
continue # Already have an asteroid on this path
seen.add(rel)
ans += 1
return ans
ans, x, y = max((count_spotted(*pos), *pos) for pos in asteroids)
print(f"({x}, {y}): {ans}")
if __name__ == "__main__":
main()

31
2019/d10/ex1/input Normal file
View file

@ -0,0 +1,31 @@
#...##.####.#.......#.##..##.#.
#.##.#..#..#...##..##.##.#.....
#..#####.#......#..#....#.###.#
...#.#.#...#..#.....#..#..#.#..
.#.....##..#...#..#.#...##.....
##.....#..........##..#......##
.##..##.#.#....##..##.......#..
#.##.##....###..#...##...##....
##.#.#............##..#...##..#
###..##.###.....#.##...####....
...##..#...##...##..#.#..#...#.
..#.#.##.#.#.#####.#....####.#.
#......###.##....#...#...#...##
.....#...#.#.#.#....#...#......
#..#.#.#..#....#..#...#..#..##.
#.....#..##.....#...###..#..#.#
.....####.#..#...##..#..#..#..#
..#.....#.#........#.#.##..####
.#.....##..#.##.....#...###....
###.###....#..#..#.....#####...
#..##.##..##.#.#....#.#......#.
.#....#.##..#.#.#.......##.....
##.##...#...#....###.#....#....
.....#.######.#.#..#..#.#.....#
.#..#.##.#....#.##..#.#...##..#
.##.###..#..#..#.###...#####.#.
#...#...........#.....#.......#
#....##.#.#..##...#..####...#..
#.####......#####.....#.##..#..
.#...#....#...##..##.#.#......#
#..###.....##.#.......#.##...##

87
2019/d10/ex2/ex2.py Executable file
View file

@ -0,0 +1,87 @@
#!/usr/bin/env python
import sys
from cmath import phase
from itertools import groupby
from math import gcd, pi
from pprint import pprint
from typing import NamedTuple, Set, Tuple
class Position(NamedTuple):
x: int
y: int
def pos_to_angle_dist(pos: Position) -> Tuple[float, float]:
cartesian = complex(*pos)
angle = phase(cartesian)
if angle < -pi / 2:
angle += 2.5 * pi
else:
angle += pi / 2
return (angle, abs(cartesian))
def main() -> None:
asteroids = [
Position(x, y)
for y, line in enumerate(sys.stdin.readlines())
for x, c in enumerate(line.rstrip())
if c == "#"
]
def count_spotted(x: int, y: int) -> int:
seen: Set[Position] = set()
ans = 0
radius = 1
while True:
def is_r_away(pos: Position) -> bool:
return max(abs(pos.x - x), abs(pos.y - y)) == radius
to_visit = list(filter(is_r_away, asteroids))
radius += 1
if len(to_visit) == 0:
break
for pos in to_visit:
rel = (pos.x - x, pos.y - y)
common = gcd(*rel)
rel = Position(*(a // common for a in rel))
if rel in seen:
continue # Already have an asteroid on this path
seen.add(rel)
ans += 1
return ans
# We need to find the observatory's position as a prerequisite
ans, orig = max((count_spotted(*pos), pos) for pos in asteroids)
print(f"({orig.x}, {orig.y}): {ans}")
def to_rel(p: Position) -> Position:
return Position(*(a - o for (a, o) in zip(p, orig)))
angle_dists = sorted(
(pos_to_angle_dist(to_rel(p)), p) for p in asteroids if p != orig
)
grouped_angle_dists = [
[val[1] for val in group]
for __, group in groupby(angle_dists, key=lambda x: x[0][0])
]
def find_n_th(n: int) -> Position:
assert 0 < n < len(asteroids) # Sanity check
while n >= len(grouped_angle_dists):
for group in grouped_angle_dists:
group.pop(0)
n -= 1
return grouped_angle_dists[n - 1][0]
x, y = find_n_th(200)
print(x * 100 + y)
if __name__ == "__main__":
main()

31
2019/d10/ex2/input Normal file
View file

@ -0,0 +1,31 @@
#...##.####.#.......#.##..##.#.
#.##.#..#..#...##..##.##.#.....
#..#####.#......#..#....#.###.#
...#.#.#...#..#.....#..#..#.#..
.#.....##..#...#..#.#...##.....
##.....#..........##..#......##
.##..##.#.#....##..##.......#..
#.##.##....###..#...##...##....
##.#.#............##..#...##..#
###..##.###.....#.##...####....
...##..#...##...##..#.#..#...#.
..#.#.##.#.#.#####.#....####.#.
#......###.##....#...#...#...##
.....#...#.#.#.#....#...#......
#..#.#.#..#....#..#...#..#..##.
#.....#..##.....#...###..#..#.#
.....####.#..#...##..#..#..#..#
..#.....#.#........#.#.##..####
.#.....##..#.##.....#...###....
###.###....#..#..#.....#####...
#..##.##..##.#.#....#.#......#.
.#....#.##..#.#.#.......##.....
##.##...#...#....###.#....#....
.....#.######.#.#..#..#.#.....#
.#..#.##.#....#.##..#.#...##..#
.##.###..#..#..#.###...#####.#.
#...#...........#.....#.......#
#....##.#.#..##...#..####...#..
#.####......#####.....#.##..#..
.#...#....#...##..##.#.#......#
#..###.....##.#.......#.##...##

243
2019/d11/ex1/ex1.py Executable file
View file

@ -0,0 +1,243 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Dict, List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Position(NamedTuple):
x: int
y: int
# Up, Right, Down, Left offsets
offsets = [Position(1, 0), Position(0, 1), Position(-1, 0), Position(0, -1)]
class Color(IntEnum):
BLACK = 0
WHITE = 1
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
painter = Computer(memory)
pos = Position(0, 0)
orientation = 0
painted: Dict[Position, Color] = {}
has_painted = False
while not painter.is_halted:
try:
painter.run()
except InputInterrupt:
painter.input_list.append(int(painted.get(pos, Color.BLACK)))
except OutputInterrupt:
if has_painted:
orientation += 1 if painter.output_list.pop(0) == 1 else -1
if orientation < 0:
orientation += len(offsets)
else:
orientation = orientation % len(offsets)
offset = offsets[orientation]
pos = Position(pos.x + offset.x, pos.y + offset.y)
else:
painted[pos] = Color(painter.output_list.pop(0))
has_painted = not has_painted
print(len(painted))
if __name__ == "__main__":
main()

1
2019/d11/ex1/input Normal file
View file

@ -0,0 +1 @@
3,8,1005,8,330,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,29,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,51,1,1103,2,10,1006,0,94,1006,0,11,1,1106,13,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,1001,8,0,87,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,109,2,1105,5,10,2,103,16,10,1,1103,12,10,2,105,2,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,146,1006,0,49,2,1,12,10,2,1006,6,10,1,1101,4,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,1001,8,0,183,1,6,9,10,1006,0,32,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,213,2,1101,9,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,239,1006,0,47,1006,0,4,2,6,0,10,1006,0,58,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,102,1,8,274,2,1005,14,10,1006,0,17,1,104,20,10,1006,0,28,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1002,8,1,309,101,1,9,9,1007,9,928,10,1005,10,15,99,109,652,104,0,104,1,21101,0,937263411860,1,21102,347,1,0,1105,1,451,21101,932440724376,0,1,21102,1,358,0,1105,1,451,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,29015167015,1,21101,0,405,0,1106,0,451,21102,1,3422723163,1,21101,0,416,0,1106,0,451,3,10,104,0,104,0,3,10,104,0,104,0,21101,0,868389376360,1,21101,0,439,0,1105,1,451,21102,825544712960,1,1,21102,1,450,0,1106,0,451,99,109,2,21201,-1,0,1,21101,0,40,2,21102,482,1,3,21102,1,472,0,1106,0,515,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,477,478,493,4,0,1001,477,1,477,108,4,477,10,1006,10,509,1101,0,0,477,109,-2,2106,0,0,0,109,4,2101,0,-1,514,1207,-3,0,10,1006,10,532,21102,1,0,-3,22101,0,-3,1,22102,1,-2,2,21102,1,1,3,21101,551,0,0,1106,0,556,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,579,2207,-4,-2,10,1006,10,579,22102,1,-4,-4,1106,0,647,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,598,0,1106,0,556,22101,0,1,-4,21101,1,0,-1,2207,-4,-2,10,1006,10,617,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,639,21201,-1,0,1,21102,639,1,0,105,1,514,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0

253
2019/d11/ex2/ex2.py Executable file
View file

@ -0,0 +1,253 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Dict, List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Position(NamedTuple):
x: int
y: int
# Up, Right, Down, Left offsets
offsets = [Position(1, 0), Position(0, 1), Position(-1, 0), Position(0, -1)]
class Color(IntEnum):
BLACK = 0
WHITE = 1
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
painter = Computer(memory)
pos = Position(0, 0)
orientation = 0
painted: Dict[Position, Color] = {pos: Color.WHITE}
has_painted = False
while not painter.is_halted:
try:
painter.run()
except InputInterrupt:
painter.input_list.append(int(painted.get(pos, Color.BLACK)))
except OutputInterrupt:
if has_painted:
orientation += 1 if painter.output_list.pop(0) == 1 else -1
if orientation < 0:
orientation += len(offsets)
else:
orientation = orientation % len(offsets)
offset = offsets[orientation]
pos = Position(pos.x + offset.x, pos.y + offset.y)
else:
painted[pos] = Color(painter.output_list.pop(0))
has_painted = not has_painted
maxx, maxy = max(p.x for p in painted), max(p.y for p in painted)
minx, miny = min(p.x for p in painted), min(p.y for p in painted)
ans: List[List[str]] = []
for x in range(minx, maxx + 1):
ans.append([])
for y in range(miny, maxy + 1):
color = painted.get(Position(x, y), Color.BLACK)
ans[-1].append("" if color == Color.WHITE else " ")
lines = ["".join(l) for l in ans]
print("\n".join(reversed(lines))) # Seems like my coordinates are reversed
if __name__ == "__main__":
main()

1
2019/d11/ex2/input Normal file
View file

@ -0,0 +1 @@
3,8,1005,8,330,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,29,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,101,0,8,51,1,1103,2,10,1006,0,94,1006,0,11,1,1106,13,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,1,10,4,10,1001,8,0,87,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,1001,8,0,109,2,1105,5,10,2,103,16,10,1,1103,12,10,2,105,2,10,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1001,8,0,146,1006,0,49,2,1,12,10,2,1006,6,10,1,1101,4,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,108,0,8,10,4,10,1001,8,0,183,1,6,9,10,1006,0,32,3,8,102,-1,8,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,213,2,1101,9,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,239,1006,0,47,1006,0,4,2,6,0,10,1006,0,58,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,0,10,4,10,102,1,8,274,2,1005,14,10,1006,0,17,1,104,20,10,1006,0,28,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,1002,8,1,309,101,1,9,9,1007,9,928,10,1005,10,15,99,109,652,104,0,104,1,21101,0,937263411860,1,21102,347,1,0,1105,1,451,21101,932440724376,0,1,21102,1,358,0,1105,1,451,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,0,29015167015,1,21101,0,405,0,1106,0,451,21102,1,3422723163,1,21101,0,416,0,1106,0,451,3,10,104,0,104,0,3,10,104,0,104,0,21101,0,868389376360,1,21101,0,439,0,1105,1,451,21102,825544712960,1,1,21102,1,450,0,1106,0,451,99,109,2,21201,-1,0,1,21101,0,40,2,21102,482,1,3,21102,1,472,0,1106,0,515,109,-2,2106,0,0,0,1,0,0,1,109,2,3,10,204,-1,1001,477,478,493,4,0,1001,477,1,477,108,4,477,10,1006,10,509,1101,0,0,477,109,-2,2106,0,0,0,109,4,2101,0,-1,514,1207,-3,0,10,1006,10,532,21102,1,0,-3,22101,0,-3,1,22102,1,-2,2,21102,1,1,3,21101,551,0,0,1106,0,556,109,-4,2105,1,0,109,5,1207,-3,1,10,1006,10,579,2207,-4,-2,10,1006,10,579,22102,1,-4,-4,1106,0,647,21201,-4,0,1,21201,-3,-1,2,21202,-2,2,3,21102,1,598,0,1106,0,556,22101,0,1,-4,21101,1,0,-1,2207,-4,-2,10,1006,10,617,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,639,21201,-1,0,1,21102,639,1,0,105,1,514,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0

50
2019/d12/ex1/ex1.py Executable file
View file

@ -0,0 +1,50 @@
#!/usr/bin/env python
import re
import sys
from dataclasses import dataclass
@dataclass
class Position:
x: int
y: int
z: int
def line_to_pos(l: str) -> Position:
"<x=4, y=1, z=1>"
regex = r"<x=(?P<x>[^,]*), y=(?P<y>[^,]*), z=(?P<z>[^,]*)>"
match = re.search(regex, l)
assert match is not None # Sanity check
return Position(*(int(match.group(g)) for g in ("x", "y", "z")))
def main() -> None:
asteroids = [line_to_pos(line) for line in sys.stdin.readlines()]
velocities = [Position(0, 0, 0) for __ in asteroids]
for __ in range(1000):
for orig, v in zip(asteroids, velocities):
for other in asteroids:
if orig.x != other.x:
v.x += 1 if orig.x < other.x else -1
if orig.y != other.y:
v.y += 1 if orig.y < other.y else -1
if orig.z != other.z:
v.z += 1 if orig.z < other.z else -1
for asteroid, v in zip(asteroids, velocities):
asteroid.x += v.x
asteroid.y += v.y
asteroid.z += v.z
pot = (abs(p.x) + abs(p.y) + abs(p.z) for p in asteroids)
kin = (abs(v.x) + abs(v.y) + abs(v.z) for v in velocities)
print(sum(p * k for p, k in zip(pot, kin)))
if __name__ == "__main__":
main()

4
2019/d12/ex1/input Normal file
View file

@ -0,0 +1,4 @@
<x=4, y=1, z=1>
<x=11, y=-18, z=-1>
<x=-2, y=-10, z=-4>
<x=-7, y=-2, z=14>

77
2019/d12/ex2/ex2.py Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env python
import re
import sys
from copy import deepcopy
from dataclasses import dataclass
from math import gcd
from typing import List
@dataclass
class Position:
x: int
y: int
z: int
def line_to_pos(l: str) -> Position:
"<x=4, y=1, z=1>"
regex = r"<x=(?P<x>[^,]*), y=(?P<y>[^,]*), z=(?P<z>[^,]*)>"
match = re.search(regex, l)
assert match is not None # Sanity check
return Position(*(int(match.group(g)) for g in ("x", "y", "z")))
def lcm(a: int, b: int, c: int) -> int:
def lcm_2(a: int, b: int) -> int:
return abs(a * b) // gcd(a, b)
return lcm_2(lcm_2(a, b), c)
def main() -> None:
asteroids = [line_to_pos(line) for line in sys.stdin.readlines()]
velocities = [Position(0, 0, 0) for __ in asteroids]
cycles: List[int] = []
for attr in ("x", "y", "z"):
all_prev_pos = [deepcopy(asteroids)]
all_prev_vel = [deepcopy(velocities)]
i = 0
found = False
while not found:
i += 1
for orig, v in zip(asteroids, velocities):
for other in asteroids:
if orig.x != other.x:
v.x += 1 if orig.x < other.x else -1
if orig.y != other.y:
v.y += 1 if orig.y < other.y else -1
if orig.z != other.z:
v.z += 1 if orig.z < other.z else -1
for asteroid, v in zip(asteroids, velocities):
asteroid.x += v.x
asteroid.y += v.y
asteroid.z += v.z
for old_pos, old_vel in zip(all_prev_pos, all_prev_vel):
if all(
n.__getattribute__(attr) == o.__getattribute__(attr)
for n, o in zip(asteroids, old_pos)
) and all(
n.__getattribute__(attr) == o.__getattribute__(attr)
for n, o in zip(velocities, old_vel)
):
found = True
cycles.append(i)
print(lcm(*cycles))
if __name__ == "__main__":
main()

4
2019/d12/ex2/input Normal file
View file

@ -0,0 +1,4 @@
<x=4, y=1, z=1>
<x=11, y=-18, z=-1>
<x=-2, y=-10, z=-4>
<x=-7, y=-2, z=14>

213
2019/d13/ex1/ex1.py Executable file
View file

@ -0,0 +1,213 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Dict, Iterable, List, NamedTuple, Tuple, TypeVar
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
game = Computer(memory)
game.run_no_output_interrupt()
T = TypeVar("T")
def grouped(l: Iterable[T], n: int) -> Iterable[Tuple[T, ...]]:
return zip(*[iter(l)] * n)
print(sum(1 for __, __, tile in grouped(game.output_list, 3) if tile == 2))
if __name__ == "__main__":
main()

1
2019/d13/ex1/input Normal file

File diff suppressed because one or more lines are too long

249
2019/d13/ex2/ex2.py Executable file
View file

@ -0,0 +1,249 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Dict, Iterable, List, NamedTuple, Tuple, TypeVar
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Tile(IntEnum):
EMPTY = 0
WALL = 1
BLOCK = 2
PADDLE = 3
BALL = 4
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
memory[0] = 2 # Play for free
game = Computer(memory)
T = TypeVar("T")
def grouped(l: Iterable[T], n: int) -> Iterable[Tuple[T, ...]]:
return zip(*[iter(l)] * n)
paddle_pos = None
ball_pos = None
score = None
output_num = 0
while not game.is_halted:
try:
game.run()
except OutputInterrupt:
output_num += 1
if output_num < 3: # Not processable yet
continue
x, y = game.output_list[0:2]
if x == -1 and y == 0: # Score display
score = game.output_list[2]
else:
tile_type = Tile(game.output_list[2])
if tile_type == Tile.PADDLE:
paddle_pos = x
elif tile_type == Tile.BALL:
ball_pos = x
game.output_list.clear() # Remove processed tiles
output_num = 0 # Reset count for next output
except InputInterrupt:
assert paddle_pos is not None and ball_pos is not None # Sanity check
offset = ball_pos - paddle_pos
game.input_list.append(0 if offset == 0 else offset // abs(offset))
assert score is not None # Sanity check
print(score)
if __name__ == "__main__":
main()

1
2019/d13/ex2/input Normal file

File diff suppressed because one or more lines are too long

89
2019/d14/ex1/ex1.py Executable file
View file

@ -0,0 +1,89 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass
from math import ceil
from typing import Dict, List
@dataclass
class Ingredient:
name: str
quantity: int
@dataclass
class ReactionEquation:
quantity: int
inputs: List[Ingredient]
Reactions = Dict[str, ReactionEquation]
def solve_for(n: int, reactions: Reactions) -> int:
ore_needed = 0
wanted = [("FUEL", n)]
excess: Dict[str, int] = {}
def provide_ingredient(name: str, wanted_quantity: int) -> None:
nonlocal ore_needed
nonlocal excess
nonlocal wanted
if name == "ORE":
ore_needed += wanted_quantity # There's no recipy for this one
return
if name in excess:
# Take from excess
if excess[name] > wanted_quantity:
excess[name] -= wanted_quantity
return # Nothing left to do
wanted_quantity -= excess[name]
del excess[name] # Took everything
if wanted_quantity == 0: # In case we provided just enough by excess
return
equation = reactions[name]
reaction_num = ceil(wanted_quantity / equation.quantity)
for ingredient in equation.inputs:
needed_quantity = ingredient.quantity * reaction_num
provide_ingredient(ingredient.name, needed_quantity)
produced_quantity = equation.quantity * reaction_num
excess_quantity = produced_quantity - wanted_quantity
if excess_quantity > 0:
if name in excess:
excess[name] += excess_quantity
else:
excess[name] = excess_quantity
while len(wanted) != 0:
provide_ingredient(*(wanted.pop()))
return ore_needed
def main() -> None:
reactions: Reactions = {}
def parse_react(l: str) -> None:
def parse_ingredient(i: str) -> Ingredient:
quantity, name = i.strip().split(" ")
return Ingredient(name, int(quantity))
input_list, output_str = l.split("=>")
inputs = [i for i in map(parse_ingredient, input_list.split(", "))]
output = parse_ingredient(output_str)
reactions[output.name] = ReactionEquation(output.quantity, inputs)
for line in sys.stdin.readlines():
parse_react(line)
print(solve_for(1, reactions))
if __name__ == "__main__":
main()

59
2019/d14/ex1/input Normal file
View file

@ -0,0 +1,59 @@
10 LSZLT, 29 XQJK => 4 BMRQJ
22 HCKS => 1 GQKCZ
1 HCKS, 8 WZWRV, 18 HVZR => 7 BGFR
1 LSZLT, 1 WRKJ, 3 LJFP, 3 RNLPB, 1 NZGK, 3 LDSV, 5 RJDN, 8 HGFGC => 3 QZTXD
1 BRSGQ, 1 XGLF, 1 ZHSK, 20 LSZLT, 16 WFCPT, 3 KTWV, 1 QRJC => 4 XPKX
1 DCLR, 6 RNLPB => 5 HCKS
1 HFHFV => 3 SHLMF
2 LTMZQ, 21 FGCXN => 6 QKFKV
3 BGFR => 7 WRKJ
3 KHSB => 2 XQJL
3 SHLMF => 2 LPLG
12 SVHWT, 20 BXPSZ => 9 NBMF
2 FGCXN, 32 DCSVN => 8 TBDWZ
1 KHSB, 3 HGFGC => 6 WZWRV
27 WFCPT, 4 KTWV, 14 BRSGQ, 1 MFNK, 1 WRKJ, 2 NZGK, 24 FBFLK => 5 TRLCK
2 SVHWT => 3 QRJC
1 MNVR, 1 FKBMW => 2 FGCXN
4 GJXW => 9 JXFS
3 XQJK => 5 WNJM
1 WZVWZ, 1 XQJL => 9 SHKJV
2 DCSVN => 4 HDVC
2 GJXW => 2 RNLPB
1 QKFKV, 1 PBRWB => 5 WTZQ
14 QKFKV => 6 RDFTD
166 ORE => 1 QDSXV
2 DCSVN => 5 BXPSZ
113 ORE => 6 LTMZQ
13 MNVR => 7 RJDN
2 NZGK, 9 XQJK, 18 WRKJ => 9 KTWV
1 NZGK => 8 XQJK
6 RZCGN, 6 HDVC, 1 DLKR => 9 DSLXW
18 HVZR => 8 LJFP
7 XQJL => 1 NPDS
15 DLKR, 1 DSLXW, 26 MJFVP => 3 FBFLK
125 ORE => 9 MNVR
3 RJDN => 4 HFHFV
1 TBDWZ, 1 DCLR => 2 HVZR
2 SHKJV => 5 GJXW
7 LTMZQ, 1 QDSXV, 1 FKBMW => 3 DCSVN
9 LPLG, 11 JXFS => 3 BRSGQ
5 JXFS, 1 ZHSK, 25 XGLF => 4 MFNK
5 PBRWB => 2 SVHWT
15 SHKJV => 5 XGLF
1 XQJL, 2 NPDS => 4 DLKR
39 JXFS => 5 KSHF
6 GJXW, 1 FBFLK => 7 HGFGC
3 JXFS => 1 LSZLT
3 NBMF, 1 BMRQJ => 2 LDSV
1 JXFS, 25 GJXW, 10 HGFGC => 4 NZGK
8 QZTXD, 26 KSHF, 60 WNJM, 6 GJXW, 9 TRLCK, 20 XPKX, 21 FGCXN, 57 GQKCZ, 6 WRKJ => 1 FUEL
4 SVHWT, 1 RZCGN => 3 ZHSK
1 BXPSZ => 7 DCLR
8 RDFTD, 1 SHKJV, 1 HFHFV => 6 MJFVP
1 LTMZQ => 9 KHSB
5 WTZQ, 4 HGFGC, 4 HCKS => 9 WFCPT
184 ORE => 4 FKBMW
4 XQJL => 3 WZVWZ
12 QDSXV => 9 RZCGN
1 FBFLK, 7 HVZR => 9 PBRWB

106
2019/d14/ex2/ex2.py Executable file
View file

@ -0,0 +1,106 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass
from math import ceil
from typing import Dict, List
@dataclass
class Ingredient:
name: str
quantity: int
@dataclass
class ReactionEquation:
quantity: int
inputs: List[Ingredient]
Reactions = Dict[str, ReactionEquation]
def solve_for(n: int, reactions: Reactions) -> int:
ore_needed = 0
wanted = [("FUEL", n)]
excess: Dict[str, int] = {}
def provide_ingredient(name: str, wanted_quantity: int) -> None:
nonlocal ore_needed
nonlocal excess
nonlocal wanted
if name == "ORE":
ore_needed += wanted_quantity # There's no recipy for this one
return
if name in excess:
# Take from excess
if excess[name] > wanted_quantity:
excess[name] -= wanted_quantity
return # Nothing left to do
wanted_quantity -= excess[name]
del excess[name] # Took everything
if wanted_quantity == 0: # In case we provided just enough by excess
return
equation = reactions[name]
reaction_num = ceil(wanted_quantity / equation.quantity)
for ingredient in equation.inputs:
needed_quantity = ingredient.quantity * reaction_num
provide_ingredient(ingredient.name, needed_quantity)
produced_quantity = equation.quantity * reaction_num
excess_quantity = produced_quantity - wanted_quantity
if excess_quantity > 0:
if name in excess:
excess[name] += excess_quantity
else:
excess[name] = excess_quantity
while len(wanted) != 0:
provide_ingredient(*(wanted.pop()))
return ore_needed
def main() -> None:
reactions: Reactions = {}
def parse_react(l: str) -> None:
def parse_ingredient(i: str) -> Ingredient:
quantity, name = i.strip().split(" ")
return Ingredient(name, int(quantity))
input_list, output_str = l.split("=>")
inputs = [i for i in map(parse_ingredient, input_list.split(", "))]
output = parse_ingredient(output_str)
reactions[output.name] = ReactionEquation(output.quantity, inputs)
for line in sys.stdin.readlines():
parse_react(line)
for_one = solve_for(1, reactions)
target = 1000000000000
# Educated guesses about minimum and maximum fuel needed to use 'target' ORE
min_fuel_needed = target // for_one
max_fuel_needed = 2 * min_fuel_needed
while min_fuel_needed < max_fuel_needed:
# We already know that minimum value is valid, offset it by one for the search
mid = ceil((min_fuel_needed + max_fuel_needed) / 2)
mid_res = solve_for(mid, reactions)
if mid_res > target:
# Exclude the maximum that was already searched
max_fuel_needed = mid - 1
else:
# Keep the valid minimum value
min_fuel_needed = mid
print(max_fuel_needed)
if __name__ == "__main__":
main()

59
2019/d14/ex2/input Normal file
View file

@ -0,0 +1,59 @@
10 LSZLT, 29 XQJK => 4 BMRQJ
22 HCKS => 1 GQKCZ
1 HCKS, 8 WZWRV, 18 HVZR => 7 BGFR
1 LSZLT, 1 WRKJ, 3 LJFP, 3 RNLPB, 1 NZGK, 3 LDSV, 5 RJDN, 8 HGFGC => 3 QZTXD
1 BRSGQ, 1 XGLF, 1 ZHSK, 20 LSZLT, 16 WFCPT, 3 KTWV, 1 QRJC => 4 XPKX
1 DCLR, 6 RNLPB => 5 HCKS
1 HFHFV => 3 SHLMF
2 LTMZQ, 21 FGCXN => 6 QKFKV
3 BGFR => 7 WRKJ
3 KHSB => 2 XQJL
3 SHLMF => 2 LPLG
12 SVHWT, 20 BXPSZ => 9 NBMF
2 FGCXN, 32 DCSVN => 8 TBDWZ
1 KHSB, 3 HGFGC => 6 WZWRV
27 WFCPT, 4 KTWV, 14 BRSGQ, 1 MFNK, 1 WRKJ, 2 NZGK, 24 FBFLK => 5 TRLCK
2 SVHWT => 3 QRJC
1 MNVR, 1 FKBMW => 2 FGCXN
4 GJXW => 9 JXFS
3 XQJK => 5 WNJM
1 WZVWZ, 1 XQJL => 9 SHKJV
2 DCSVN => 4 HDVC
2 GJXW => 2 RNLPB
1 QKFKV, 1 PBRWB => 5 WTZQ
14 QKFKV => 6 RDFTD
166 ORE => 1 QDSXV
2 DCSVN => 5 BXPSZ
113 ORE => 6 LTMZQ
13 MNVR => 7 RJDN
2 NZGK, 9 XQJK, 18 WRKJ => 9 KTWV
1 NZGK => 8 XQJK
6 RZCGN, 6 HDVC, 1 DLKR => 9 DSLXW
18 HVZR => 8 LJFP
7 XQJL => 1 NPDS
15 DLKR, 1 DSLXW, 26 MJFVP => 3 FBFLK
125 ORE => 9 MNVR
3 RJDN => 4 HFHFV
1 TBDWZ, 1 DCLR => 2 HVZR
2 SHKJV => 5 GJXW
7 LTMZQ, 1 QDSXV, 1 FKBMW => 3 DCSVN
9 LPLG, 11 JXFS => 3 BRSGQ
5 JXFS, 1 ZHSK, 25 XGLF => 4 MFNK
5 PBRWB => 2 SVHWT
15 SHKJV => 5 XGLF
1 XQJL, 2 NPDS => 4 DLKR
39 JXFS => 5 KSHF
6 GJXW, 1 FBFLK => 7 HGFGC
3 JXFS => 1 LSZLT
3 NBMF, 1 BMRQJ => 2 LDSV
1 JXFS, 25 GJXW, 10 HGFGC => 4 NZGK
8 QZTXD, 26 KSHF, 60 WNJM, 6 GJXW, 9 TRLCK, 20 XPKX, 21 FGCXN, 57 GQKCZ, 6 WRKJ => 1 FUEL
4 SVHWT, 1 RZCGN => 3 ZHSK
1 BXPSZ => 7 DCLR
8 RDFTD, 1 SHKJV, 1 HFHFV => 6 MJFVP
1 LTMZQ => 9 KHSB
5 WTZQ, 4 HGFGC, 4 HCKS => 9 WFCPT
184 ORE => 4 FKBMW
4 XQJL => 3 WZVWZ
12 QDSXV => 9 RZCGN
1 FBFLK, 7 HVZR => 9 PBRWB

315
2019/d15/ex1/ex1.py Executable file
View file

@ -0,0 +1,315 @@
#!/usr/bin/env python
import heapq
import sys
from dataclasses import dataclass, field
from enum import Enum, IntEnum, auto
from typing import List, NamedTuple, Optional, Set
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Movement(IntEnum):
NORTH = 1
SOUTH = 2
WEST = 3
EAST = 4
class StatusCode(IntEnum):
BLOCKED = 0
SUCCESS = 1
ON_TANK = 2
class BlockType(Enum):
WALL = auto()
HALLWAY = auto()
OXYGEN_TANK = auto()
class Coordinate(NamedTuple):
x: int
y: int
@dataclass
class GraphNode:
memory_state: Optional[List[int]] # Only walls have no need for the memory state
block_type: BlockType
parent: Optional[Coordinate] # Only the root of the exploration has no parent
def coord_plus_dir(c: Coordinate, d: Movement) -> Coordinate:
offset = {
Movement.NORTH: Coordinate(0, 1),
Movement.SOUTH: Coordinate(0, -1),
Movement.WEST: Coordinate(-1, 0),
Movement.EAST: Coordinate(1, 0),
}
return Coordinate(*(a + b for (a, b) in zip(c, offset[d])))
def move_to_opposite(d: Movement) -> Movement:
if d == Movement.NORTH:
return Movement.SOUTH
elif d == Movement.SOUTH:
return Movement.NORTH
elif d == Movement.WEST:
return Movement.EAST
else:
return Movement.WEST
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
droid = Computer(memory)
block_map = {Coordinate(0, 0): BlockType.HALLWAY}
def dfs(p: Coordinate, direction: Movement) -> None:
end_coord = coord_plus_dir(p, direction)
if end_coord in block_map:
return # Nothing to do
droid.input_list.append(int(direction))
try:
droid.run()
except OutputInterrupt:
status = StatusCode(droid.output_list.pop(0))
if status == StatusCode.BLOCKED:
block_map[end_coord] = BlockType.WALL
return # Don't need to backtrack
block_map[end_coord] = (
BlockType.OXYGEN_TANK
if status == StatusCode.ON_TANK
else BlockType.HALLWAY
)
for d in Movement:
dfs(end_coord, d)
droid.input_list.append(int(move_to_opposite(direction)))
try:
droid.run()
except OutputInterrupt:
droid.output_list.pop(0)
for direction in Movement:
dfs(Coordinate(0, 0), direction)
assert len(droid.input_list) == 0 and len(droid.output_list) == 0 # Sanity check
block_map = {p: t for p, t in block_map.items() if t != BlockType.WALL}
oxygen_gen = (
pos for pos, block in block_map.items() if block == BlockType.OXYGEN_TANK
)
oxygen_pos = next(oxygen_gen)
assert next(oxygen_gen, None) is None # Sanity check
seen: Set[Coordinate] = set()
to_visit = [(0, oxygen_pos)]
def find_shortest() -> int:
while True:
dist, pos = heapq.heappop(to_visit)
if pos == Coordinate(0, 0):
return dist
if pos in seen:
continue
if pos not in block_map:
continue
seen.add(pos)
for d in Movement:
new_pos = coord_plus_dir(pos, d)
heapq.heappush(to_visit, (dist + 1, new_pos))
print(find_shortest())
if __name__ == "__main__":
main()

1
2019/d15/ex1/input Normal file
View file

@ -0,0 +1 @@
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,101,0,1034,1039,1001,1036,0,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1105,1,124,1002,1034,1,1039,1001,1036,0,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1106,0,124,1001,1034,-1,1039,1008,1036,0,1041,101,0,1035,1040,1001,1038,0,1043,1002,1037,1,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,1002,1035,1,1040,101,0,1038,1043,1001,1037,0,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,33,1032,1006,1032,165,1008,1040,33,1032,1006,1032,165,1101,2,0,1044,1106,0,224,2,1041,1043,1032,1006,1032,179,1101,0,1,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,68,1044,1106,0,224,1101,0,0,1044,1105,1,224,1006,1044,247,1002,1039,1,1034,102,1,1040,1035,1001,1041,0,1036,1002,1043,1,1038,1001,1042,0,1037,4,1044,1105,1,0,67,55,37,80,63,12,30,78,95,7,20,63,83,54,86,58,97,11,84,24,11,77,42,78,22,54,89,52,44,28,93,30,81,60,58,78,87,60,54,59,78,96,17,82,74,85,66,41,89,96,54,40,82,17,22,89,65,96,71,55,81,34,90,11,85,44,58,83,79,93,30,76,62,80,16,73,20,43,40,73,69,39,39,15,93,39,99,8,74,33,97,84,24,50,91,5,71,34,81,76,22,98,50,93,80,36,76,16,76,43,19,71,63,41,21,99,40,75,55,27,82,80,83,54,66,75,61,86,14,10,74,38,92,31,49,97,20,98,15,71,59,96,53,86,35,60,6,73,71,59,79,10,84,69,23,82,14,7,76,99,45,19,96,92,14,63,55,71,46,71,34,74,73,22,95,89,10,24,59,69,17,42,96,12,92,94,66,1,69,91,36,90,94,13,17,33,46,20,89,90,24,12,94,92,83,42,73,43,70,83,55,17,92,66,23,74,99,1,92,82,54,71,96,1,22,78,74,94,66,78,40,87,13,87,73,74,89,26,26,70,42,79,3,9,84,72,55,98,56,27,73,74,57,85,66,76,88,55,58,30,97,40,71,76,6,10,55,71,43,36,99,46,59,34,37,84,61,85,90,62,98,18,39,46,84,23,70,93,9,71,5,71,94,5,59,40,71,26,90,12,45,57,74,5,92,86,32,99,20,92,82,22,44,88,29,41,89,7,86,81,72,76,9,94,94,3,8,94,71,12,93,6,82,91,91,20,86,86,38,85,95,42,86,85,19,57,90,17,85,6,84,17,81,42,77,63,26,59,9,24,85,22,31,35,93,64,90,4,16,91,67,83,23,43,63,75,3,88,93,52,14,84,85,36,95,12,51,79,54,1,16,72,1,76,79,88,63,95,77,6,91,86,23,92,54,91,51,82,45,14,98,89,74,47,52,82,80,65,74,44,58,90,14,98,42,91,6,50,88,29,81,96,25,1,97,62,62,73,61,48,82,76,93,98,49,14,74,6,97,30,47,73,77,8,89,10,17,65,21,74,95,43,83,89,72,96,27,59,20,58,80,10,70,86,42,92,26,50,98,85,3,62,20,93,86,78,19,78,91,23,90,37,71,66,97,97,95,86,40,46,79,70,37,14,98,51,91,81,4,9,77,93,19,53,70,87,40,11,95,25,93,90,17,98,39,76,92,55,57,93,39,76,13,99,58,92,26,88,80,65,34,71,62,72,17,64,38,97,85,32,4,88,69,82,51,63,61,71,77,33,90,59,74,49,76,8,76,93,55,36,71,84,7,67,47,3,85,98,9,99,32,8,79,18,28,55,77,10,30,79,77,4,1,99,82,66,90,41,64,22,82,33,20,87,24,29,80,53,72,27,17,85,84,70,16,94,11,81,92,48,85,61,47,83,21,45,92,92,38,61,75,98,52,73,80,29,82,94,29,85,61,69,59,35,84,86,60,98,63,83,69,39,10,15,64,18,85,88,63,97,95,56,13,43,75,93,13,34,85,57,37,96,39,65,60,73,73,82,11,81,80,38,88,76,23,88,19,70,2,93,46,28,79,92,91,18,6,92,96,50,77,56,45,77,36,64,83,91,64,75,48,72,71,17,69,40,82,7,6,92,70,25,23,72,9,23,84,16,17,75,76,70,60,61,99,86,21,27,85,63,80,81,55,87,93,97,53,78,53,97,14,97,49,85,65,91,72,72,5,93,34,81,10,85,86,81,19,87,61,84,11,99,96,94,8,78,13,84,9,70,0,0,21,21,1,10,1,0,0,0,0,0,0

318
2019/d15/ex2/ex2.py Executable file
View file

@ -0,0 +1,318 @@
#!/usr/bin/env python
import heapq
import sys
from dataclasses import dataclass, field
from enum import Enum, IntEnum, auto
from typing import List, NamedTuple, Optional, Set
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Movement(IntEnum):
NORTH = 1
SOUTH = 2
WEST = 3
EAST = 4
class StatusCode(IntEnum):
BLOCKED = 0
SUCCESS = 1
ON_TANK = 2
class BlockType(Enum):
WALL = auto()
HALLWAY = auto()
OXYGEN_TANK = auto()
class Coordinate(NamedTuple):
x: int
y: int
@dataclass
class GraphNode:
memory_state: Optional[List[int]] # Only walls have no need for the memory state
block_type: BlockType
parent: Optional[Coordinate] # Only the root of the exploration has no parent
def coord_plus_dir(c: Coordinate, d: Movement) -> Coordinate:
offset = {
Movement.NORTH: Coordinate(0, 1),
Movement.SOUTH: Coordinate(0, -1),
Movement.WEST: Coordinate(-1, 0),
Movement.EAST: Coordinate(1, 0),
}
return Coordinate(*(a + b for (a, b) in zip(c, offset[d])))
def move_to_opposite(d: Movement) -> Movement:
if d == Movement.NORTH:
return Movement.SOUTH
elif d == Movement.SOUTH:
return Movement.NORTH
elif d == Movement.WEST:
return Movement.EAST
else:
return Movement.WEST
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
droid = Computer(memory)
block_map = {Coordinate(0, 0): BlockType.HALLWAY}
def dfs(p: Coordinate, direction: Movement) -> None:
end_coord = coord_plus_dir(p, direction)
if end_coord in block_map:
return # Nothing to do
droid.input_list.append(int(direction))
try:
droid.run()
except OutputInterrupt:
status = StatusCode(droid.output_list.pop(0))
if status == StatusCode.BLOCKED:
block_map[end_coord] = BlockType.WALL
return # Don't need to backtrack
block_map[end_coord] = (
BlockType.OXYGEN_TANK
if status == StatusCode.ON_TANK
else BlockType.HALLWAY
)
for d in Movement:
dfs(end_coord, d)
droid.input_list.append(int(move_to_opposite(direction)))
try:
droid.run()
except OutputInterrupt:
droid.output_list.pop(0)
for direction in Movement:
dfs(Coordinate(0, 0), direction)
assert len(droid.input_list) == 0 and len(droid.output_list) == 0 # Sanity check
block_map = {p: t for p, t in block_map.items() if t != BlockType.WALL}
oxygen_gen = (
pos for pos, block in block_map.items() if block == BlockType.OXYGEN_TANK
)
oxygen_pos = next(oxygen_gen)
assert next(oxygen_gen, None) is None # Sanity check
seen: Set[Coordinate] = set()
to_visit = [(0, oxygen_pos)]
max_dist = 0
def fill_oxygen() -> None:
nonlocal max_dist
while len(to_visit) != 0:
dist, pos = heapq.heappop(to_visit)
if pos in seen:
continue
if pos not in block_map:
continue
seen.add(pos)
max_dist = max(max_dist, dist)
for d in Movement:
new_pos = coord_plus_dir(pos, d)
heapq.heappush(to_visit, (dist + 1, new_pos))
fill_oxygen()
print(max_dist)
if __name__ == "__main__":
main()

1
2019/d15/ex2/input Normal file
View file

@ -0,0 +1 @@
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,101,0,1034,1039,1001,1036,0,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1105,1,124,1002,1034,1,1039,1001,1036,0,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1106,0,124,1001,1034,-1,1039,1008,1036,0,1041,101,0,1035,1040,1001,1038,0,1043,1002,1037,1,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,1002,1035,1,1040,101,0,1038,1043,1001,1037,0,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,33,1032,1006,1032,165,1008,1040,33,1032,1006,1032,165,1101,2,0,1044,1106,0,224,2,1041,1043,1032,1006,1032,179,1101,0,1,1044,1106,0,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,68,1044,1106,0,224,1101,0,0,1044,1105,1,224,1006,1044,247,1002,1039,1,1034,102,1,1040,1035,1001,1041,0,1036,1002,1043,1,1038,1001,1042,0,1037,4,1044,1105,1,0,67,55,37,80,63,12,30,78,95,7,20,63,83,54,86,58,97,11,84,24,11,77,42,78,22,54,89,52,44,28,93,30,81,60,58,78,87,60,54,59,78,96,17,82,74,85,66,41,89,96,54,40,82,17,22,89,65,96,71,55,81,34,90,11,85,44,58,83,79,93,30,76,62,80,16,73,20,43,40,73,69,39,39,15,93,39,99,8,74,33,97,84,24,50,91,5,71,34,81,76,22,98,50,93,80,36,76,16,76,43,19,71,63,41,21,99,40,75,55,27,82,80,83,54,66,75,61,86,14,10,74,38,92,31,49,97,20,98,15,71,59,96,53,86,35,60,6,73,71,59,79,10,84,69,23,82,14,7,76,99,45,19,96,92,14,63,55,71,46,71,34,74,73,22,95,89,10,24,59,69,17,42,96,12,92,94,66,1,69,91,36,90,94,13,17,33,46,20,89,90,24,12,94,92,83,42,73,43,70,83,55,17,92,66,23,74,99,1,92,82,54,71,96,1,22,78,74,94,66,78,40,87,13,87,73,74,89,26,26,70,42,79,3,9,84,72,55,98,56,27,73,74,57,85,66,76,88,55,58,30,97,40,71,76,6,10,55,71,43,36,99,46,59,34,37,84,61,85,90,62,98,18,39,46,84,23,70,93,9,71,5,71,94,5,59,40,71,26,90,12,45,57,74,5,92,86,32,99,20,92,82,22,44,88,29,41,89,7,86,81,72,76,9,94,94,3,8,94,71,12,93,6,82,91,91,20,86,86,38,85,95,42,86,85,19,57,90,17,85,6,84,17,81,42,77,63,26,59,9,24,85,22,31,35,93,64,90,4,16,91,67,83,23,43,63,75,3,88,93,52,14,84,85,36,95,12,51,79,54,1,16,72,1,76,79,88,63,95,77,6,91,86,23,92,54,91,51,82,45,14,98,89,74,47,52,82,80,65,74,44,58,90,14,98,42,91,6,50,88,29,81,96,25,1,97,62,62,73,61,48,82,76,93,98,49,14,74,6,97,30,47,73,77,8,89,10,17,65,21,74,95,43,83,89,72,96,27,59,20,58,80,10,70,86,42,92,26,50,98,85,3,62,20,93,86,78,19,78,91,23,90,37,71,66,97,97,95,86,40,46,79,70,37,14,98,51,91,81,4,9,77,93,19,53,70,87,40,11,95,25,93,90,17,98,39,76,92,55,57,93,39,76,13,99,58,92,26,88,80,65,34,71,62,72,17,64,38,97,85,32,4,88,69,82,51,63,61,71,77,33,90,59,74,49,76,8,76,93,55,36,71,84,7,67,47,3,85,98,9,99,32,8,79,18,28,55,77,10,30,79,77,4,1,99,82,66,90,41,64,22,82,33,20,87,24,29,80,53,72,27,17,85,84,70,16,94,11,81,92,48,85,61,47,83,21,45,92,92,38,61,75,98,52,73,80,29,82,94,29,85,61,69,59,35,84,86,60,98,63,83,69,39,10,15,64,18,85,88,63,97,95,56,13,43,75,93,13,34,85,57,37,96,39,65,60,73,73,82,11,81,80,38,88,76,23,88,19,70,2,93,46,28,79,92,91,18,6,92,96,50,77,56,45,77,36,64,83,91,64,75,48,72,71,17,69,40,82,7,6,92,70,25,23,72,9,23,84,16,17,75,76,70,60,61,99,86,21,27,85,63,80,81,55,87,93,97,53,78,53,97,14,97,49,85,65,91,72,72,5,93,34,81,10,85,86,81,19,87,61,84,11,99,96,94,8,78,13,84,9,70,0,0,21,21,1,10,1,0,0,0,0,0,0

29
2019/d16/ex1/ex1.py Executable file
View file

@ -0,0 +1,29 @@
#!/usr/bin/env python
import sys
from functools import reduce
from itertools import chain, cycle
from typing import Iterable, List
def sequencer(pattern: List[int], n: int) -> Iterable[int]:
gen = cycle(list(chain(*([a] * n for a in pattern))))
next(gen) # Skip the first one
yield from gen
def main() -> None:
signal = [int(d) for d in sys.stdin.read().strip()]
base_pattern = [0, 1, 0, -1]
for __ in range(100):
signal = [
abs(sum(a * b for a, b in zip(signal, sequencer(base_pattern, i + 1)))) % 10
for i in range(len(signal))
]
print(reduce(lambda a, b: a * 10 + b, signal[0:8]))
if __name__ == "__main__":
main()

1
2019/d16/ex1/input Normal file
View file

@ -0,0 +1 @@
59793513516782374825915243993822865203688298721919339628274587775705006728427921751430533510981343323758576985437451867752936052153192753660463974146842169169504066730474876587016668826124639010922391218906707376662919204980583671961374243713362170277231101686574078221791965458164785925384486127508173239563372833776841606271237694768938831709136453354321708319835083666223956618272981294631469954624760620412170069396383335680428214399523030064601263676270903213996956414287336234682903859823675958155009987384202594409175930384736760416642456784909043049471828143167853096088824339425988907292558707480725410676823614387254696304038713756368483311

29
2019/d16/ex2/ex2.py Executable file
View file

@ -0,0 +1,29 @@
#!/usr/bin/env python
import sys
from functools import reduce
from itertools import chain, cycle
from typing import Iterable, List
def main() -> None:
rep = 10000
signal = [int(d) for d in sys.stdin.read().strip()] * rep
offset = reduce(lambda a, b: a * 10 + b, signal[0:7])
assert offset >= len(signal) / 2 # Sanity check
# The trick is that the second half is only affected by itself (triangular matrix):
# For i > len(signal) / 2, new_signal[i] = sum(signal, i, len(signal))
# Therefore, we're only interested in numbers that start at the offset
signal = signal[offset:] # Only take the end we need
for __ in range(100):
for i in range(len(signal) - 1, 0, -1): # Do the sum from the end
signal[i - 1] += signal[i]
signal[i - 1] = signal[i - 1] % 10
print(reduce(lambda a, b: a * 10 + b, signal[:8]))
if __name__ == "__main__":
main()

1
2019/d16/ex2/input Normal file
View file

@ -0,0 +1 @@
59793513516782374825915243993822865203688298721919339628274587775705006728427921751430533510981343323758576985437451867752936052153192753660463974146842169169504066730474876587016668826124639010922391218906707376662919204980583671961374243713362170277231101686574078221791965458164785925384486127508173239563372833776841606271237694768938831709136453354321708319835083666223956618272981294631469954624760620412170069396383335680428214399523030064601263676270903213996956414287336234682903859823675958155009987384202594409175930384736760416642456784909043049471828143167853096088824339425988907292558707480725410676823614387254696304038713756368483311

223
2019/d17/ex1/ex1.py Executable file
View file

@ -0,0 +1,223 @@
#!/usr/bin/env python
import sys
from dataclasses import dataclass, field
from enum import IntEnum
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
camera = Computer(memory)
camera.run_no_output_interrupt()
view = "".join(chr(c) for c in camera.output_list)
mapped_view = [[c for c in line] for line in view.split("\n") if line != ""]
def is_intersection(x: int, y: int) -> bool:
neighbors_and_point = ((x, y), (x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1))
return all(mapped_view[a][b] not in (".", "X") for a, b in neighbors_and_point)
tot = 0
for x in range(1, len(mapped_view) - 1):
for y in range(1, len(mapped_view[0]) - 1): # No need to look at the borders
if is_intersection(x, y):
tot += x * y
print(tot)
if __name__ == "__main__":
main()

1
2019/d17/ex1/input Normal file
View file

@ -0,0 +1 @@
1,330,331,332,109,2952,1101,1182,0,16,1101,1467,0,24,102,1,0,570,1006,570,36,1002,571,1,0,1001,570,-1,570,1001,24,1,24,1106,0,18,1008,571,0,571,1001,16,1,16,1008,16,1467,570,1006,570,14,21101,0,58,0,1105,1,786,1006,332,62,99,21102,1,333,1,21101,73,0,0,1106,0,579,1101,0,0,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,101,0,574,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21101,340,0,1,1105,1,177,21101,477,0,1,1106,0,177,21101,514,0,1,21101,0,176,0,1105,1,579,99,21102,1,184,0,1106,0,579,4,574,104,10,99,1007,573,22,570,1006,570,165,101,0,572,1182,21101,375,0,1,21101,211,0,0,1106,0,579,21101,1182,11,1,21101,222,0,0,1105,1,979,21101,0,388,1,21102,233,1,0,1106,0,579,21101,1182,22,1,21101,0,244,0,1106,0,979,21101,401,0,1,21102,1,255,0,1106,0,579,21101,1182,33,1,21101,266,0,0,1105,1,979,21101,414,0,1,21102,1,277,0,1106,0,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21101,1182,0,1,21101,313,0,0,1105,1,622,1005,575,327,1101,0,1,575,21102,327,1,0,1106,0,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,20,14,0,109,4,2102,1,-3,586,21001,0,0,-1,22101,1,-3,-3,21102,1,0,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1105,1,597,109,-4,2105,1,0,109,5,2101,0,-4,629,21001,0,0,-2,22101,1,-4,-4,21101,0,0,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,652,21002,0,1,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21101,702,0,0,1105,1,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21101,0,731,0,1105,1,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21102,1,756,0,1105,1,786,1105,1,774,21202,-1,-11,1,22101,1182,1,1,21101,0,774,0,1105,1,622,21201,-3,1,-3,1106,0,640,109,-5,2106,0,0,109,7,1005,575,802,20102,1,576,-6,20101,0,577,-5,1106,0,814,21101,0,0,-1,21102,1,0,-5,21101,0,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,45,-3,22201,-6,-3,-3,22101,1467,-3,-3,1202,-3,1,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21102,1,1,-1,1106,0,924,1205,-2,873,21101,0,35,-4,1105,1,924,1201,-3,0,878,1008,0,1,570,1006,570,916,1001,374,1,374,1201,-3,0,895,1102,1,2,0,1201,-3,0,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21001,0,0,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,45,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,33,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1101,0,1,575,21101,973,0,0,1106,0,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,1,0,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1106,0,1041,21102,-4,1,-2,1106,0,1041,21102,1,-5,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,1202,-2,1,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,1201,-2,0,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1105,1,989,21101,0,439,1,1105,1,1150,21102,477,1,1,1106,0,1150,21102,1,514,1,21102,1149,1,0,1106,0,579,99,21102,1157,1,0,1105,1,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,1202,-5,1,1176,2102,1,-4,0,109,-6,2105,1,0,10,11,34,1,9,1,34,1,9,1,7,9,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,9,1,13,3,1,26,1,9,1,3,1,3,1,20,11,5,1,1,9,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,1,9,1,1,1,1,3,9,12,1,5,1,3,1,7,1,1,1,5,1,5,1,10,9,3,1,1,9,5,1,5,1,10,1,1,1,9,1,1,1,5,1,7,1,5,14,9,9,7,1,5,2,9,1,13,1,13,1,5,2,7,9,7,1,13,1,5,2,7,1,1,1,5,1,7,1,19,2,7,1,1,1,5,1,7,1,19,2,7,1,1,1,5,1,7,1,19,2,7,1,1,13,1,1,7,14,7,1,7,1,5,1,1,1,7,1,12,1,7,1,7,1,5,1,1,1,7,1,12,1,7,1,7,1,5,1,1,1,7,1,12,9,7,9,7,1,34,1,9,1,34,1,9,1,34,1,9,1,34,11,12

350
2019/d17/ex2/ex2.py Executable file
View file

@ -0,0 +1,350 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import Enum, IntEnum, auto
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self): # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
class Position(NamedTuple):
x: int
y: int
class Direction(Enum):
NORTH = auto()
WEST = auto()
SOUTH = auto()
EAST = auto()
DIRECTIONS = [d for d in Direction]
ARROW_DIRECTION = {
"^": Direction.NORTH,
"v": Direction.SOUTH,
"<": Direction.WEST,
">": Direction.EAST,
}
DIRECTION_OFFSET = {
Direction.NORTH: (-1, 0),
Direction.SOUTH: (1, 0),
Direction.WEST: (0, -1),
Direction.EAST: (0, 1),
}
def turn(d: Direction, turn: str) -> Direction:
def turn_left() -> Direction:
return DIRECTIONS[(DIRECTIONS.index(d) + 1) % len(DIRECTIONS)]
def turn_right() -> Direction:
return DIRECTIONS[DIRECTIONS.index(d) - 1]
if turn == "L":
return turn_left()
elif turn == "R":
return turn_right()
assert False # Sanity check
def find_arrow(mapped_view: List[List[str]]) -> Position:
for x in range(len(mapped_view)):
for y in range(len(mapped_view[0])):
if mapped_view[x][y] in ARROW_DIRECTION:
return Position(x, y)
assert False # Sanity check
def get_path(mapped_view: List[List[str]]) -> List[str]:
pos = find_arrow(mapped_view)
def pos_is_valid(p: Position) -> bool:
return 0 <= p.x < len(mapped_view) and 0 <= p.y < len(mapped_view[0])
def pos_is_scaffold(p: Position) -> bool:
return pos_is_valid(p) and mapped_view[p.x][p.y] != "."
direction = ARROW_DIRECTION[mapped_view[pos.x][pos.y]]
ans: List[str] = []
def advance_until_stopped(turn_string: str) -> bool:
nonlocal pos
nonlocal direction
d = turn(direction, turn_string)
offset = DIRECTION_OFFSET[d]
neighbor = Position(*(a + b for a, b in zip(pos, offset)))
tot = 0
while pos_is_scaffold(neighbor):
tot += 1
mapped_view[pos.x][pos.y] = "@"
pos = neighbor
neighbor = Position(*(a + b for a, b in zip(pos, offset)))
if tot == 0:
return False
direction = d
ans.append(turn_string)
ans.append(str(tot))
return True
has_no_neighbors = False
while not has_no_neighbors:
for turn_string in ("L", "R"):
if advance_until_stopped(turn_string):
break
else:
has_no_neighbors = True
return ans
def sequitur_algorithm(path: str) -> None:
# FIXME: seems like a good candidate for compression
pass
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
camera = Computer(deepcopy(memory))
camera.run_no_output_interrupt()
view = "".join(chr(c) for c in camera.output_list)
mapped_view = [[c for c in line] for line in view.split("\n") if line != ""]
path = get_path(mapped_view)
print(path)
# I didn't want to write the compression algorithm when I could just use Vim
# The answere is A,B,B,A,C,A,A,C,B,C
# A: R,8,L,12,R,8
# B: R,12,L,8,R,10
# C: R,8,L,8,L,8,R,8,R,10
ans = "A,B,B,A,C,A,A,C,B,C"
A = "R,8,L,12,R,8"
B = "R,12,L,8,R,10"
C = "R,8,L,8,L,8,R,8,R,10"
assert len(ans) <= 20 # Sanity check
assert len(A) <= 20 # Sanity check
assert len(B) <= 20 # Sanity check
assert len(C) <= 20 # Sanity check
memory[0] = 2 # Wake up the robot
robot = Computer(memory)
for c in ans:
robot.input_list.append(ord(c))
robot.input_list.append(ord("\n"))
for c in A:
robot.input_list.append(ord(c))
robot.input_list.append(ord("\n"))
for c in B:
robot.input_list.append(ord(c))
robot.input_list.append(ord("\n"))
for c in C:
robot.input_list.append(ord(c))
robot.input_list.append(ord("\n"))
for c in "n\n": # Do not output the video feed
robot.input_list.append(ord(c))
robot.run_no_output_interrupt()
print(robot.output_list.pop())
if __name__ == "__main__":
main()

1
2019/d17/ex2/input Normal file
View file

@ -0,0 +1 @@
1,330,331,332,109,2952,1101,1182,0,16,1101,1467,0,24,102,1,0,570,1006,570,36,1002,571,1,0,1001,570,-1,570,1001,24,1,24,1106,0,18,1008,571,0,571,1001,16,1,16,1008,16,1467,570,1006,570,14,21101,0,58,0,1105,1,786,1006,332,62,99,21102,1,333,1,21101,73,0,0,1106,0,579,1101,0,0,572,1101,0,0,573,3,574,101,1,573,573,1007,574,65,570,1005,570,151,107,67,574,570,1005,570,151,1001,574,-64,574,1002,574,-1,574,1001,572,1,572,1007,572,11,570,1006,570,165,101,1182,572,127,101,0,574,0,3,574,101,1,573,573,1008,574,10,570,1005,570,189,1008,574,44,570,1006,570,158,1105,1,81,21101,340,0,1,1105,1,177,21101,477,0,1,1106,0,177,21101,514,0,1,21101,0,176,0,1105,1,579,99,21102,1,184,0,1106,0,579,4,574,104,10,99,1007,573,22,570,1006,570,165,101,0,572,1182,21101,375,0,1,21101,211,0,0,1106,0,579,21101,1182,11,1,21101,222,0,0,1105,1,979,21101,0,388,1,21102,233,1,0,1106,0,579,21101,1182,22,1,21101,0,244,0,1106,0,979,21101,401,0,1,21102,1,255,0,1106,0,579,21101,1182,33,1,21101,266,0,0,1105,1,979,21101,414,0,1,21102,1,277,0,1106,0,579,3,575,1008,575,89,570,1008,575,121,575,1,575,570,575,3,574,1008,574,10,570,1006,570,291,104,10,21101,1182,0,1,21101,313,0,0,1105,1,622,1005,575,327,1101,0,1,575,21102,327,1,0,1106,0,786,4,438,99,0,1,1,6,77,97,105,110,58,10,33,10,69,120,112,101,99,116,101,100,32,102,117,110,99,116,105,111,110,32,110,97,109,101,32,98,117,116,32,103,111,116,58,32,0,12,70,117,110,99,116,105,111,110,32,65,58,10,12,70,117,110,99,116,105,111,110,32,66,58,10,12,70,117,110,99,116,105,111,110,32,67,58,10,23,67,111,110,116,105,110,117,111,117,115,32,118,105,100,101,111,32,102,101,101,100,63,10,0,37,10,69,120,112,101,99,116,101,100,32,82,44,32,76,44,32,111,114,32,100,105,115,116,97,110,99,101,32,98,117,116,32,103,111,116,58,32,36,10,69,120,112,101,99,116,101,100,32,99,111,109,109,97,32,111,114,32,110,101,119,108,105,110,101,32,98,117,116,32,103,111,116,58,32,43,10,68,101,102,105,110,105,116,105,111,110,115,32,109,97,121,32,98,101,32,97,116,32,109,111,115,116,32,50,48,32,99,104,97,114,97,99,116,101,114,115,33,10,94,62,118,60,0,1,0,-1,-1,0,1,0,0,0,0,0,0,1,20,14,0,109,4,2102,1,-3,586,21001,0,0,-1,22101,1,-3,-3,21102,1,0,-2,2208,-2,-1,570,1005,570,617,2201,-3,-2,609,4,0,21201,-2,1,-2,1105,1,597,109,-4,2105,1,0,109,5,2101,0,-4,629,21001,0,0,-2,22101,1,-4,-4,21101,0,0,-3,2208,-3,-2,570,1005,570,781,2201,-4,-3,652,21002,0,1,-1,1208,-1,-4,570,1005,570,709,1208,-1,-5,570,1005,570,734,1207,-1,0,570,1005,570,759,1206,-1,774,1001,578,562,684,1,0,576,576,1001,578,566,692,1,0,577,577,21101,702,0,0,1105,1,786,21201,-1,-1,-1,1106,0,676,1001,578,1,578,1008,578,4,570,1006,570,724,1001,578,-4,578,21101,0,731,0,1105,1,786,1106,0,774,1001,578,-1,578,1008,578,-1,570,1006,570,749,1001,578,4,578,21102,1,756,0,1105,1,786,1105,1,774,21202,-1,-11,1,22101,1182,1,1,21101,0,774,0,1105,1,622,21201,-3,1,-3,1106,0,640,109,-5,2106,0,0,109,7,1005,575,802,20102,1,576,-6,20101,0,577,-5,1106,0,814,21101,0,0,-1,21102,1,0,-5,21101,0,0,-6,20208,-6,576,-2,208,-5,577,570,22002,570,-2,-2,21202,-5,45,-3,22201,-6,-3,-3,22101,1467,-3,-3,1202,-3,1,843,1005,0,863,21202,-2,42,-4,22101,46,-4,-4,1206,-2,924,21102,1,1,-1,1106,0,924,1205,-2,873,21101,0,35,-4,1105,1,924,1201,-3,0,878,1008,0,1,570,1006,570,916,1001,374,1,374,1201,-3,0,895,1102,1,2,0,1201,-3,0,902,1001,438,0,438,2202,-6,-5,570,1,570,374,570,1,570,438,438,1001,578,558,921,21001,0,0,-4,1006,575,959,204,-4,22101,1,-6,-6,1208,-6,45,570,1006,570,814,104,10,22101,1,-5,-5,1208,-5,33,570,1006,570,810,104,10,1206,-1,974,99,1206,-1,974,1101,0,1,575,21101,973,0,0,1106,0,786,99,109,-7,2105,1,0,109,6,21101,0,0,-4,21102,1,0,-3,203,-2,22101,1,-3,-3,21208,-2,82,-1,1205,-1,1030,21208,-2,76,-1,1205,-1,1037,21207,-2,48,-1,1205,-1,1124,22107,57,-2,-1,1205,-1,1124,21201,-2,-48,-2,1106,0,1041,21102,-4,1,-2,1106,0,1041,21102,1,-5,-2,21201,-4,1,-4,21207,-4,11,-1,1206,-1,1138,2201,-5,-4,1059,1202,-2,1,0,203,-2,22101,1,-3,-3,21207,-2,48,-1,1205,-1,1107,22107,57,-2,-1,1205,-1,1107,21201,-2,-48,-2,2201,-5,-4,1090,20102,10,0,-1,22201,-2,-1,-2,2201,-5,-4,1103,1201,-2,0,0,1106,0,1060,21208,-2,10,-1,1205,-1,1162,21208,-2,44,-1,1206,-1,1131,1105,1,989,21101,0,439,1,1105,1,1150,21102,477,1,1,1106,0,1150,21102,1,514,1,21102,1149,1,0,1106,0,579,99,21102,1157,1,0,1105,1,579,204,-2,104,10,99,21207,-3,22,-1,1206,-1,1138,1202,-5,1,1176,2102,1,-4,0,109,-6,2105,1,0,10,11,34,1,9,1,34,1,9,1,7,9,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,1,9,1,7,1,7,1,18,9,1,13,3,1,26,1,9,1,3,1,3,1,20,11,5,1,1,9,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,3,1,5,1,1,1,1,1,3,1,1,1,18,1,5,1,1,9,1,1,1,1,3,9,12,1,5,1,3,1,7,1,1,1,5,1,5,1,10,9,3,1,1,9,5,1,5,1,10,1,1,1,9,1,1,1,5,1,7,1,5,14,9,9,7,1,5,2,9,1,13,1,13,1,5,2,7,9,7,1,13,1,5,2,7,1,1,1,5,1,7,1,19,2,7,1,1,1,5,1,7,1,19,2,7,1,1,1,5,1,7,1,19,2,7,1,1,13,1,1,7,14,7,1,7,1,5,1,1,1,7,1,12,1,7,1,7,1,5,1,1,1,7,1,12,1,7,1,7,1,5,1,1,1,7,1,12,9,7,9,7,1,34,1,9,1,34,1,9,1,34,1,9,1,34,11,12

128
2019/d18/ex1/ex1.py Executable file
View file

@ -0,0 +1,128 @@
#!/usr/bin/env python
import heapq
import sys
from collections import defaultdict, deque
from dataclasses import dataclass
from functools import lru_cache
from math import inf
from typing import DefaultDict, Deque, Dict, FrozenSet, Iterator, List, Tuple, Union
RawGrid = List[str]
GraphInfo = List[Tuple[str, int]]
Graph = Dict[str, GraphInfo]
@dataclass(eq=True, frozen=True) # Hash-able
class Position:
x: int
y: int
def neighbours(grid: RawGrid, pos: Position) -> Iterator[Position]:
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
new_pos = Position(pos.x + dx, pos.y + dy)
if not (0 <= new_pos.x < len(grid) and 0 <= new_pos.y < len(grid[0])):
continue
if grid[new_pos.x][new_pos.y] == "#":
continue
yield new_pos
def find_adjacent(grid: RawGrid, pos: Position) -> GraphInfo:
queue: Deque[Tuple[Position, int]] = deque()
visited = {pos}
adjacent: GraphInfo = []
for n in neighbours(grid, pos):
queue.append((n, 1)) # Distance is 1
while queue:
n, d = queue.popleft()
if n in visited:
continue
visited |= {n}
cell = grid[n.x][n.y]
if cell not in "#.@": # We don't care about those
adjacent.append((cell, d))
continue # Do not go through doors and keys
for neighbour in neighbours(grid, n):
queue.append((neighbour, d + 1))
return adjacent
def build_graph(grid: RawGrid) -> Graph:
graph = {}
for x, row in enumerate(grid):
for y, cell in enumerate(row):
if cell not in "#.":
graph[cell] = find_adjacent(grid, Position(x, y))
return graph
def solve(G: Graph, start: str) -> int:
@lru_cache(2**20)
def reachable_keys(src: str, found: FrozenSet[str]) -> List[Tuple[str, int]]:
queue = []
distance: DefaultDict[str, Union[float, int]] = defaultdict(lambda: inf)
reachable: List[Tuple[str, int]] = []
for neighbor, weight in G[src]:
queue.append((weight, neighbor)) # Weight first for heap comparisons
heapq.heapify(queue)
while queue:
dist, node = heapq.heappop(queue)
# Do key, add it to reachable if not found previously
if node.islower() and node not in found:
reachable.append((node, dist))
continue
# Do door, if not opened by a key that was found in the search
if node.lower() not in found:
continue
# If not a key and not a closed door
for neighbor, weight in G[node]:
new_dist = dist + weight
if new_dist < distance[neighbor]:
distance[neighbor] = new_dist
heapq.heappush(queue, (new_dist, neighbor))
return reachable
@lru_cache(2**20)
def min_steps(
src: str, keys_to_find: int, found: FrozenSet[str] = frozenset()
) -> int:
if keys_to_find == 0:
return 0
best = inf
for key, dist in reachable_keys(src, found):
new_keys = found | {key}
dist += min_steps(key, keys_to_find - 1, new_keys)
if dist < best:
best = dist
return int(best) # That way we throw if we kept the infinite float
total_keys = sum(node.islower() for node in G)
return min_steps(start, total_keys)
def main() -> None:
G = build_graph(list(line.strip() for line in sys.stdin.readlines()))
print(solve(G, "@"))
if __name__ == "__main__":
main()

81
2019/d18/ex1/input Normal file
View file

@ -0,0 +1,81 @@
#################################################################################
#.......#...#...#...........#.....#...#.#.....#m......#.......#.....#........u..#
#####.#.#.#.#.#.###.#######.###.#.#.#.#.#.###.###.#####.#.###.###.#.###########.#
#.....#...#...#.....#.#.....#...#...#...#.#....e#.......#...#.....#.....#.......#
#.###################.#.#####.#########.#.#####.###########.###########.#.#######
#.#...#...#...........#.#.....#.......#.#.....#.....#.....#...#.......#.#.#.....#
#.#S#.###.#.#####.#####.#.###.#.###.###.#####.#####.#.###.###.#.#.#####.#.#.###.#
#.#.#...#.#...#.#.......#.#.#.#.#...#...#.D.#.#...#...#.#.#...#.#.#.....#j..#...#
#.#.###.#.###.#.#########.#.#.###.###.###.#.#.#.#.#####.#.#.###.###.#########.###
#.#...#.#...#...#.#.........#...#.#...#.#.#...#.#.....#...#...#...#.#.#.....#...#
#.###.#.###.###.#.#.#########.#.#.#.###.#.#####.#####.#.#####.###.#.#.#.#.#.###.#
#...#.#c..#.....#.......#...#.#.#.#.#...#...#.....#.#.#.#.....#...#.#...#.#...#.#
#.###.###.#.#############.#.###.#.#.#.#.###.#####.#.#.#.#.#####.###.#.###.###.#.#
#.#...#.#.#.........#.....#...#.#.....#.#.#...#.#...#.#...#...#.....#.#...#...K.#
#.#.###.#.#########.#.#######.#.#########.###.#.###.#.#####.#.#.#######.#########
#.......#.#.......#h..#.....#.#.........#...#.#.....#.......#...#.....#.#...#...#
#.#######.#O#####.#######.#.#.#.#######.###.#.#.#######.#######.#.###F#.#.#.#.#.#
#.#....y..#...#...#.....#.#.#.#.#.#.....#...#.#.#.....#.#.....#...#.#.#...#.#.#.#
###.#####.###.#.###.###.#.###.#.#.#.###.#.#.#.###.###.#.#.###.#####.#.#.###.#.#.#
#...#.....#.#.#...#.#.Z.#...#.#.#.#.#...#.#.#.....#.#.#.#.#.#...#.....#...#...#.#
#.###.#####.#.###A#.#.###.#.#.#.#.#.#####.#########.#.#.#.#.###.#.#########.###.#
#.#.#.#.....#.#.#...#.#...#...#...#.....#.#.........#.#.#.#.#...#.#.......#.#...#
#.#.#.#####.#.#.#######.#########.#####.#.#.#####.#.#.#.#.#.#####.#.###.#.###.#.#
#.#.#...#...#.#...#.....#.....#.......#.#.#.#.#...#.#.#.#.#.....#.#.#...#.....#.#
#.#.###.#.#.#.###.#.#######.#.#####.###.#.#.#.#.#####.#.#.#.#.###.###.#########X#
#.#...#...#.#...#.#...#.....#.....#.#...#.....#.#...#.#.#.#.#...#...#.....#.....#
#.#W#.#####.###N#.###.#.#.#######.###.#.#######.#.#.#.###.#.###.###.#####.###.###
#i#.#.....#.#.#.#...#.#.#.#.....#.....#.#..r..#...#.#...#.#.#.....#.#...#...#.#.#
#.#######.#.#.#.#.###.###.#.###########.#.###.#.###.###.#.###.#####.#.#.###.#.#.#
#.......#...#.#.#...#...#.#.............#.#.#.#.#.#...#...#...#.....#.#.....#.#.#
#.#####.#.###.#.#.#.###.#.#.#############.#.#.#.#.###.#####.###.#####.#######.#.#
#.#.#...#.....#.#.#...#..t#...#.#.......#.#.#.#...#.....#.....#...#...#.....#.#.#
#.#.#.#######.#.#.###.#######.#.#.#.#####.#.#.#.###.###.#####.###.###.#.###.#.#.#
#...#.#...#...#.#...#.....#.#.#...#.....#.#.#.#.#...#.........#.#...#...T.#.#...#
###.#.#.#.#.###.###.#.###.#.#.#########.#.#.#.###.###########.#.###.#####.#.###.#
#...#...#.#.#...#...#...#...#.......#...#.#.#...#.#.....#...#...#...#...#.#...#.#
#.#######.###.###.#####.###########.#.###.#.###.#.#.###.#.#.###.#.###.#.#####.###
#.#...#v#...#.#.#.....#.........#...#...#.#.......#...#..l#...#.#.....#.....#.P.#
#.#.#.#.###.#.#.#####.#########.#.#####.#.###########.#######.#############.###.#
#...#.....#...#...............#.............................#....b..............#
#######################################.@.#######################################
#...#.#.........#.....#...........#...........#...#.....#.......#...#.....Q.#...#
#.#.#.#.#####.###.#.#.#.#####.###.#.###.#.###.#.#.#.###.#.#####.#.#.#.#.###.###.#
#.#.#.#.#...#.....#.#.#.#.#...#...#...#.#.#.....#.#...#...#.....#.#.#.#...#.#...#
#.#.#.#.#.#.#######.###.#.#.#####.###.#.#.#######.###.#####.#####.#.#.###.#.#.#.#
#.#...#.#.#.....#.#.#.B...#.....#.#...#.#.....#.....#.#...#.......#.#.#...#...#.#
#.#####.#.#####.#.#.#.#######.#.###.###.#.###.###.###.#.#####.#####.#.#.#######.#
#.#...#q#..f#.....#...#.....#.#...#.#...#.#.#...#.#.....#...#.#...#...#.#.....#.#
#.#.#.#.#.#.#######.###.###.###.#.#.#.###.#.###.###.#####.#.#.###.#####.#.###.#.#
#...#.#.#.#...#...#p..#.#.#...#.#...#...#.....#...#.#.....#.#.....#...#...#...#.#
#####.#.#####.#.#.###.#.#.###.#########.#####.###.#.#.#####.#####.###.#####.###.#
#.....#.......#.#.#...#.#...#.#.......#.#...#.#.#...#.#...#.....#.....#.#...#.#.#
#.###########.#.#.#####.###.#L#.#####R#.#.#.#.#.#####.#.#.#####.#####.#.#.###.#.#
#...........#.#.#.......#...#...#...#...#.#.#.....#...#.#.....#...#...#.#...#...#
#######.###.#.#.#########.#.#####.#.#######.#####.#.#######.#.###.#.###.###.###.#
#.......#...#.#.#.........#.......#.....#...#.....#.#.....#.#...#.#...#...#...#.#
#.#######.###.#.#.###.#################.#.###.#####.#.#.#.###.###.###.###.###.#.#
#.#.........#.#.#...#.............#.....#.........#.#.#.#.....#...#.#.......#.#.#
#.###.#######.#.###########.#####.#.###############.###.#####.#.###.#.#####.#.###
#...#.#.......#.#.........#.#...#.#.#...#.......#...#...#.#...#.#.....#...#.#...#
#.#G###.#######.#.#######.#.###.#.###.#.#.#####.#.###.###.#.###.#######.#.#####.#
#.#...#....x#.#.#.#z#.....#.....#.....#.#.....#...#...#...#.#...#.......#.#...#.#
#.###.#####.#.#.#.#.#########.#########.#####.#######.#.###.#####.#######.#.#.#.#
#k#.#.....#...#...#.#.....#...#.......#.#...#.#.......#.#...#.....#.#...#...#.#.#
#.#.#####.###.#####.#.###.#.###.#####.#.#.#.#.#.#.#####.#.###.#####.#.#.#####.#H#
#.#.....#...#.....#.#...#.#.#...#...#...#.#...#.#.#.....#.#...#...#...#...#.#.#.#
#.#.###.###.#####.#.###.#.#.#.###.#.###.#.#######.#.###.#.#.###.#.#.###.#Y#.#.#.#
#...#...#.#...#...#.....#..o#.#.#.#.....#.#.......#.#...#...#...#...#...#...#..g#
#####.###.#.###.#######.#####.#.#.#######.#####.###.###.#############.#####.###.#
#...#.#...#.....#.....#.....#.#.#...#...#.......#.....#...#...........#.#...#...#
#.#.#.###.#######.###.#######.#.###.#.###########.###.###.#.###########.#.###.###
#.#.#.#.....#.#.....#.#.......#...#.#...#...#...#...#.#...#.......#...#.I.#.#...#
#.#.#.#.###.#.#.###.#.#.#######.#.#.###.#.###.#.#.###.#.#########.###.#.###.###.#
#.#.#.#.#...#s....#.#.#.......#a#.#.....#.#...#.#.#...#.....#.....#...#.....#.#.#
#.###M#U###.#####.#.#.###.###.###.#####.#.#.###.#.#.#.#####.#.#####.#V#####.#.#.#
#.....#...#...#...#.#...#...#.#...#....n#.#...#d..#.#.#.J.#...#.....#...#..w#.#.#
#.#######.###.#####.###.#####.#.###.#####.###.#####.#.#.#.###.#####.#####.###.#.#
#.......#.#.#...#...#.#.....#.#...#.#...#...#.#.#...#.#.#.#...#...#...........#.#
#######.#.#.###E#.###.#####.#.#.#.#.###.#.###.#.#.#####.#.#####.#.#############.#
#.........#.......#.........C.#.#.......#.......#.......#.......#...............#
#################################################################################

130
2019/d18/ex2/ex2.py Executable file
View file

@ -0,0 +1,130 @@
#!/usr/bin/env python
import heapq
import sys
from collections import defaultdict, deque
from dataclasses import dataclass
from functools import lru_cache
from math import inf
from typing import DefaultDict, Deque, Dict, FrozenSet, Iterator, List, Tuple, Union
RawGrid = List[str]
GraphInfo = List[Tuple[str, int]]
Graph = Dict[str, GraphInfo]
@dataclass(eq=True, frozen=True) # Hash-able
class Position:
x: int
y: int
def neighbours(grid: RawGrid, pos: Position) -> Iterator[Position]:
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
new_pos = Position(pos.x + dx, pos.y + dy)
if not (0 <= new_pos.x < len(grid) and 0 <= new_pos.y < len(grid[0])):
continue
if grid[new_pos.x][new_pos.y] == "#":
continue
yield new_pos
def find_adjacent(grid: RawGrid, pos: Position) -> GraphInfo:
queue: Deque[Tuple[Position, int]] = deque()
visited = {pos}
adjacent: GraphInfo = []
for n in neighbours(grid, pos):
queue.append((n, 1)) # Distance is 1
while queue:
n, d = queue.popleft()
if n in visited:
continue
visited |= {n}
cell = grid[n.x][n.y]
if cell not in "#.1234": # We don't care about those
adjacent.append((cell, d))
continue # Do not go through doors and keys
for neighbour in neighbours(grid, n):
queue.append((neighbour, d + 1))
return adjacent
def build_graph(grid: RawGrid) -> Graph:
graph = {}
for x, row in enumerate(grid):
for y, cell in enumerate(row):
if cell not in "#.":
graph[cell] = find_adjacent(grid, Position(x, y))
return graph
def solve(G: Graph, start: str) -> int:
@lru_cache(2**20)
def reachable_keys(src: str, found: FrozenSet[str]) -> GraphInfo:
queue = []
distance: DefaultDict[str, Union[float, int]] = defaultdict(lambda: inf)
reachable: GraphInfo = []
for neighbor, weight in G[src]:
queue.append((weight, neighbor)) # Weight first for heap comparisons
heapq.heapify(queue)
while queue:
dist, node = heapq.heappop(queue)
# Do key, add it to reachable if not found previously
if node.islower() and node not in found:
reachable.append((node, dist))
continue
# Do door, if not opened by a key that was found in the search
if node.lower() not in found:
continue
# If not a key and not a closed door
for neighbor, weight in G[node]:
new_dist = dist + weight
if new_dist < distance[neighbor]:
distance[neighbor] = new_dist
heapq.heappush(queue, (new_dist, neighbor))
return reachable
@lru_cache(2**20)
def min_steps(
sources: str, keys_to_find: int, found: FrozenSet[str] = frozenset()
) -> Union[float, int]:
if keys_to_find == 0:
return 0
best = inf
for src in sources:
for key, dist in reachable_keys(src, found):
new_keys = found | {key}
new_sources = sources.replace(src, key)
new_dist = dist + min_steps(new_sources, keys_to_find - 1, new_keys)
if new_dist < best:
best = new_dist
return best
total_keys = sum(node.islower() for node in G)
return int(min_steps(start, total_keys)) # Throw if we kept the infinite float
def main() -> None:
G = build_graph(list(line.strip() for line in sys.stdin.readlines()))
print(solve(G, "1234"))
if __name__ == "__main__":
main()

81
2019/d18/ex2/input Normal file
View file

@ -0,0 +1,81 @@
#################################################################################
#.......#...#...#...........#.....#...#.#.....#m......#.......#.....#........u..#
#####.#.#.#.#.#.###.#######.###.#.#.#.#.#.###.###.#####.#.###.###.#.###########.#
#.....#...#...#.....#.#.....#...#...#...#.#....e#.......#...#.....#.....#.......#
#.###################.#.#####.#########.#.#####.###########.###########.#.#######
#.#...#...#...........#.#.....#.......#.#.....#.....#.....#...#.......#.#.#.....#
#.#S#.###.#.#####.#####.#.###.#.###.###.#####.#####.#.###.###.#.#.#####.#.#.###.#
#.#.#...#.#...#.#.......#.#.#.#.#...#...#.D.#.#...#...#.#.#...#.#.#.....#j..#...#
#.#.###.#.###.#.#########.#.#.###.###.###.#.#.#.#.#####.#.#.###.###.#########.###
#.#...#.#...#...#.#.........#...#.#...#.#.#...#.#.....#...#...#...#.#.#.....#...#
#.###.#.###.###.#.#.#########.#.#.#.###.#.#####.#####.#.#####.###.#.#.#.#.#.###.#
#...#.#c..#.....#.......#...#.#.#.#.#...#...#.....#.#.#.#.....#...#.#...#.#...#.#
#.###.###.#.#############.#.###.#.#.#.#.###.#####.#.#.#.#.#####.###.#.###.###.#.#
#.#...#.#.#.........#.....#...#.#.....#.#.#...#.#...#.#...#...#.....#.#...#...K.#
#.#.###.#.#########.#.#######.#.#########.###.#.###.#.#####.#.#.#######.#########
#.......#.#.......#h..#.....#.#.........#...#.#.....#.......#...#.....#.#...#...#
#.#######.#O#####.#######.#.#.#.#######.###.#.#.#######.#######.#.###F#.#.#.#.#.#
#.#....y..#...#...#.....#.#.#.#.#.#.....#...#.#.#.....#.#.....#...#.#.#...#.#.#.#
###.#####.###.#.###.###.#.###.#.#.#.###.#.#.#.###.###.#.#.###.#####.#.#.###.#.#.#
#...#.....#.#.#...#.#.Z.#...#.#.#.#.#...#.#.#.....#.#.#.#.#.#...#.....#...#...#.#
#.###.#####.#.###A#.#.###.#.#.#.#.#.#####.#########.#.#.#.#.###.#.#########.###.#
#.#.#.#.....#.#.#...#.#...#...#...#.....#.#.........#.#.#.#.#...#.#.......#.#...#
#.#.#.#####.#.#.#######.#########.#####.#.#.#####.#.#.#.#.#.#####.#.###.#.###.#.#
#.#.#...#...#.#...#.....#.....#.......#.#.#.#.#...#.#.#.#.#.....#.#.#...#.....#.#
#.#.###.#.#.#.###.#.#######.#.#####.###.#.#.#.#.#####.#.#.#.#.###.###.#########X#
#.#...#...#.#...#.#...#.....#.....#.#...#.....#.#...#.#.#.#.#...#...#.....#.....#
#.#W#.#####.###N#.###.#.#.#######.###.#.#######.#.#.#.###.#.###.###.#####.###.###
#i#.#.....#.#.#.#...#.#.#.#.....#.....#.#..r..#...#.#...#.#.#.....#.#...#...#.#.#
#.#######.#.#.#.#.###.###.#.###########.#.###.#.###.###.#.###.#####.#.#.###.#.#.#
#.......#...#.#.#...#...#.#.............#.#.#.#.#.#...#...#...#.....#.#.....#.#.#
#.#####.#.###.#.#.#.###.#.#.#############.#.#.#.#.###.#####.###.#####.#######.#.#
#.#.#...#.....#.#.#...#..t#...#.#.......#.#.#.#...#.....#.....#...#...#.....#.#.#
#.#.#.#######.#.#.###.#######.#.#.#.#####.#.#.#.###.###.#####.###.###.#.###.#.#.#
#...#.#...#...#.#...#.....#.#.#...#.....#.#.#.#.#...#.........#.#...#...T.#.#...#
###.#.#.#.#.###.###.#.###.#.#.#########.#.#.#.###.###########.#.###.#####.#.###.#
#...#...#.#.#...#...#...#...#.......#...#.#.#...#.#.....#...#...#...#...#.#...#.#
#.#######.###.###.#####.###########.#.###.#.###.#.#.###.#.#.###.#.###.#.#####.###
#.#...#v#...#.#.#.....#.........#...#...#.#.......#...#..l#...#.#.....#.....#.P.#
#.#.#.#.###.#.#.#####.#########.#.#####.#.###########.#######.#############.###.#
#...#.....#...#...............#........1#2..................#....b..............#
########################################@.#######################################
#...#.#.........#.....#...........#....3#4....#...#.....#.......#...#.....Q.#...#
#.#.#.#.#####.###.#.#.#.#####.###.#.###.#.###.#.#.#.###.#.#####.#.#.#.#.###.###.#
#.#.#.#.#...#.....#.#.#.#.#...#...#...#.#.#.....#.#...#...#.....#.#.#.#...#.#...#
#.#.#.#.#.#.#######.###.#.#.#####.###.#.#.#######.###.#####.#####.#.#.###.#.#.#.#
#.#...#.#.#.....#.#.#.B...#.....#.#...#.#.....#.....#.#...#.......#.#.#...#...#.#
#.#####.#.#####.#.#.#.#######.#.###.###.#.###.###.###.#.#####.#####.#.#.#######.#
#.#...#q#..f#.....#...#.....#.#...#.#...#.#.#...#.#.....#...#.#...#...#.#.....#.#
#.#.#.#.#.#.#######.###.###.###.#.#.#.###.#.###.###.#####.#.#.###.#####.#.###.#.#
#...#.#.#.#...#...#p..#.#.#...#.#...#...#.....#...#.#.....#.#.....#...#...#...#.#
#####.#.#####.#.#.###.#.#.###.#########.#####.###.#.#.#####.#####.###.#####.###.#
#.....#.......#.#.#...#.#...#.#.......#.#...#.#.#...#.#...#.....#.....#.#...#.#.#
#.###########.#.#.#####.###.#L#.#####R#.#.#.#.#.#####.#.#.#####.#####.#.#.###.#.#
#...........#.#.#.......#...#...#...#...#.#.#.....#...#.#.....#...#...#.#...#...#
#######.###.#.#.#########.#.#####.#.#######.#####.#.#######.#.###.#.###.###.###.#
#.......#...#.#.#.........#.......#.....#...#.....#.#.....#.#...#.#...#...#...#.#
#.#######.###.#.#.###.#################.#.###.#####.#.#.#.###.###.###.###.###.#.#
#.#.........#.#.#...#.............#.....#.........#.#.#.#.....#...#.#.......#.#.#
#.###.#######.#.###########.#####.#.###############.###.#####.#.###.#.#####.#.###
#...#.#.......#.#.........#.#...#.#.#...#.......#...#...#.#...#.#.....#...#.#...#
#.#G###.#######.#.#######.#.###.#.###.#.#.#####.#.###.###.#.###.#######.#.#####.#
#.#...#....x#.#.#.#z#.....#.....#.....#.#.....#...#...#...#.#...#.......#.#...#.#
#.###.#####.#.#.#.#.#########.#########.#####.#######.#.###.#####.#######.#.#.#.#
#k#.#.....#...#...#.#.....#...#.......#.#...#.#.......#.#...#.....#.#...#...#.#.#
#.#.#####.###.#####.#.###.#.###.#####.#.#.#.#.#.#.#####.#.###.#####.#.#.#####.#H#
#.#.....#...#.....#.#...#.#.#...#...#...#.#...#.#.#.....#.#...#...#...#...#.#.#.#
#.#.###.###.#####.#.###.#.#.#.###.#.###.#.#######.#.###.#.#.###.#.#.###.#Y#.#.#.#
#...#...#.#...#...#.....#..o#.#.#.#.....#.#.......#.#...#...#...#...#...#...#..g#
#####.###.#.###.#######.#####.#.#.#######.#####.###.###.#############.#####.###.#
#...#.#...#.....#.....#.....#.#.#...#...#.......#.....#...#...........#.#...#...#
#.#.#.###.#######.###.#######.#.###.#.###########.###.###.#.###########.#.###.###
#.#.#.#.....#.#.....#.#.......#...#.#...#...#...#...#.#...#.......#...#.I.#.#...#
#.#.#.#.###.#.#.###.#.#.#######.#.#.###.#.###.#.#.###.#.#########.###.#.###.###.#
#.#.#.#.#...#s....#.#.#.......#a#.#.....#.#...#.#.#...#.....#.....#...#.....#.#.#
#.###M#U###.#####.#.#.###.###.###.#####.#.#.###.#.#.#.#####.#.#####.#V#####.#.#.#
#.....#...#...#...#.#...#...#.#...#....n#.#...#d..#.#.#.J.#...#.....#...#..w#.#.#
#.#######.###.#####.###.#####.#.###.#####.###.#####.#.#.#.###.#####.#####.###.#.#
#.......#.#.#...#...#.#.....#.#...#.#...#...#.#.#...#.#.#.#...#...#...........#.#
#######.#.#.###E#.###.#####.#.#.#.#.###.#.###.#.#.#####.#.#####.#.#############.#
#.........#.......#.........C.#.#.......#.......#.......#.......#...............#
#################################################################################

214
2019/d19/ex1/ex1.py Executable file
View file

@ -0,0 +1,214 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from itertools import product
from typing import List, NamedTuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self) -> None: # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
lines: List[List[int]] = [[0 for i in range(50)] for __ in range(50)]
for x, y in product(range(50), range(50)):
drone = Computer(deepcopy(memory), input_list=[x, y])
drone.run_no_output_interrupt()
assert len(drone.output_list) == 1
lines[x][y] = drone.output_list.pop()
print(sum(map(sum, lines)))
if __name__ == "__main__":
main()

1
2019/d19/ex1/input Normal file
View file

@ -0,0 +1 @@
109,424,203,1,21102,11,1,0,1106,0,282,21102,18,1,0,1106,0,259,1201,1,0,221,203,1,21102,31,1,0,1106,0,282,21101,38,0,0,1106,0,259,21002,23,1,2,22102,1,1,3,21101,1,0,1,21102,57,1,0,1105,1,303,2102,1,1,222,20101,0,221,3,20101,0,221,2,21102,259,1,1,21101,80,0,0,1106,0,225,21101,0,44,2,21102,91,1,0,1105,1,303,1201,1,0,223,20101,0,222,4,21101,0,259,3,21102,225,1,2,21101,225,0,1,21102,118,1,0,1105,1,225,21002,222,1,3,21101,100,0,2,21101,133,0,0,1105,1,303,21202,1,-1,1,22001,223,1,1,21101,148,0,0,1106,0,259,2102,1,1,223,20102,1,221,4,21002,222,1,3,21102,1,12,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21102,1,195,0,106,0,108,20207,1,223,2,21002,23,1,1,21102,-1,1,3,21101,0,214,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2102,1,-4,249,21201,-3,0,1,22101,0,-2,2,22101,0,-1,3,21101,0,250,0,1105,1,225,22102,1,1,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,21202,-2,1,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,22102,1,-2,3,21101,0,343,0,1105,1,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21201,-4,0,1,21101,0,384,0,1106,0,303,1106,0,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,22102,1,1,-4,109,-5,2106,0,0

221
2019/d19/ex2/ex2.py Executable file
View file

@ -0,0 +1,221 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Iterator, List, NamedTuple, Tuple
class ParameterMode(IntEnum):
POSITION = 0 # Acts on address
IMMEDIATE = 1 # Acts on the immediate value
RELATIVE = 2 # Acts on offset to relative base
class Instruction(NamedTuple):
address: int # The address of the instruction, for convenience
op: int # The opcode
p1_mode: ParameterMode # Which mode is the first parameter in
p2_mode: ParameterMode # Which mode is the second parameter in
p3_mode: ParameterMode # Which mode is the third parameter in
def lookup_ops(index: int, memory: List[int]) -> Instruction:
digits = list(map(int, str(memory[index])))
a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values
return Instruction(
address=index,
op=d * 10 + e,
p1_mode=ParameterMode(c),
p2_mode=ParameterMode(b),
p3_mode=ParameterMode(a),
)
class InputInterrupt(Exception):
pass
class OutputInterrupt(Exception):
pass
@dataclass
class Computer:
memory: List[int] # Memory space
rip: int = 0 # Instruction pointer
input_list: List[int] = field(default_factory=list)
output_list: List[int] = field(default_factory=list)
is_halted: bool = field(default=False, init=False)
relative_base: int = field(default=0, init=False)
def run(self) -> None:
while not self.is_halted:
self.run_single()
def run_no_output_interrupt(self) -> None:
while not self.is_halted:
try:
self.run_single()
except OutputInterrupt:
continue
def run_single(self) -> None: # Returns True when halted
instr = lookup_ops(self.rip, self.memory)
if instr.op == 99: # Halt
self.is_halted = True
elif instr.op == 1: # Sum
self._do_addition(instr)
elif instr.op == 2: # Multiplication
self._do_multiplication(instr)
elif instr.op == 3: # Load from input
self._do_input(instr)
elif instr.op == 4: # Store to output
self._do_output(instr)
elif instr.op == 5: # Jump if true
self._do_jump_if_true(instr)
elif instr.op == 6: # Jump if false
self._do_jump_if_false(instr)
elif instr.op == 7: # Less than
self._do_less_than(instr)
elif instr.op == 8: # Equal to
self._do_equal_to(instr)
elif instr.op == 9: # Change relative base
self._do_change_relative_base(instr)
else:
assert False # Sanity check
def _fill_to_addres(self, address: int) -> None:
values = address - len(self.memory) + 1
if values <= 0:
return
for __ in range(values):
self.memory.append(0)
def _get_value(self, mode: ParameterMode, val: int) -> int:
if mode == ParameterMode.POSITION:
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
elif mode == ParameterMode.RELATIVE:
val += self.relative_base
assert 0 <= val # Sanity check
self._fill_to_addres(val)
return self.memory[val]
assert mode == ParameterMode.IMMEDIATE # Sanity check
return val
def _set_value(self, mode: ParameterMode, address: int, value: int) -> None:
if mode == ParameterMode.RELATIVE:
address += self.relative_base
else:
assert mode == ParameterMode.POSITION # Sanity check
assert address >= 0 # Sanity check
self._fill_to_addres(address)
self.memory[address] = value
def _do_addition(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs + rhs)
self.rip += 4 # Length of the instruction
def _do_multiplication(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, lhs * rhs)
self.rip += 4 # Length of the instruction
def _do_input(self, instr: Instruction) -> None:
if len(self.input_list) == 0:
raise InputInterrupt # No input, halt until an input is provided
value = int(self.input_list.pop(0))
param = self.memory[instr.address + 1]
self._set_value(instr.p1_mode, param, value)
self.rip += 2 # Length of the instruction
def _do_output(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.output_list.append(value)
self.rip += 2 # Length of the instruction
raise OutputInterrupt # Alert that we got an output to give
def _do_jump_if_true(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond != 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_jump_if_false(self, instr: Instruction) -> None:
cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
value = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
if cond == 0:
self.rip = value
else:
self.rip += 3 # Length of the instruction
def _do_less_than(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0)
self.rip += 4 # Length of the instruction
def _do_equal_to(self, instr: Instruction) -> None:
lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2])
dest = self.memory[instr.address + 3]
self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0)
self.rip += 4 # Length of the instruction
def _do_change_relative_base(self, instr: Instruction) -> None:
value = self._get_value(instr.p1_mode, self.memory[instr.address + 1])
self.relative_base += value
self.rip += 2 # Length of the instruction
def true_at(memory: List[int], x: int, y: int) -> bool:
drone = Computer(deepcopy(memory), input_list=[x, y])
drone.run_no_output_interrupt()
assert len(drone.output_list) == 1
return drone.output_list.pop() == 1
def main() -> None:
memory = [int(n) for n in sys.stdin.read().split(",")]
x = 0
y = 0
size = 100
while not true_at(memory, x + size - 1, y):
y += 1
while not true_at(memory, x, y + size - 1):
x += 1
print((x * 10000 + y))
if __name__ == "__main__":
main()

1
2019/d19/ex2/input Normal file
View file

@ -0,0 +1 @@
109,424,203,1,21102,11,1,0,1106,0,282,21102,18,1,0,1106,0,259,1201,1,0,221,203,1,21102,31,1,0,1106,0,282,21101,38,0,0,1106,0,259,21002,23,1,2,22102,1,1,3,21101,1,0,1,21102,57,1,0,1105,1,303,2102,1,1,222,20101,0,221,3,20101,0,221,2,21102,259,1,1,21101,80,0,0,1106,0,225,21101,0,44,2,21102,91,1,0,1105,1,303,1201,1,0,223,20101,0,222,4,21101,0,259,3,21102,225,1,2,21101,225,0,1,21102,118,1,0,1105,1,225,21002,222,1,3,21101,100,0,2,21101,133,0,0,1105,1,303,21202,1,-1,1,22001,223,1,1,21101,148,0,0,1106,0,259,2102,1,1,223,20102,1,221,4,21002,222,1,3,21102,1,12,2,1001,132,-2,224,1002,224,2,224,1001,224,3,224,1002,132,-1,132,1,224,132,224,21001,224,1,1,21102,1,195,0,106,0,108,20207,1,223,2,21002,23,1,1,21102,-1,1,3,21101,0,214,0,1105,1,303,22101,1,1,1,204,1,99,0,0,0,0,109,5,2102,1,-4,249,21201,-3,0,1,22101,0,-2,2,22101,0,-1,3,21101,0,250,0,1105,1,225,22102,1,1,-4,109,-5,2106,0,0,109,3,22107,0,-2,-1,21202,-1,2,-1,21201,-1,-1,-1,22202,-1,-2,-2,109,-3,2106,0,0,109,3,21207,-2,0,-1,1206,-1,294,104,0,99,21202,-2,1,-2,109,-3,2105,1,0,109,5,22207,-3,-4,-1,1206,-1,346,22201,-4,-3,-4,21202,-3,-1,-1,22201,-4,-1,2,21202,2,-1,-1,22201,-4,-1,1,22102,1,-2,3,21101,0,343,0,1105,1,303,1105,1,415,22207,-2,-3,-1,1206,-1,387,22201,-3,-2,-3,21202,-2,-1,-1,22201,-3,-1,3,21202,3,-1,-1,22201,-3,-1,2,21201,-4,0,1,21101,0,384,0,1106,0,303,1106,0,415,21202,-4,-1,-4,22201,-4,-3,-4,22202,-3,-2,-2,22202,-2,-4,-4,22202,-3,-2,-3,21202,-4,-1,-2,22201,-3,-2,1,22102,1,1,-4,109,-5,2106,0,0

17
2020/d01/ex1/ex1.py Executable file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env python
import functools
import itertools
import operator
import sys
def main() -> None:
values = [int(n) for n in sys.stdin.readlines()]
for tup in itertools.combinations(values, 2):
if sum(tup) == 2020:
print(functools.reduce(operator.mul, tup))
break
if __name__ == "__main__":
main()

200
2020/d01/ex1/input Normal file
View file

@ -0,0 +1,200 @@
1742
1763
1238
1424
1736
1903
1580
1847
1860
1933
1779
1901
1984
1861
1769
1896
1428
2010
1673
1491
1996
1746
1973
1696
1616
2006
1890
1600
1991
1724
1804
1794
462
1706
2002
1939
1834
1312
1943
1465
1405
1459
1659
1288
1241
1935
1294
1388
1772
1945
1649
813
1956
1274
1686
1404
1770
1631
1366
1321
1353
1685
1365
1738
1911
1235
1495
1837
1456
1283
1929
1326
1735
1604
1223
1261
1844
1850
1429
277
1848
1818
1395
1522
1863
1475
1562
1351
1538
1313
1416
1690
1539
1338
1982
1297
1821
780
1859
1420
1934
1303
1731
1714
1702
1417
1872
1998
1908
1957
1270
1359
1760
1997
1773
2000
1203
1880
1955
1273
1775
1893
1237
1707
1885
1900
1801
1367
1561
1524
1678
1511
1623
1464
1477
1733
1423
1575
1851
2007
1651
804
1836
1849
1713
1401
1502
1806
1506
1646
1968
1253
1889
1759
1734
1611
1558
1256
1657
1778
1953
1578
1717
1498
1381
1919
1512
1391
384
1802
1573
1940
1323
2003
1689
1936
1368
1962
1964
1586
1619
1482
1445
372
1792
96
1468
1999
1301
1757
1613
1807
1941
1642
1557
1884
1626
489
1989
1327

17
2020/d01/ex2/ex2.py Executable file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env python
import functools
import itertools
import operator
import sys
def main() -> None:
values = [int(n) for n in sys.stdin.readlines()]
for tup in itertools.combinations(values, 3):
if sum(tup) == 2020:
print(functools.reduce(operator.mul, tup))
break
if __name__ == "__main__":
main()

200
2020/d01/ex2/input Normal file
View file

@ -0,0 +1,200 @@
1742
1763
1238
1424
1736
1903
1580
1847
1860
1933
1779
1901
1984
1861
1769
1896
1428
2010
1673
1491
1996
1746
1973
1696
1616
2006
1890
1600
1991
1724
1804
1794
462
1706
2002
1939
1834
1312
1943
1465
1405
1459
1659
1288
1241
1935
1294
1388
1772
1945
1649
813
1956
1274
1686
1404
1770
1631
1366
1321
1353
1685
1365
1738
1911
1235
1495
1837
1456
1283
1929
1326
1735
1604
1223
1261
1844
1850
1429
277
1848
1818
1395
1522
1863
1475
1562
1351
1538
1313
1416
1690
1539
1338
1982
1297
1821
780
1859
1420
1934
1303
1731
1714
1702
1417
1872
1998
1908
1957
1270
1359
1760
1997
1773
2000
1203
1880
1955
1273
1775
1893
1237
1707
1885
1900
1801
1367
1561
1524
1678
1511
1623
1464
1477
1733
1423
1575
1851
2007
1651
804
1836
1849
1713
1401
1502
1806
1506
1646
1968
1253
1889
1759
1734
1611
1558
1256
1657
1778
1953
1578
1717
1498
1381
1919
1512
1391
384
1802
1573
1940
1323
2003
1689
1936
1368
1962
1964
1586
1619
1482
1445
372
1792
96
1468
1999
1301
1757
1613
1807
1941
1642
1557
1884
1626
489
1989
1327

42
2020/d02/ex1/ex1.py Executable file
View file

@ -0,0 +1,42 @@
#!/usr/bin/env python
import re
import sys
from dataclasses import dataclass
from typing import List
@dataclass
class Policy:
min: int
max: int
letter: str
@dataclass
class Password:
policy: Policy
password: str
def is_valid(pwd: Password) -> bool:
occurences = pwd.password.count(pwd.policy.letter)
return pwd.policy.min <= occurences <= pwd.policy.max
def solve(passwords: List[Password]) -> int:
return sum(map(is_valid, passwords))
def main() -> None:
pattern = re.compile("([0-9]+)-([0-9]+) (.): (.+)")
input = [
Password(Policy(int(m.group(1)), int(m.group(2)), m.group(3)), m.group(4))
for m in (pattern.match(line) for line in sys.stdin.readlines())
if m
]
print(solve(input))
if __name__ == "__main__":
main()

1000
2020/d02/ex1/input Normal file

File diff suppressed because it is too large Load diff

43
2020/d02/ex2/ex2.py Executable file
View file

@ -0,0 +1,43 @@
#!/usr/bin/env python
import re
import sys
from dataclasses import dataclass
from typing import List
@dataclass
class Policy:
min: int
max: int
letter: str
@dataclass
class Password:
policy: Policy
password: str
def is_valid(pwd: Password) -> bool:
min = pwd.password[pwd.policy.min - 1] == pwd.policy.letter
max = pwd.password[pwd.policy.max - 1] == pwd.policy.letter
return min ^ max
def solve(passwords: List[Password]) -> int:
return sum(map(is_valid, passwords))
def main() -> None:
pattern = re.compile("([0-9]+)-([0-9]+) (.): (.+)")
input = [
Password(Policy(int(m.group(1)), int(m.group(2)), m.group(3)), m.group(4))
for m in (pattern.match(line) for line in sys.stdin.readlines())
if m
]
print(solve(input))
if __name__ == "__main__":
main()

1000
2020/d02/ex2/input Normal file

File diff suppressed because it is too large Load diff

25
2020/d03/ex1/ex1.py Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env python
import sys
from typing import List, Tuple
def solve(trees: List[str], delta: Tuple[int, int]) -> int:
x, y = 0, 0
sum = 0
while True:
x += delta[0]
y += delta[1]
if y >= len(trees):
break
sum += trees[y][x % len(trees[0])] == "#"
return sum
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input, (3, 1)))
if __name__ == "__main__":
main()

323
2020/d03/ex1/input Normal file
View file

@ -0,0 +1,323 @@
...............#.#.............
##..#....................#...##
......#..#.#.....#..#.#.##.....
.........#...#..............#.#
............#.......##.........
...#.....#.....#...#.....#..#..
..............#..##.#..#......#
.##.....#.....#......##.#......
.#..........###....#...##....#.
.....#....#.#.......#......##..
.#....#......#.......#........#
..#.#.......#..##.....##.......
...#.#....#.......#.......#...#
##.##...##..#......#.#.....#..#
.#.#.......#..#.#......#...#.#.
#.......##.......#...#.........
.....#......#.#.#.....#....##..
.#.#........#....#..#..#.......
...#....#..###.........#.....#.
........#........#........#....
..##..............#.....#.#..#.
.#...##.............#.#........
....#..#...........#.......#...
..#....#.....................#.
#.#..................##......##
.#.##....#......#........#.....
.........##.....#....#...##..#.
#..........#..#.#.............#
.........#...#.#.#.#..##..##...
#...#.....#..#..#....#...#.....
..##.....#..................#..
#..###.....#....#.......#..#...
...##.##..#............#......#
........###.........###......#.
#..##....#.........#.........#.
....#.....................#....
#..#..##..#..####.##..#.....##.
..#...#.#....#....##.....#.....
...#.#.........#.....#.#.......
....#................#..#...##.
....#..#..........#...#.#.##...
........#..##............#....#
...#......##..........#.##...#.
.......##......................
.......##..........#....#.#...#
......###.##..##..#....#...#..#
#.#...........##.....#........#
..#...........#..###....#.#.#..
........#...........#......##..
.........#...##.###...###..#...
.....#.....#..##.........##....
...##..............#.....#...##
.##....#.......###.....#.......
.#...........##.............##.
......#..#..##.##......#......#
........###........#......#.#..
#.#....#.....#........#......#.
.##..#.........##...##....#....
.....#.........#...##.....#....
.............#........###....#.
......#.......#.#........#.#...
..#....#.#...#....#...#.#...##.
#...#......##..##......#.##.###
...##.#....#...#....#.........#
...#..####.....##.#..#.#...##..
##.#..#....##......#......##...
###.........#.#..#.#.....#.....
...#........#..##...#.#.#..#.#.
...###..#.###.#...#............
....................###........
...........#...........#.......
#..............#.#.........###.
....................##.....#..#
#.#.....#.......#...#..........
.#...#......#....##...#...#....
.....#.##..................###.
.........#.#..#.#......#.......
.......#.....##..#.##.#........
..#..........#.###.....#....#..
......#.............#.#........
........##....#........#.......
...#.............#....#.#......
#........#..####.....#.....#.#.
.##......##...#........#..#.#..
....##....#...#...#..##...#.#..
#.##...###..#....##.#..........
....#.#...#.#...#..##.###...#..
#.....##..#..#....#.#.....##...
.#..#..........##.#.....##.....
.#..#........#.#.#.#...........
.#..#.....#...........#...#....
...#......##..........##..#....
...#..#....#.##...#..#.....###.
#.#....#.....##................
#..#......#.#.#.......#........
......#....#.#....#..##....#..#
.#.....#.#....###.##.........#.
.###..#.....#........#.#.......
.#...#......#..#.#......#.....#
#...............####...#.....#.
.......#..........##.#........#
#........##....##.....###..##..
#..#.....#..##.....#....#..#...
#.....#.......##......#.#.....#
#.##..#......##..#.............
##...#.....#........##.........
....#..##....#...#.......#.#...
....#...#...##..#....#..#...#..
..............#.#...#....###...
...#....#..##...##..#....##....
#.##.#..#..#......#.#.#.#...#..
.......#..#..##........#......#
##.#....#....##.#......##.#....
.#...#..............#........#.
.#.#....#.........#............
.#..#..###.............#....#..
#......#...#.#..##..#...#....#.
.......................#...#.#.
.............#..#...##.........
..#.#..#....#....#........#....
#......#.##..#...#.#...........
.....#....#...........##.#..#..
..#.#.....#..............#.#...
#.......#.....#................
#..............#...#....#...#..
...#...##..#..#............#...
......###.....................#
.........#.......##..#....#....
........#...#.##..#.##......#..
....###..#.#...#...#..#.#...###
##...#...##.#...#.#...#.#....#.
.........#...#.....###.........
...#........##..#.......##.....
.#.......##.........#.....##..#
.#..................#...#......
.##..#..#.#.....#.###..........
...#.....##..#.........#...#...
.#......#.#.......#.#..........
.........#.#...#..........#.#..
#..........#.##..#.##....#.....
.#.#....#.....#..##.....#...#..
..#........##...##..#..#....#..
#...........##....#..###....#..
...........##.........####...#.
..#........###...#.#.........#.
.#...............#.##.#.#...#..
.#.##..#.....#.#.....##..#.....
...#...#..#.##.##...#.......##.
..#...#...#......##.##.##...#..
##....#...#...#...............#
...##...........#......#..#.#..
#.........#......#.#.##.....#..
........#..#.........##........
..#.#....###.....##..#...#.....
.........#...#.......#.....##..
##.....................#...##..
.#.#..#......#.................
.....###..#......#..###..#.....
...#.....##.........#......#..#
......##.....#...#........#.#..
..#.#...#......#...#.##.##.....
...#..........#...#.......#..##
.###........#........##........
..#.#.#..........#.#...##......
.........#........#......###..#
....##..#.........#...........#
..####..#............##.......#
.....##.#..##.........#...#.#..
...#.........#.....#.....#.....
.......#...#..#...##.........#.
...#...#..#...#....#..#........
#............##.##...#.........
.#.#.....#.......####.....#....
..............#......#.#.......
..............#...........#...#
#...#........###....#.#....#.#.
##.#..#..#......#......#.#.#...
.#..#.....#..#.#..#.#.......##.
......##.#...#...#......#...#..
#...........##....#.#..........
....#.......###.#...#..........
.......................#.....#.
........#...#..#...#.#.#.#.#...
.#.#...........#......##...#...
.........................#.....
.................#.##.#...##...
...#...##.....#.....##....#.#..
...#...#...................#...
...#..#..#...#...#....#........
#....#...#.....#...............
.......#...........#...#.......
....#....#.....##.......#......
.......#..........##...........
.#.#........#..##....#......#..
.....#.......#.#.........#...#.
.#..####.#.#...............#..#
.....###..#..#..........#.#..##
..#.......#...#.....##..#..#.#.
#....#......#..................
........#.##.#....#...........#
....#.#....##..#.#.....##......
...#..#.......#....#.....#.#.#.
#...#......#.....#.#..........#
....#....#...............#.....
..###......................###.
.##....#..#.......###.....#..#.
..###............#........#.##.
.#........#......#.....#..#....
....#..##...#...#.###.......#.#
.......#.##...........#.#..#...
.....#...##....................
....#....#...##......#.........
..#............##....###.#...#.
.#........#...............#....
#..#.#.##.........#..##....##..
#.#....#..#.##....##...#.#.....
.....#.....##....#.#........#..
#..#...#...#....#....#.........
...#........#..#.#.....##......
..#...#...#................##..
#........#.#.##.......#.#...#..
#......#..####.##.....#.#..#.#.
............#..#.#....#......##
..#.....##....#...#.#..........
...#...#.........#...#.#.......
.###..#.......##.##.....#.#.#..
...#....#...............##.#...
....##..#..#..#.#......##.....#
#.#..............##...##...####
.....#.##...#.#...............#
.##.....#.........#.......#.#.#
#.#..#.....#.......#.......#..#
...#.#.....#.....#......#......
.......#....#..#.#..........#..
......#......#.##...#..........
.....#.......###...#...#.#.....
#..#.#.........#.....#.##....#.
..#.#.........#..#..#..#.....#.
.#..##..#..#....#......#.##..#.
...##......###.....#.##.##.....
.#.....#...#..#...#............
##..##..#.##....#..#...........
...#..##..#..#.............#.##
...............##............#.
..#.....##........##.#...#....#
.#.#...#.#.#..#.#.....#....#...
.#....#...............#..#.....
....#.##..#....#......#...###..
#................###...#.#.....
...#...#......##..#.#....#.....
.#....#....#.#...##............
....#...##..#..#........#.##...
..##.....#..#..##..............
..#..##..#.#..##....#....#....#
...##.............#............
#....#....#.#........#.....##.#
.....#..#.#.....####...###.....
................#......#.......
.....#.#.#.#.#....#..#........#
.##.#...#.#.......##....#....#.
.....#........#................
..#.....#..#...#..#...........#
.#.....#...##.....##..#.#....##
......#.......#..#......##.#...
#.#..........#.##.#........#...
...#..#.............#..........
#..#..#..........#..##.#.......
.#..#...............####..#....
.......#.....#......#.....#.#..
.#...............#...#.........
.#..#..........#..#.#..##..#..#
......##..#.....#..#......###..
..........#...#..#.......#.....
.#.#.#..#.....#.##.#...#..#....
........#.......#.....#.#......
......#.....##.....#....##.#...
...............#......#.......#
..#.#...#.....#.#...##......#..
#.#.........#.#...#........####
#..........##..#..#........##..
.............#..#.......##.#..#
..#........#.#....#........#.#.
.#......####..#..#.............
............###.......#.#..#...
#.##......##...#...#.........#.
....##.#.#.#......#....#..#...#
.#..#.#....#...#.........#.....
#...#.....##............#...#..
#.#...#..#.................#...
............#.#..#.....#.#.#..#
...................#....#.##...
.....#...#.#....#....#.#......#
.......##.#.#......##..........
.#..#...##.#...#..#......#.....
......#.#..#..###..##..##......
.#.#.#.#.....#...###.....#..#..
.#....#.....#.......#.......#..
..........##.........####......
.#.#.............#..#.#...#....
........#........##...#.#....#.
........#......................
..#.#....#...............#...##
.......#.#...#..#.....##......#
.#...#....#..........##........
.#.........#.#............##...
.....#......##...#.......#..#..
#.#..#.............#...#...#...
......#.......#............#...
...........##....#......##.....
.#.#..#.....................#..
##..##.....###..##.#...........
...##......##....#...##.....#..
#...#.##.............#.........
......#..#.........###.#......#
#.#.....#.....................#
....#####.....##........#.#..#.
...........##..##.###..........
..........##.....#........#...#
.......#..#......#.....##..##.#
.....##.#........#.........#...
......##......................#
.#.......#.#.#............#..#.
.....##.#.......#.#........#...

33
2020/d03/ex2/ex2.py Executable file
View file

@ -0,0 +1,33 @@
#!/usr/bin/env python
import sys
from math import prod
from typing import List, Tuple
def solve(trees: List[str], delta: Tuple[int, int]) -> int:
x, y = 0, 0
sum = 0
while True:
x += delta[0]
y += delta[1]
if y >= len(trees):
break
sum += trees[y][x % len(trees[0])] == "#"
return sum
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
deltas = [
(1, 1),
(3, 1),
(5, 1),
(7, 1),
(1, 2),
]
print(prod(solve(input, delt) for delt in deltas))
if __name__ == "__main__":
main()

323
2020/d03/ex2/input Normal file
View file

@ -0,0 +1,323 @@
...............#.#.............
##..#....................#...##
......#..#.#.....#..#.#.##.....
.........#...#..............#.#
............#.......##.........
...#.....#.....#...#.....#..#..
..............#..##.#..#......#
.##.....#.....#......##.#......
.#..........###....#...##....#.
.....#....#.#.......#......##..
.#....#......#.......#........#
..#.#.......#..##.....##.......
...#.#....#.......#.......#...#
##.##...##..#......#.#.....#..#
.#.#.......#..#.#......#...#.#.
#.......##.......#...#.........
.....#......#.#.#.....#....##..
.#.#........#....#..#..#.......
...#....#..###.........#.....#.
........#........#........#....
..##..............#.....#.#..#.
.#...##.............#.#........
....#..#...........#.......#...
..#....#.....................#.
#.#..................##......##
.#.##....#......#........#.....
.........##.....#....#...##..#.
#..........#..#.#.............#
.........#...#.#.#.#..##..##...
#...#.....#..#..#....#...#.....
..##.....#..................#..
#..###.....#....#.......#..#...
...##.##..#............#......#
........###.........###......#.
#..##....#.........#.........#.
....#.....................#....
#..#..##..#..####.##..#.....##.
..#...#.#....#....##.....#.....
...#.#.........#.....#.#.......
....#................#..#...##.
....#..#..........#...#.#.##...
........#..##............#....#
...#......##..........#.##...#.
.......##......................
.......##..........#....#.#...#
......###.##..##..#....#...#..#
#.#...........##.....#........#
..#...........#..###....#.#.#..
........#...........#......##..
.........#...##.###...###..#...
.....#.....#..##.........##....
...##..............#.....#...##
.##....#.......###.....#.......
.#...........##.............##.
......#..#..##.##......#......#
........###........#......#.#..
#.#....#.....#........#......#.
.##..#.........##...##....#....
.....#.........#...##.....#....
.............#........###....#.
......#.......#.#........#.#...
..#....#.#...#....#...#.#...##.
#...#......##..##......#.##.###
...##.#....#...#....#.........#
...#..####.....##.#..#.#...##..
##.#..#....##......#......##...
###.........#.#..#.#.....#.....
...#........#..##...#.#.#..#.#.
...###..#.###.#...#............
....................###........
...........#...........#.......
#..............#.#.........###.
....................##.....#..#
#.#.....#.......#...#..........
.#...#......#....##...#...#....
.....#.##..................###.
.........#.#..#.#......#.......
.......#.....##..#.##.#........
..#..........#.###.....#....#..
......#.............#.#........
........##....#........#.......
...#.............#....#.#......
#........#..####.....#.....#.#.
.##......##...#........#..#.#..
....##....#...#...#..##...#.#..
#.##...###..#....##.#..........
....#.#...#.#...#..##.###...#..
#.....##..#..#....#.#.....##...
.#..#..........##.#.....##.....
.#..#........#.#.#.#...........
.#..#.....#...........#...#....
...#......##..........##..#....
...#..#....#.##...#..#.....###.
#.#....#.....##................
#..#......#.#.#.......#........
......#....#.#....#..##....#..#
.#.....#.#....###.##.........#.
.###..#.....#........#.#.......
.#...#......#..#.#......#.....#
#...............####...#.....#.
.......#..........##.#........#
#........##....##.....###..##..
#..#.....#..##.....#....#..#...
#.....#.......##......#.#.....#
#.##..#......##..#.............
##...#.....#........##.........
....#..##....#...#.......#.#...
....#...#...##..#....#..#...#..
..............#.#...#....###...
...#....#..##...##..#....##....
#.##.#..#..#......#.#.#.#...#..
.......#..#..##........#......#
##.#....#....##.#......##.#....
.#...#..............#........#.
.#.#....#.........#............
.#..#..###.............#....#..
#......#...#.#..##..#...#....#.
.......................#...#.#.
.............#..#...##.........
..#.#..#....#....#........#....
#......#.##..#...#.#...........
.....#....#...........##.#..#..
..#.#.....#..............#.#...
#.......#.....#................
#..............#...#....#...#..
...#...##..#..#............#...
......###.....................#
.........#.......##..#....#....
........#...#.##..#.##......#..
....###..#.#...#...#..#.#...###
##...#...##.#...#.#...#.#....#.
.........#...#.....###.........
...#........##..#.......##.....
.#.......##.........#.....##..#
.#..................#...#......
.##..#..#.#.....#.###..........
...#.....##..#.........#...#...
.#......#.#.......#.#..........
.........#.#...#..........#.#..
#..........#.##..#.##....#.....
.#.#....#.....#..##.....#...#..
..#........##...##..#..#....#..
#...........##....#..###....#..
...........##.........####...#.
..#........###...#.#.........#.
.#...............#.##.#.#...#..
.#.##..#.....#.#.....##..#.....
...#...#..#.##.##...#.......##.
..#...#...#......##.##.##...#..
##....#...#...#...............#
...##...........#......#..#.#..
#.........#......#.#.##.....#..
........#..#.........##........
..#.#....###.....##..#...#.....
.........#...#.......#.....##..
##.....................#...##..
.#.#..#......#.................
.....###..#......#..###..#.....
...#.....##.........#......#..#
......##.....#...#........#.#..
..#.#...#......#...#.##.##.....
...#..........#...#.......#..##
.###........#........##........
..#.#.#..........#.#...##......
.........#........#......###..#
....##..#.........#...........#
..####..#............##.......#
.....##.#..##.........#...#.#..
...#.........#.....#.....#.....
.......#...#..#...##.........#.
...#...#..#...#....#..#........
#............##.##...#.........
.#.#.....#.......####.....#....
..............#......#.#.......
..............#...........#...#
#...#........###....#.#....#.#.
##.#..#..#......#......#.#.#...
.#..#.....#..#.#..#.#.......##.
......##.#...#...#......#...#..
#...........##....#.#..........
....#.......###.#...#..........
.......................#.....#.
........#...#..#...#.#.#.#.#...
.#.#...........#......##...#...
.........................#.....
.................#.##.#...##...
...#...##.....#.....##....#.#..
...#...#...................#...
...#..#..#...#...#....#........
#....#...#.....#...............
.......#...........#...#.......
....#....#.....##.......#......
.......#..........##...........
.#.#........#..##....#......#..
.....#.......#.#.........#...#.
.#..####.#.#...............#..#
.....###..#..#..........#.#..##
..#.......#...#.....##..#..#.#.
#....#......#..................
........#.##.#....#...........#
....#.#....##..#.#.....##......
...#..#.......#....#.....#.#.#.
#...#......#.....#.#..........#
....#....#...............#.....
..###......................###.
.##....#..#.......###.....#..#.
..###............#........#.##.
.#........#......#.....#..#....
....#..##...#...#.###.......#.#
.......#.##...........#.#..#...
.....#...##....................
....#....#...##......#.........
..#............##....###.#...#.
.#........#...............#....
#..#.#.##.........#..##....##..
#.#....#..#.##....##...#.#.....
.....#.....##....#.#........#..
#..#...#...#....#....#.........
...#........#..#.#.....##......
..#...#...#................##..
#........#.#.##.......#.#...#..
#......#..####.##.....#.#..#.#.
............#..#.#....#......##
..#.....##....#...#.#..........
...#...#.........#...#.#.......
.###..#.......##.##.....#.#.#..
...#....#...............##.#...
....##..#..#..#.#......##.....#
#.#..............##...##...####
.....#.##...#.#...............#
.##.....#.........#.......#.#.#
#.#..#.....#.......#.......#..#
...#.#.....#.....#......#......
.......#....#..#.#..........#..
......#......#.##...#..........
.....#.......###...#...#.#.....
#..#.#.........#.....#.##....#.
..#.#.........#..#..#..#.....#.
.#..##..#..#....#......#.##..#.
...##......###.....#.##.##.....
.#.....#...#..#...#............
##..##..#.##....#..#...........
...#..##..#..#.............#.##
...............##............#.
..#.....##........##.#...#....#
.#.#...#.#.#..#.#.....#....#...
.#....#...............#..#.....
....#.##..#....#......#...###..
#................###...#.#.....
...#...#......##..#.#....#.....
.#....#....#.#...##............
....#...##..#..#........#.##...
..##.....#..#..##..............
..#..##..#.#..##....#....#....#
...##.............#............
#....#....#.#........#.....##.#
.....#..#.#.....####...###.....
................#......#.......
.....#.#.#.#.#....#..#........#
.##.#...#.#.......##....#....#.
.....#........#................
..#.....#..#...#..#...........#
.#.....#...##.....##..#.#....##
......#.......#..#......##.#...
#.#..........#.##.#........#...
...#..#.............#..........
#..#..#..........#..##.#.......
.#..#...............####..#....
.......#.....#......#.....#.#..
.#...............#...#.........
.#..#..........#..#.#..##..#..#
......##..#.....#..#......###..
..........#...#..#.......#.....
.#.#.#..#.....#.##.#...#..#....
........#.......#.....#.#......
......#.....##.....#....##.#...
...............#......#.......#
..#.#...#.....#.#...##......#..
#.#.........#.#...#........####
#..........##..#..#........##..
.............#..#.......##.#..#
..#........#.#....#........#.#.
.#......####..#..#.............
............###.......#.#..#...
#.##......##...#...#.........#.
....##.#.#.#......#....#..#...#
.#..#.#....#...#.........#.....
#...#.....##............#...#..
#.#...#..#.................#...
............#.#..#.....#.#.#..#
...................#....#.##...
.....#...#.#....#....#.#......#
.......##.#.#......##..........
.#..#...##.#...#..#......#.....
......#.#..#..###..##..##......
.#.#.#.#.....#...###.....#..#..
.#....#.....#.......#.......#..
..........##.........####......
.#.#.............#..#.#...#....
........#........##...#.#....#.
........#......................
..#.#....#...............#...##
.......#.#...#..#.....##......#
.#...#....#..........##........
.#.........#.#............##...
.....#......##...#.......#..#..
#.#..#.............#...#...#...
......#.......#............#...
...........##....#......##.....
.#.#..#.....................#..
##..##.....###..##.#...........
...##......##....#...##.....#..
#...#.##.............#.........
......#..#.........###.#......#
#.#.....#.....................#
....#####.....##........#.#..#.
...........##..##.###..........
..........##.....#........#...#
.......#..#......#.....##..##.#
.....##.#........#.........#...
......##......................#
.#.......#.#.#............#..#.
.....##.#.......#.#........#...

38
2020/d04/ex1/ex1.py Executable file
View file

@ -0,0 +1,38 @@
#!/usr/bin/env python
import sys
from typing import List
def validate(passport: List[str]) -> int:
fields = [
"byr",
"iyr",
"eyr",
"hgt",
"hcl",
"ecl",
"pid",
]
for field in fields:
if field not in passport:
return False
return True
def solve(passport_fields: List[List[str]]) -> int:
return sum(validate(passport) for passport in passport_fields)
def main() -> None:
passports: List[List[str]] = [[]]
for line in sys.stdin:
if line == "\n" or line == "":
passports.append([])
continue
passports[-1] += [s.split(":")[0] for s in line.split(" ")]
print(solve(passports))
if __name__ == "__main__":
main()

1069
2020/d04/ex1/input Normal file

File diff suppressed because it is too large Load diff

109
2020/d04/ex2/ex2.py Executable file
View file

@ -0,0 +1,109 @@
#!/usr/bin/env python
import re
import sys
from typing import List, Tuple
Field = Tuple[str, ...]
def validate_byr(field: str) -> bool:
pattern = "^[0-9]{4}$"
if not re.fullmatch(pattern, field):
return False
val = int(field)
return 1920 <= val <= 2002
def validate_iyr(field: str) -> bool:
pattern = "^[0-9]{4}$"
if not re.fullmatch(pattern, field):
return False
val = int(field)
return 2010 <= val <= 2020
def validate_eyr(field: str) -> bool:
pattern = "^[0-9]{4}$"
if not re.fullmatch(pattern, field):
return False
val = int(field)
return 2020 <= val <= 2030
def validate_hgt(field: str) -> bool:
pattern = "^[0-9]+(cm|in)$"
if not re.fullmatch(pattern, field):
return False
val = int(field[:-2])
if "cm" in field:
return 150 <= val <= 193
return 59 <= val <= 76
def validate_hcl(field: str) -> bool:
pattern = "^#[a-f0-9]{6}$"
if not re.fullmatch(pattern, field):
return False
return True
def validate_ecl(field: str) -> bool:
return field in {
"amb",
"blu",
"brn",
"gry",
"grn",
"hzl",
"oth",
}
def validate_pid(field: str) -> bool:
pattern = "^[0-9]{9}$"
if not re.fullmatch(pattern, field):
return False
return True
def validate(passport: List[Field]) -> int:
fields = {
"byr": validate_byr,
"iyr": validate_iyr,
"eyr": validate_eyr,
"hgt": validate_hgt,
"hcl": validate_hcl,
"ecl": validate_ecl,
"pid": validate_pid,
}
tot = 0
for field in passport:
if len(field) != 2:
continue
if field[0] not in fields:
if field[0] == "cid":
continue
return False
if not fields[field[0]](field[1].strip()):
return False
tot += 1
return tot == len(fields)
def solve(passport_fields: List[List[Field]]) -> int:
return sum(validate(passport) for passport in passport_fields)
def main() -> None:
passports: List[List[Field]] = [[]]
for line in sys.stdin:
if line == "\n" or line == "":
passports.append([])
continue
passports[-1] += [tuple(s.split(":")) for s in line.split(" ") if s]
print(solve(passports))
if __name__ == "__main__":
main()

1069
2020/d04/ex2/input Normal file

File diff suppressed because it is too large Load diff

35
2020/d05/ex1/ex1.py Executable file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env python
import sys
from typing import List
def seat_id(boarding_pass: str) -> int:
min_x = 0
max_x = 128
min_y = 0
max_y = 8
for char in boarding_pass:
if char == "F":
max_x = (min_x + max_x) // 2
elif char == "B":
min_x = (min_x + max_x) // 2
elif char == "L":
max_y = (min_y + max_y) // 2
elif char == "R":
min_y = (min_y + max_y) // 2
return min_x * 8 + min_y
def solve(passes: List[str]) -> int:
return max(seat_id(p) for p in passes)
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

781
2020/d05/ex1/input Normal file
View file

@ -0,0 +1,781 @@
FBFFBFFRLL
BFFFFBBRLR
FFFBBBBRLR
FBFFFBFLRL
FFBFBFFRRL
FFBBBBFRRR
FBFFBFBLRR
FFBBFBFRRL
FFFFBBFRRL
BFBBBBBLLL
FFBFBFBLLL
FFBFFFBLLL
FBBBFBFRLL
BBFFFBFRRR
FFFBFBBLLR
FBFBFBFRRR
BBFFBFBRLL
FBFBBBBLRL
FBFFFFFLLL
BFFFFFFRLL
BFFFBFBLRL
BFBBBFBRRL
BFFFBFFRRL
FBFFFFFRRR
FFBBBBBLLR
BFBBFFBLRL
FBBFBBBRLR
BFBFBFFRLL
BFBFBFBRLL
BFFBFBFLLL
FFBBFFBLRL
FBBFFBFLRR
FBBBFBBRRR
BFBFFBFRLR
BFBBBFBLLL
FFBFBBBLRR
BFBFFBFLLL
FBFBFBBLLL
BFBBBFBLRL
FBFBFBFLRL
FFBFFBFRRL
FBBFFBFLLL
BFBBBBBLRL
FBBBBBFRLR
BFFFBBFRLL
FBBBBFFLLR
FBBBBBFRLL
BFBBBFFRLR
BFBBBFBRLL
BFFFBFFLLL
FFFBFBFLRL
BFFBBFFLRL
BBFFFBFRLL
BFBBFFBRLR
BFBFBFBRRL
BBFFFBFRRL
FBBFBBBLRR
FFBFBBBLLL
BFFFBFBRLR
FFBBFBBLLL
FBFBBFBLLL
BFBBFBFLLR
FFBFBBBRRL
FFBFFFFLRL
FFFBBFFLRR
FBBBBBFRRR
FFFFBBBRLL
BFBFBBBRRR
BBFFBFBRRL
FBFBBFFRLR
FBBFFBFRRR
BBFFBFBRRR
FBFBBFBLRR
FBBFFBBLRR
FBBBBFFRLL
BFBFFFBRLR
FBFBBFBRRL
FFBFBBFRRR
FBFBFFFRLL
BFBBFFBLLR
FBFFFFBRLR
BFBBBFFRLL
FFBBFFBRLR
FFFBBFBRLL
FBBBBBBLRR
FBFFBBBLRR
BFFFFBFLRL
BBFFFFFLRR
BFFBFFBLLR
FFBBBFFRLL
BFBFBFBRLR
FBBFBFBLRR
FBFBBBFRLR
FBFFBBBRRR
FBBFFBFRLL
FBBBFFFRLR
BFBBBBFLLR
BFFFBFFLLR
FFBFFFBRRR
FBFFFBFLLR
FFFFBBBLLR
BFBFFFBRLL
BFFBBFBLRL
BFFBFBFLLR
FFBFFBFRLR
BFBFFFBRRL
FFBBFBFLLL
BFBBBBBRLR
BFBFBFBLRR
FBFFBFBLLR
FBFBFBBRRL
BFBFBBBLLL
FFBBFBBLRL
FBFFFBFRRL
BFBBFFFLRR
BFBFBBFRRR
FBFFFFBLRL
BBFFBBFRRR
FFBFFBBRLR
FBBFBFBLRL
BFBFFFBRRR
FFFBBBFLRL
BFFBFFBRLL
FBFBFFBLRR
FFBFBBFLLL
FFBBBFFLRL
FFBBFFFRLR
BBFFBFBLRL
FFFFBBFRLR
FFFBFFBLRR
BFFBBBFLLR
BFFFBBBRRL
FBBFBFBRLL
BFFBFFFRRR
BBFFFFFLRL
BBFFFBBRLL
BFFFBBBRRR
BFFFBBBLRL
BBFFBFFRRR
BFFBFFBLRL
FBBBBFBRLR
FFFBFBFRRL
BFFBBBBRRL
FBBBBBFLRR
FBFBBBBLLR
FBBBBFBLRR
FFFBFFBRLL
FFBBBBFLLR
FFBBBBBRRL
FBBFFFFLLL
FBFFBBBRLL
FBFBFFBLLR
FBBBBBFRRL
BFFFBFBLLL
FFFBFFFLRL
FFFFBBFRLL
BFBBFFFRLR
BFFFBBBRLR
FFBBBFBLLR
BFFFBFBRRR
BFFBFBBLRL
FFBFBFBLRR
FBBBBFBRRR
FFBFBFFLLR
BBFFFFFLLR
FBBBFBFRRR
BBFFFFBRRL
FBFBFBBLRL
BFBBBFFLLR
BBFFBBFLRL
BFBFFBBRLR
FBFBBBFRRL
FBBBFFBRLL
BBFFFFBLLR
FFBBFBBLRR
FBBBBBBRLR
FFFFBBBRRL
FBFBBBBRLR
BBFFBFFRRL
FBBBFFBLRL
FFBBBFBLRR
BFBFBBBRLL
FBFFFBBLRL
FBFBBBBRLL
BBFFFBBLLL
BFBBFFBLLL
BFFBBBBRRR
FBFBFFBLLL
FBFBFBFRRL
FBBFFFBLLL
BBFFFBFRLR
FBBBBFFLRR
FBFFFBBRLL
FFBBFBFRRR
FBFFFFFLRR
BFBFFBBLRR
FFBFBFFRRR
BFBFFBBRLL
FBBFFFFRRL
BFFBBFBRLL
BFFFFFBLLR
FBFBBFBLLR
BFFBBFBRLR
BFFBFBFRRR
FFBFBBFRLL
FFFBBBBLRR
BFFFBFBLLR
FBBBBFBLRL
FBFBBFFLRL
FFFBFFFRLL
BFFFFBBRRL
FBBFFFBRRR
FBBFBFFLLR
BFBBBBBRRR
BFFBFBFRLL
FFBFBBFRRL
BFBFBFBLLR
FFBFBBFLLR
FFBFFFFLRR
FBBBFBBRRL
BFFBFBFRLR
BFFBFFBRRL
BFBBBFBRLR
BBFFFFBLRL
FBBBFFBRRL
FBFFFBBRRL
FBBBBBBLLL
FFFBFFBLLL
BFBBFBFRLL
FBFBFFBRLR
FFFFBBBRRR
BBFFFBBRLR
BFBBBBFRLR
FBFFBBFLRR
BFFFBFFRLR
FFFBBBBLLR
FBFFFFBLRR
FBFBFBBRLL
FBFFBBBRLR
BFFFFFFLRR
FBFFFFFRLL
FFBFBFFRLL
FFFBBFFRLR
FBBFBFFRRL
FBBBBBBRRR
BFBFBBBLRL
BBFFFFBRRR
FFBFFBBLRL
FBBBBBBLLR
FFBBFFFLRL
FBBBFBBLRR
FFBBBBBRLR
BFBFFFFLLR
BFFBBBBRLL
BFBFBFFLRL
FBBFFFBLRL
BFBFBBBRRL
BFBFBFBLRL
BFBBFBFLRR
BFFFFBFRLR
BFFFBFBRLL
FBFBFBFLLL
FBFFBFFLRL
BFFFFFFRRL
FBBFBFFRLR
FFBBBFFLLR
FBBBBFFLRL
FBBBFBBRLR
BFBBBFFLRL
FBFFBBBLRL
BFFFFBFRRL
BFFFBFFLRR
FFBFBBFLRL
BFBFFFBLRL
BFFFFFBLLL
FBFFBFBLLL
FBFBBBBRRL
FBBFFBBRLR
BFFFBBFRRL
BFBBFBBRLR
FFFBFBBLRR
FFFBFBFRLR
FBFBFBFRLR
BFBFBBBRLR
BFFFFBBLLL
BFFBBFBRRR
BFFBBBFLLL
FFBBBFFRRL
BFBBBFBLLR
FBBFFBBLLR
FBBFBBFLRL
BFFFFFBRRR
FBBBFBBRLL
FBFBFFBRRR
BFFBBBFRRR
FBBBBBBLRL
FFBBBFFLRR
BFFBBBFRLL
BBFFBBFRLL
FBBFBBFRLR
BFBFBFFRRR
BFBFBBFLRL
BFFFFBFRLL
FFBBFBFLLR
BFFBFBBLRR
FBFFBBBRRL
FBBFBBFRLL
FBFFFBBLLR
FFFBBBBRRR
FFFFBBBLRL
FFBBFFFRRL
BFFBBFFRRL
BFFFBBFLRL
BFFFFBBLRR
BBFFBBBLRR
BFBFFFFLRR
FBFBBBBLLL
BBFFFBBLRR
FFFBFBFLRR
FBBFFFFLRL
FFBBBBFRLL
FBFFBFBLRL
BFBBFBBLLL
FBBFBBFLLL
FFBFFBBRLL
BFBFFFFRLR
FBFFBBFRRR
FFFBBFFRRR
FFFBFFBRLR
FBBBBBFLLL
FBBBFFFLRL
FFBBFFFLRR
FFFBBBBRRL
BFBFBBFRLL
BFBFFBBRRL
FBBFBBFRRL
BFBFBBFLLR
BBFFBBBRRR
BFFFBBFRLR
FFFBBBFRLR
BFFBFFFRLL
BFBFFFFRRL
FFBBFFFLLL
FBFBBBBLRR
FBFBFFFLRR
BBFFBFFLRR
FBBBFBBLRL
BFBFBFBLLL
FBFBFFFLLR
BFFBBFBLRR
FBBFFFBRRL
BFFBBFFRRR
FBBFBBBRRL
BFFFFBBLLR
FFBBBBFLLL
BFFBFFBRRR
BFFFFBFRRR
FFFBBBFRRR
FBFBFFFRLR
FBBBFBFLLR
FFBBFFBRLL
FBFBFFFLLL
BFFBFBFRRL
BFBFFBFRRL
BFBBBBFLLL
FBBBFBFRRL
FFBFBFFLLL
BFBBFFFRRL
FFBBFFBLLR
BFFBBBBRLR
FFBBBBBLRR
BFFBFFFRRL
BFFBFBBRLL
FBBBFBFRLR
FBBFFFFLRR
BFFFBBFLLR
FFFBBFBRRL
FFBBFFBLRR
FBBFFFBRLR
BFBBBBBRLL
BBFFFFFRRL
FFBFFBBRRL
BFBFFBFLLR
FBFBBBFLLL
FBFFFFFRRL
BFFFBFBLRR
FBFFFFBLLR
FBBFBFBRRR
FBBBFFFLLR
BBFFBFBLRR
BBFFFBFLLL
FBFFFBFRLR
BFFFBFFLRL
BBFFBFFLRL
BFFFFFFLLR
BBFFBBBLLL
FFBFBBBLLR
FBBFBBBLRL
BFBBFBBLRR
FFBFBFBLLR
FFBFBFBRRL
BFBBFBBRRL
BFFBFFFLLR
FFBBFFBRRL
BBFFBBBRRL
FFFBBFBRLR
BFBBFBFRRR
BFFFFFFRRR
FBBBFFBLLL
BFBFFFFLLL
BBFFBFBLLR
BFBFBBFRLR
FFBFBBBRRR
BFFFBBFLLL
FBFFBBFRLL
FFBBFBFRLL
BFBFBBBLLR
FBBFBFBLLL
BBFFFFBRLL
BBFFBFBLLL
BFFBFFBLRR
BFFBBFBLLL
FFBFFFBLRR
FBBFFBFRRL
FBBBBFBLLL
FFBFFBBLLR
BFFBBBFLRR
FBFBFFBRLL
FFBFFFBRLL
FFBFFBFLLL
FBFBBFBLRL
FBBFBFFRRR
BFBFBFFLLR
FBBFFFBLLR
BFBBBBFRRR
FBBFBBFRRR
BBFFBFFRLR
FBFBBBFRLL
FBBFBBBLLR
BFFFFFFLRL
BFBFFBBRRR
BFFFBFFRLL
BFBBFBFLRL
FFBFFFFRRR
BFFBBFFRLR
FBBBBBFLLR
FBFBFFBLRL
FFFBBFBLLR
FBBFBFBLLR
FFFBFFBRRR
FBFFFFFRLR
FBFBBFBRLR
FBBBFBFLRR
FBFBBBFLRL
BFFBFFFLRL
FFBBBFFRRR
FFBBBBBLLL
FBFFBBFLLR
FFBFBFFLRR
FFFBBBFLRR
BFBFBBFLLL
BBFFBFFLLR
FFBBFBBRLL
FBBFFBBLLL
FBFFBFBRLL
BFBFBFFLRR
FBBBFFBRLR
FFBFFBFRLL
FFFFBBBLLL
FFBFFBBRRR
FBBBBFBRLL
BFFFFBBRRR
FFBBFFFRLL
FFBFBFBRLL
BBFFFFBLLL
FFBBBFBRRL
BFFFFBBLRL
FBBBFBBLLR
FBBBFBBLLL
FFBFBFBLRL
FBBBBFFRRR
FBBFFFFRLR
FFBFFFBRLR
BFBFBFBRRR
FFFBFBBRLL
FBBBFFBRRR
FBBFBFFRLL
BFFBFBFLRR
BFBBBFFRRL
BFFBBFBLLR
FFBBBFBRLL
FBFBFBBLRR
BFBBFFFLRL
BFBFBBFLRR
BFBBBFFRRR
FBBBFFFRRL
FBFBFBFLLR
FBBFFFFLLR
FFBFBBFRLR
FFFBFBBLRL
BBFFFBBLLR
BFFBBBFRLR
FFFFBBBRLR
BBFFBBFRLR
FBFFFFBRLL
FBFBFFFRRR
FBFFFBBLLL
BFBBBBFRLL
FBFBFFBRRL
FFFBFFFRLR
BFBBFBFRRL
FBFFBFFLRR
FBFFFBBLRR
FFBFBBBRLR
FBBFBFFLRR
FBFFFBBRRR
FFBFBBBRLL
FFBBBBBRRR
BFFBBFFLLL
BFBBBBBRRL
BBFFBBBRLL
FBFFFFFLRL
BFFBBFFLRR
FBFFBBFLRL
BFBFFBFRRR
FBFBBFBRLL
BFFFBFBRRL
FBBFFBFLLR
BFFFFFFLLL
FBFBFBFRLL
FBBBBFFRRL
BFBFFBBLLR
FBBFBFBRRL
FFFBFFFLLR
FFBBBBBLRL
FFBFFBBLRR
FFFBFBFRRR
BFBBFBBRLL
BFBBBFBLRR
FFBBBBFLRR
FBBBFFBLLR
BBFFBBBLLR
FBFBBFFRRL
FBBBBBFLRL
FFFBBFFRRL
BFFBBBBLRR
FFFFBBBLRR
FFFFBBFLRR
FBFFFBFLLL
FBFBFBBLLR
BFFBBBBLLL
FFBFFFFRLR
BFBBFFBLRR
FFBBFBFLRL
BFBFBFFLLL
BFFBFBBLLR
BFBBFBBLRL
FFBBBBFLRL
FBBBFFFLLL
FFFBFFBRRL
BFFFFBBRLL
BFFFBBBRLL
BFFBFFFLRR
FFBFBFBRRR
BBFFBBFLLR
FFBBFBBLLR
FFBFFBFRRR
FFBBBFFRLR
BFFBBBBLLR
FFFBFFFLRR
FBFFFFFLLR
FBFFBBBLLL
BBFFBBFLLL
FFBBFBFLRR
BFFBFBFLRL
FBFBBBFRRR
BFBBFBBLLR
FBFFFFBRRL
FFFBBFBLRR
BBFFFFBLRR
BFBBBBFRRL
FFBBBFBLLL
BFBBFBFRLR
BFBBFFBRRL
BFBFBFFRRL
FBBFFBBLRL
FFFBFFBLRL
BFFBBFFRLL
FBBBFFFRLL
FBBFBBFLLR
FFBFFFFLLR
FBBBFBFLRL
BFFFBBBLLR
FBFBBBBRRR
FBBFBFBRLR
FFFBFBFLLR
FFFFBBFRRR
FFFBBFFLRL
BFBFFBFRLL
FFFBFFBLLR
FBBFFFBRLL
FFBBBFBRRR
FFBBFBBRLR
BBFFFFFRRR
FFBFFFFRLL
FBBFFBBRRL
BBFFFBFLRR
FBBFFFFRRR
FFBFFFBRRL
BFBBFBFLLL
BFFFFBFLRR
BBFFFFFLLL
FFBBFBBRRL
FFBFBFFLRL
FBFFBBFRRL
BBFFBFBRLR
BBFFBBFLRR
FBFFBFBRRR
FBBFBBFLRR
FBFFFBFRLL
BFBFFFFLRL
FFFBBFBRRR
BFBBBBBLLR
FBBFFBBRRR
FFBBBFFLLL
FBBBBFBLLR
BBFFFFFRLL
FFBBBBFRLR
FBFBFBBRRR
FBFFBFFLLL
FBFFBBBLLR
FBBBBFBRRL
BFBFBFFRLR
FBBFBBBRLL
BFBBFFFRLL
FBBBFBFLLL
FFBFFFFRRL
FBFBBFFRRR
FBFFFFBLLL
FBBBBBBRLL
BFFBFBBRRR
BBFFBBFRRL
FBBFBFFLRL
FBFFFFBRRR
FBBFFFFRLL
FFFBFFFRRR
FBFFBBFLLL
BFFFFBFLLL
BFFFFBFLLR
FFBFFBFLLR
FFBFFBFLRR
BFFBBBBLRL
FFBBFFBLLL
FBBFBBBLLL
FBFBBBFLLR
BFFBBBFLRL
BFBBFFBRLL
FBFFBFFRRR
FFBFFFBLRL
FFFBBBFRRL
FFBFBBFLRR
FFFBBBBLRL
FFFBBFFLLL
FFFBFBBRRR
FBBFBFFLLL
BFFFBBBLLL
BFFBFFFRLR
FFFBBBBLLL
BFFFFFBRRL
FFBBFFFLLR
BFBBFFFRRR
BFBFFBFLRR
FFFBBBFLLR
FBFBBBFLRR
BBFFBBBRLR
FBFBBFFLRR
FFBBBFBLRL
FFFBBBFRLL
BFFBFFBRLR
BBFFFBBRRR
BFBBBBFLRL
BFBBBFBRRR
FBBBBFFLLL
FFFBFBBLLL
BBFFFFFRLR
BBFFBFFLLL
FFBFBBBLRL
FFBBFBFRLR
BFBBBBBLRR
FFBFFFBLLR
FFBFFBFLRL
BFFBFBBRLR
FBFBFFFRRL
FBBBFFFLRR
FFFBBFFLLR
FBBBBFFRLR
FFBBFBBRRR
BFBBFBBRRR
BFBFBBFRRL
BFFBBBFRRL
FFFBFFFLLL
FBBFFBFLRL
FFFBFBBRLR
BFBBFFFLLR
BFBBFFBRRR
FBFFBFBRRL
FFBBBBBRLL
BFFBFFBLLL
BFFFBBFRRR
FBFFFBFRRR
FFBFBFBRLR
FBFBBFFLLR
FBBFBBBRRR
BFBFFFFRRR
FFBFFFFLLL
FBFBBFFRLL
BFBFFBFLRL
BFBBFFFLLL
FBFBBFBRRR
BFBFFFBLLR
BFBFFFBLLL
BBFFFBFLLR
BBFFBFFRLL
FFBBBBFRRL
BBFFFBFLRL
BBFFBBBLRL
BFBFFFBLRR
FFFBFBFRLL
BFBFFBBLLL
BBFFFBBRRL
BFBBBFFLLL
BFFBBFFLLR
FFBFFBBLLL
BFFBBFBRRL
BFFFFFBLRL
BBFFFFBRLR
FBFBBFFLLL
FFBBBFBRLR
FFFBBFBLLL
FBFFFBBRLR
FFBFBFFRLR
BFFFFFBLRR
FFFBBBBRLL
FFBBFFFRRR
BFFFFFBRLR
FBBBFFBLRR
FBFBFBBRLR
FBBFFFBLRR
BFBFFBBLRL
FBFFBFBRLR
FBFBFFFLRL
BFFFFFBRLL
BFBBBBFLRR
BFFBFFFLLL
FBFFBFFRRL
FFFBBFFRLL
BFFFBFFRRR
FBFFBFFLLR
FFFBBBFLLL
FBFFFBFLRR
BFFBFBBLLL
BFFFBBBLRR
FBBBBBBRRL
FBFFBFFRLR
FBBFFBBRLL
FBBBFFFRRR
BFFBFBBRRL
FFBBFFBRRR
BFBBBFFLRR
FFFBFBBRRL
BFBFBBBLRR
FFFBBFBLRL
FBFFBBFRLR
BFFFBBFLRR
BBFFFBBLRL
FBBFFBFRLR
FFFBFBFLLL
FFFBFFFRRL
BBFBFFFLLL
FBFBFBFLRR
BFBFFFFRLL

41
2020/d05/ex2/ex2.py Executable file
View file

@ -0,0 +1,41 @@
#!/usr/bin/env python
import sys
from typing import List
def seat_id(boarding_pass: str) -> int:
min_x = 0
max_x = 128
min_y = 0
max_y = 8
for char in boarding_pass:
if char == "F":
max_x = (min_x + max_x) // 2
elif char == "B":
min_x = (min_x + max_x) // 2
elif char == "L":
max_y = (min_y + max_y) // 2
elif char == "R":
min_y = (min_y + max_y) // 2
return min_x * 8 + min_y
def solve(passes: List[str]) -> int:
ids = sorted(seat_id(p) for p in passes)
for prev, cur in zip(ids, ids[1:]):
if prev + 1 != cur:
return prev + 1
assert False # Sanity check
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

781
2020/d05/ex2/input Normal file
View file

@ -0,0 +1,781 @@
FBFFBFFRLL
BFFFFBBRLR
FFFBBBBRLR
FBFFFBFLRL
FFBFBFFRRL
FFBBBBFRRR
FBFFBFBLRR
FFBBFBFRRL
FFFFBBFRRL
BFBBBBBLLL
FFBFBFBLLL
FFBFFFBLLL
FBBBFBFRLL
BBFFFBFRRR
FFFBFBBLLR
FBFBFBFRRR
BBFFBFBRLL
FBFBBBBLRL
FBFFFFFLLL
BFFFFFFRLL
BFFFBFBLRL
BFBBBFBRRL
BFFFBFFRRL
FBFFFFFRRR
FFBBBBBLLR
BFBBFFBLRL
FBBFBBBRLR
BFBFBFFRLL
BFBFBFBRLL
BFFBFBFLLL
FFBBFFBLRL
FBBFFBFLRR
FBBBFBBRRR
BFBFFBFRLR
BFBBBFBLLL
FFBFBBBLRR
BFBFFBFLLL
FBFBFBBLLL
BFBBBFBLRL
FBFBFBFLRL
FFBFFBFRRL
FBBFFBFLLL
BFBBBBBLRL
FBBBBBFRLR
BFFFBBFRLL
FBBBBFFLLR
FBBBBBFRLL
BFBBBFFRLR
BFBBBFBRLL
BFFFBFFLLL
FFFBFBFLRL
BFFBBFFLRL
BBFFFBFRLL
BFBBFFBRLR
BFBFBFBRRL
BBFFFBFRRL
FBBFBBBLRR
FFBFBBBLLL
BFFFBFBRLR
FFBBFBBLLL
FBFBBFBLLL
BFBBFBFLLR
FFBFBBBRRL
FFBFFFFLRL
FFFBBFFLRR
FBBBBBFRRR
FFFFBBBRLL
BFBFBBBRRR
BBFFBFBRRL
FBFBBFFRLR
FBBFFBFRRR
BBFFBFBRRR
FBFBBFBLRR
FBBFFBBLRR
FBBBBFFRLL
BFBFFFBRLR
FBFBBFBRRL
FFBFBBFRRR
FBFBFFFRLL
BFBBFFBLLR
FBFFFFBRLR
BFBBBFFRLL
FFBBFFBRLR
FFFBBFBRLL
FBBBBBBLRR
FBFFBBBLRR
BFFFFBFLRL
BBFFFFFLRR
BFFBFFBLLR
FFBBBFFRLL
BFBFBFBRLR
FBBFBFBLRR
FBFBBBFRLR
FBFFBBBRRR
FBBFFBFRLL
FBBBFFFRLR
BFBBBBFLLR
BFFFBFFLLR
FFBFFFBRRR
FBFFFBFLLR
FFFFBBBLLR
BFBFFFBRLL
BFFBBFBLRL
BFFBFBFLLR
FFBFFBFRLR
BFBFFFBRRL
FFBBFBFLLL
BFBBBBBRLR
BFBFBFBLRR
FBFFBFBLLR
FBFBFBBRRL
BFBFBBBLLL
FFBBFBBLRL
FBFFFBFRRL
BFBBFFFLRR
BFBFBBFRRR
FBFFFFBLRL
BBFFBBFRRR
FFBFFBBRLR
FBBFBFBLRL
BFBFFFBRRR
FFFBBBFLRL
BFFBFFBRLL
FBFBFFBLRR
FFBFBBFLLL
FFBBBFFLRL
FFBBFFFRLR
BBFFBFBLRL
FFFFBBFRLR
FFFBFFBLRR
BFFBBBFLLR
BFFFBBBRRL
FBBFBFBRLL
BFFBFFFRRR
BBFFFFFLRL
BBFFFBBRLL
BFFFBBBRRR
BFFFBBBLRL
BBFFBFFRRR
BFFBFFBLRL
FBBBBFBRLR
FFFBFBFRRL
BFFBBBBRRL
FBBBBBFLRR
FBFBBBBLLR
FBBBBFBLRR
FFFBFFBRLL
FFBBBBFLLR
FFBBBBBRRL
FBBFFFFLLL
FBFFBBBRLL
FBFBFFBLLR
FBBBBBFRRL
BFFFBFBLLL
FFFBFFFLRL
FFFFBBFRLL
BFBBFFFRLR
BFFFBBBRLR
FFBBBFBLLR
BFFFBFBRRR
BFFBFBBLRL
FFBFBFBLRR
FBBBBFBRRR
FFBFBFFLLR
BBFFFFFLLR
FBBBFBFRRR
BBFFFFBRRL
FBFBFBBLRL
BFBBBFFLLR
BBFFBBFLRL
BFBFFBBRLR
FBFBBBFRRL
FBBBFFBRLL
BBFFFFBLLR
FFBBFBBLRR
FBBBBBBRLR
FFFFBBBRRL
FBFBBBBRLR
BBFFBFFRRL
FBBBFFBLRL
FFBBBFBLRR
BFBFBBBRLL
FBFFFBBLRL
FBFBBBBRLL
BBFFFBBLLL
BFBBFFBLLL
BFFBBBBRRR
FBFBFFBLLL
FBFBFBFRRL
FBBFFFBLLL
BBFFFBFRLR
FBBBBFFLRR
FBFFFBBRLL
FFBBFBFRRR
FBFFFFFLRR
BFBFFBBLRR
FFBFBFFRRR
BFBFFBBRLL
FBBFFFFRRL
BFFBBFBRLL
BFFFFFBLLR
FBFBBFBLLR
BFFBBFBRLR
BFFBFBFRRR
FFBFBBFRLL
FFFBBBBLRR
BFFFBFBLLR
FBBBBFBLRL
FBFBBFFLRL
FFFBFFFRLL
BFFFFBBRRL
FBBFFFBRRR
FBBFBFFLLR
BFBBBBBRRR
BFFBFBFRLL
FFBFBBFRRL
BFBFBFBLLR
FFBFBBFLLR
FFBFFFFLRR
FBBBFBBRRL
BFFBFBFRLR
BFFBFFBRRL
BFBBBFBRLR
BBFFFFBLRL
FBBBFFBRRL
FBFFFBBRRL
FBBBBBBLLL
FFFBFFBLLL
BFBBFBFRLL
FBFBFFBRLR
FFFFBBBRRR
BBFFFBBRLR
BFBBBBFRLR
FBFFBBFLRR
BFFFBFFRLR
FFFBBBBLLR
FBFFFFBLRR
FBFBFBBRLL
FBFFBBBRLR
BFFFFFFLRR
FBFFFFFRLL
FFBFBFFRLL
FFFBBFFRLR
FBBFBFFRRL
FBBBBBBRRR
BFBFBBBLRL
BBFFFFBRRR
FFBFFBBLRL
FBBBBBBLLR
FFBBFFFLRL
FBBBFBBLRR
FFBBBBBRLR
BFBFFFFLLR
BFFBBBBRLL
BFBFBFFLRL
FBBFFFBLRL
BFBFBBBRRL
BFBFBFBLRL
BFBBFBFLRR
BFFFFBFRLR
BFFFBFBRLL
FBFBFBFLLL
FBFFBFFLRL
BFFFFFFRRL
FBBFBFFRLR
FFBBBFFLLR
FBBBBFFLRL
FBBBFBBRLR
BFBBBFFLRL
FBFFBBBLRL
BFFFFBFRRL
BFFFBFFLRR
FFBFBBFLRL
BFBFFFBLRL
BFFFFFBLLL
FBFFBFBLLL
FBFBBBBRRL
FBBFFBBRLR
BFFFBBFRRL
BFBBFBBRLR
FFFBFBBLRR
FFFBFBFRLR
FBFBFBFRLR
BFBFBBBRLR
BFFFFBBLLL
BFFBBFBRRR
BFFBBBFLLL
FFBBBFFRRL
BFBBBFBLLR
FBBFFBBLLR
FBBFBBFLRL
BFFFFFBRRR
FBBBFBBRLL
FBFBFFBRRR
BFFBBBFRRR
FBBBBBBLRL
FFBBBFFLRR
BFFBBBFRLL
BBFFBBFRLL
FBBFBBFRLR
BFBFBFFRRR
BFBFBBFLRL
BFFFFBFRLL
FFBBFBFLLR
BFFBFBBLRR
FBFFBBBRRL
FBBFBBFRLL
FBFFFBBLLR
FFFBBBBRRR
FFFFBBBLRL
FFBBFFFRRL
BFFBBFFRRL
BFFFBBFLRL
BFFFFBBLRR
BBFFBBBLRR
BFBFFFFLRR
FBFBBBBLLL
BBFFFBBLRR
FFFBFBFLRR
FBBFFFFLRL
FFBBBBFRLL
FBFFBFBLRL
BFBBFBBLLL
FBBFBBFLLL
FFBFFBBRLL
BFBFFFFRLR
FBFFBBFRRR
FFFBBFFRRR
FFFBFFBRLR
FBBBBBFLLL
FBBBFFFLRL
FFBBFFFLRR
FFFBBBBRRL
BFBFBBFRLL
BFBFFBBRRL
FBBFBBFRRL
BFBFBBFLLR
BBFFBBBRRR
BFFFBBFRLR
FFFBBBFRLR
BFFBFFFRLL
BFBFFFFRRL
FFBBFFFLLL
FBFBBBBLRR
FBFBFFFLRR
BBFFBFFLRR
FBBBFBBLRL
BFBFBFBLLL
FBFBFFFLLR
BFFBBFBLRR
FBBFFFBRRL
BFFBBFFRRR
FBBFBBBRRL
BFFFFBBLLR
FFBBBBFLLL
BFFBFFBRRR
BFFFFBFRRR
FFFBBBFRRR
FBFBFFFRLR
FBBBFBFLLR
FFBBFFBRLL
FBFBFFFLLL
BFFBFBFRRL
BFBFFBFRRL
BFBBBBFLLL
FBBBFBFRRL
FFBFBFFLLL
BFBBFFFRRL
FFBBFFBLLR
BFFBBBBRLR
FFBBBBBLRR
BFFBFFFRRL
BFFBFBBRLL
FBBBFBFRLR
FBBFFFFLRR
BFFFBBFLLR
FFFBBFBRRL
FFBBFFBLRR
FBBFFFBRLR
BFBBBBBRLL
BBFFFFFRRL
FFBFFBBRRL
BFBFFBFLLR
FBFBBBFLLL
FBFFFFFRRL
BFFFBFBLRR
FBFFFFBLLR
FBBFBFBRRR
FBBBFFFLLR
BBFFBFBLRR
BBFFFBFLLL
FBFFFBFRLR
BFFFBFFLRL
BBFFBFFLRL
BFFFFFFLLR
BBFFBBBLLL
FFBFBBBLLR
FBBFBBBLRL
BFBBFBBLRR
FFBFBFBLLR
FFBFBFBRRL
BFBBFBBRRL
BFFBFFFLLR
FFBBFFBRRL
BBFFBBBRRL
FFFBBFBRLR
BFBBFBFRRR
BFFFFFFRRR
FBBBFFBLLL
BFBFFFFLLL
BBFFBFBLLR
BFBFBBFRLR
FFBFBBBRRR
BFFFBBFLLL
FBFFBBFRLL
FFBBFBFRLL
BFBFBBBLLR
FBBFBFBLLL
BBFFFFBRLL
BBFFBFBLLL
BFFBFFBLRR
BFFBBFBLLL
FFBFFFBLRR
FBBFFBFRRL
FBBBBFBLLL
FFBFFBBLLR
BFFBBBFLRR
FBFBFFBRLL
FFBFFFBRLL
FFBFFBFLLL
FBFBBFBLRL
FBBFBFFRRR
BFBFBFFLLR
FBBFFFBLLR
BFBBBBFRRR
FBBFBBFRRR
BBFFBFFRLR
FBFBBBFRLL
FBBFBBBLLR
BFFFFFFLRL
BFBFFBBRRR
BFFFBFFRLL
BFBBFBFLRL
FFBFFFFRRR
BFFBBFFRLR
FBBBBBFLLR
FBFBFFBLRL
FFFBBFBLLR
FBBFBFBLLR
FFFBFFBRRR
FBFFFFFRLR
FBFBBFBRLR
FBBBFBFLRR
FBFBBBFLRL
BFFBFFFLRL
FFBBBFFRRR
FFBBBBBLLL
FBFFBBFLLR
FFBFBFFLRR
FFFBBBFLRR
BFBFBBFLLL
BBFFBFFLLR
FFBBFBBRLL
FBBFFBBLLL
FBFFBFBRLL
BFBFBFFLRR
FBBBFFBRLR
FFBFFBFRLL
FFFFBBBLLL
FFBFFBBRRR
FBBBBFBRLL
BFFFFBBRRR
FFBBFFFRLL
FFBFBFBRLL
BBFFFFBLLL
FFBBBFBRRL
BFFFFBBLRL
FBBBFBBLLR
FBBBFBBLLL
FFBFBFBLRL
FBBBBFFRRR
FBBFFFFRLR
FFBFFFBRLR
BFBFBFBRRR
FFFBFBBRLL
FBBBFFBRRR
FBBFBFFRLL
BFFBFBFLRR
BFBBBFFRRL
BFFBBFBLLR
FFBBBFBRLL
FBFBFBBLRR
BFBBFFFLRL
BFBFBBFLRR
BFBBBFFRRR
FBBBFFFRRL
FBFBFBFLLR
FBBFFFFLLR
FFBFBBFRLR
FFFBFBBLRL
BBFFFBBLLR
BFFBBBFRLR
FFFFBBBRLR
BBFFBBFRLR
FBFFFFBRLL
FBFBFFFRRR
FBFFFBBLLL
BFBBBBFRLL
FBFBFFBRRL
FFFBFFFRLR
BFBBFBFRRL
FBFFBFFLRR
FBFFFBBLRR
FFBFBBBRLR
FBBFBFFLRR
FBFFFBBRRR
FFBFBBBRLL
FFBBBBBRRR
BFFBBFFLLL
BFBBBBBRRL
BBFFBBBRLL
FBFFFFFLRL
BFFBBFFLRR
FBFFBBFLRL
BFBFFBFRRR
FBFBBFBRLL
BFFFBFBRRL
FBBFFBFLLR
BFFFFFFLLL
FBFBFBFRLL
FBBBBFFRRL
BFBFFBBLLR
FBBFBFBRRL
FFFBFFFLLR
FFBBBBBLRL
FFBFFBBLRR
FFFBFBFRRR
BFBBFBBRLL
BFBBBFBLRR
FFBBBBFLRR
FBBBFFBLLR
BBFFBBBLLR
FBFBBFFRRL
FBBBBBFLRL
FFFBBFFRRL
BFFBBBBLRR
FFFFBBBLRR
FFFFBBFLRR
FBFFFBFLLL
FBFBFBBLLR
BFFBBBBLLL
FFBFFFFRLR
BFBBFFBLRR
FFBBFBFLRL
BFBFBFFLLL
BFFBFBBLLR
BFBBFBBLRL
FFBBBBFLRL
FBBBFFFLLL
FFFBFFBRRL
BFFFFBBRLL
BFFFBBBRLL
BFFBFFFLRR
FFBFBFBRRR
BBFFBBFLLR
FFBBFBBLLR
FFBFFBFRRR
FFBBBFFRLR
BFFBBBBLLR
FFFBFFFLRR
FBFFFFFLLR
FBFFBBBLLL
BBFFBBFLLL
FFBBFBFLRR
BFFBFBFLRL
FBFBBBFRRR
BFBBFBBLLR
FBFFFFBRRL
FFFBBFBLRR
BBFFFFBLRR
BFBBBBFRRL
FFBBBFBLLL
BFBBFBFRLR
BFBBFFBRRL
BFBFBFFRRL
FBBFFBBLRL
FFFBFFBLRL
BFFBBFFRLL
FBBBFFFRLL
FBBFBBFLLR
FFBFFFFLLR
FBBBFBFLRL
BFFFBBBLLR
FBFBBBBRRR
FBBFBFBRLR
FFFBFBFLLR
FFFFBBFRRR
FFFBBFFLRL
BFBFFBFRLL
FFFBFFBLLR
FBBFFFBRLL
FFBBBFBRRR
FFBBFBBRLR
BBFFFFFRRR
FFBFFFFRLL
FBBFFBBRRL
BBFFFBFLRR
FBBFFFFRRR
FFBFFFBRRL
BFBBFBFLLL
BFFFFBFLRR
BBFFFFFLLL
FFBBFBBRRL
FFBFBFFLRL
FBFFBBFRRL
BBFFBFBRLR
BBFFBBFLRR
FBFFBFBRRR
FBBFBBFLRR
FBFFFBFRLL
BFBFFFFLRL
FFFBBFBRRR
BFBBBBBLLR
FBBFFBBRRR
FFBBBFFLLL
FBBBBFBLLR
BBFFFFFRLL
FFBBBBFRLR
FBFBFBBRRR
FBFFBFFLLL
FBFFBBBLLR
FBBBBFBRRL
BFBFBFFRLR
FBBFBBBRLL
BFBBFFFRLL
FBBBFBFLLL
FFBFFFFRRL
FBFBBFFRRR
FBFFFFBLLL
FBBBBBBRLL
BFFBFBBRRR
BBFFBBFRRL
FBBFBFFLRL
FBFFFFBRRR
FBBFFFFRLL
FFFBFFFRRR
FBFFBBFLLL
BFFFFBFLLL
BFFFFBFLLR
FFBFFBFLLR
FFBFFBFLRR
BFFBBBBLRL
FFBBFFBLLL
FBBFBBBLLL
FBFBBBFLLR
BFFBBBFLRL
BFBBFFBRLL
FBFFBFFRRR
FFBFFFBLRL
FFFBBBFRRL
FFBFBBFLRR
FFFBBBBLRL
FFFBBFFLLL
FFFBFBBRRR
FBBFBFFLLL
BFFFBBBLLL
BFFBFFFRLR
FFFBBBBLLL
BFFFFFBRRL
FFBBFFFLLR
BFBBFFFRRR
BFBFFBFLRR
FFFBBBFLLR
FBFBBBFLRR
BBFFBBBRLR
FBFBBFFLRR
FFBBBFBLRL
FFFBBBFRLL
BFFBFFBRLR
BBFFFBBRRR
BFBBBBFLRL
BFBBBFBRRR
FBBBBFFLLL
FFFBFBBLLL
BBFFFFFRLR
BBFFBFFLLL
FFBFBBBLRL
FFBBFBFRLR
BFBBBBBLRR
FFBFFFBLLR
FFBFFBFLRL
BFFBFBBRLR
FBFBFFFRRL
FBBBFFFLRR
FFFBBFFLLR
FBBBBFFRLR
FFBBFBBRRR
BFBBFBBRRR
BFBFBBFRRL
BFFBBBFRRL
FFFBFFFLLL
FBBFFBFLRL
FFFBFBBRLR
BFBBFFFLLR
BFBBFFBRRR
FBFFBFBRRL
FFBBBBBRLL
BFFBFFBLLL
BFFFBBFRRR
FBFFFBFRRR
FFBFBFBRLR
FBFBBFFLLR
FBBFBBBRRR
BFBFFFFRRR
FFBFFFFLLL
FBFBBFFRLL
BFBFFBFLRL
BFBBFFFLLL
FBFBBFBRRR
BFBFFFBLLR
BFBFFFBLLL
BBFFFBFLLR
BBFFBFFRLL
FFBBBBFRRL
BBFFFBFLRL
BBFFBBBLRL
BFBFFFBLRR
FFFBFBFRLL
BFBFFBBLLL
BBFFFBBRRL
BFBBBFFLLL
BFFBBFFLLR
FFBFFBBLLL
BFFBBFBRRL
BFFFFFBLRL
BBFFFFBRLR
FBFBBFFLLL
FFBBBFBRLR
FFFBBFBLLL
FBFFFBBRLR
FFBFBFFRLR
BFFFFFBLRR
FFFBBBBRLL
FFBBFFFRRR
BFFFFFBRLR
FBBBFFBLRR
FBFBFBBRLR
FBBFFFBLRR
BFBFFBBLRL
FBFFBFBRLR
FBFBFFFLRL
BFFFFFBRLL
BFBBBBFLRR
BFFBFFFLLL
FBFFBFFRRL
FFFBBFFRLL
BFFFBFFRRR
FBFFBFFLLR
FFFBBBFLLL
FBFFFBFLRR
BFFBFBBLLL
BFFFBBBLRR
FBBBBBBRRL
FBFFBFFRLR
FBBFFBBRLL
FBBBFFFRRR
BFFBFBBRRL
FFBBFFBRRR
BFBBBFFLRR
FFFBFBBRRL
BFBFBBBLRR
FFFBBFBLRL
FBFFBBFRLR
BFFFBBFLRR
BBFFFBBLRL
FBBFFBFRLR
FFFBFBFLLL
FFFBFFFRRL
BBFBFFFLLL
FBFBFBFLRR
BFBFFFFRLL

25
2020/d06/ex1/ex1.py Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env python
import sys
from collections import defaultdict
from typing import DefaultDict, List, Set
def solve(raw: List[str]) -> int:
answers: DefaultDict[int, Set[str]] = defaultdict(set)
group = 0
for line in raw:
if line == "":
group += 1
continue
answers[group] |= {char for char in line}
return sum(len(answer) for answer in answers.values())
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

2246
2020/d06/ex1/input Normal file

File diff suppressed because it is too large Load diff

31
2020/d06/ex2/ex2.py Executable file
View file

@ -0,0 +1,31 @@
#!/usr/bin/env python
import sys
from collections import defaultdict
from typing import DefaultDict, List, Set
def solve(raw: List[str]) -> int:
answers: DefaultDict[int, Set[str]] = defaultdict(set)
group = 0
first = True
for line in raw:
if line == "":
group += 1
first = True
continue
if not first:
answers[group] &= {char for char in line}
else:
answers[group] = {char for char in line}
first = False
return sum(len(answer) for answer in answers.values())
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

2246
2020/d06/ex2/input Normal file

File diff suppressed because it is too large Load diff

77
2020/d07/ex1/ex1.py Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env python
import re
import sys
from collections import defaultdict
from copy import deepcopy
from dataclasses import dataclass
from typing import Dict, List, Set, Tuple
@dataclass(eq=True, frozen=True) # Hashable
class ColorInfo:
num: int
color: str
Graph = Dict[str, Set[ColorInfo]]
def extract_info(line: str) -> Tuple[str, Set[ColorInfo]]:
color_pattern = re.compile("(.*) contain ")
match = color_pattern.search(line)
assert match is not None
color = match.group(1).replace("bags", "bag")
line = line[match.end() : -1] # Remove period at end of line
if line == "no other bags":
return color, set()
colors: Set[ColorInfo] = set()
pattern = re.compile("([0-9]+) (.*)")
for col in line.split(", "):
match = pattern.search(col)
assert match is not None
colors |= {
ColorInfo(int(match.group(1)), match.group(2).replace("bags", "bag"))
}
return color, colors
def to_graph(raw: List[str]) -> Graph:
return {color: inside for color, inside in map(extract_info, raw)}
def reverse(graph: Graph) -> Graph:
reverse: Graph = defaultdict(set)
for color, contained in graph.items():
for col in contained:
reverse[col.color] |= {ColorInfo(-1, color)}
return reverse
def containing(graph: Graph, col: str) -> Set[ColorInfo]:
res = deepcopy(graph[col])
for contains in graph[col]:
res |= containing(graph, contains.color)
return res
def solve(raw: List[str]) -> int:
graph = to_graph(raw)
reverse_graph = reverse(graph)
return len(containing(reverse_graph, "shiny gold bag"))
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

594
2020/d07/ex1/input Normal file
View file

@ -0,0 +1,594 @@
shiny aqua bags contain 1 dark white bag.
muted blue bags contain 1 vibrant lavender bag, 4 dotted silver bags, 2 dim indigo bags.
drab gray bags contain 5 mirrored white bags, 1 light green bag, 5 shiny lavender bags, 5 faded aqua bags.
muted indigo bags contain 4 muted chartreuse bags, 2 dotted teal bags.
drab white bags contain 2 dull fuchsia bags, 1 vibrant bronze bag.
dim lavender bags contain 4 muted tan bags.
dotted tomato bags contain 1 mirrored lime bag, 2 vibrant white bags.
clear orange bags contain 5 clear violet bags, 2 dull beige bags, 2 dark chartreuse bags.
bright lime bags contain no other bags.
striped brown bags contain 3 bright orange bags.
vibrant green bags contain 3 shiny fuchsia bags.
plaid tomato bags contain 3 faded chartreuse bags, 2 wavy salmon bags, 1 faded white bag, 3 mirrored maroon bags.
drab beige bags contain 2 shiny bronze bags, 4 pale violet bags, 3 bright tomato bags, 4 pale red bags.
posh green bags contain 2 dull lavender bags, 4 clear plum bags, 2 dark gray bags.
dull maroon bags contain 3 dull magenta bags, 1 dull tan bag, 1 faded cyan bag, 5 dull silver bags.
faded crimson bags contain 2 muted purple bags, 4 dotted olive bags, 5 drab silver bags.
wavy bronze bags contain 3 dark orange bags, 2 dark brown bags, 5 bright silver bags.
dark turquoise bags contain 5 dull plum bags.
dull lavender bags contain 4 dotted maroon bags, 3 muted brown bags, 4 drab black bags, 4 dull cyan bags.
dotted plum bags contain 1 shiny bronze bag, 3 clear brown bags, 3 muted indigo bags.
dull white bags contain 3 clear tan bags, 5 shiny gold bags, 2 drab crimson bags.
dull teal bags contain 2 bright tomato bags.
shiny crimson bags contain 3 light green bags, 5 striped brown bags, 3 faded fuchsia bags.
wavy brown bags contain 1 drab crimson bag, 2 wavy indigo bags.
dark tan bags contain 2 faded gray bags, 4 shiny salmon bags.
shiny red bags contain 4 dull chartreuse bags, 5 pale tomato bags.
bright orange bags contain no other bags.
wavy yellow bags contain 5 light indigo bags, 5 dark gray bags, 5 plaid indigo bags, 4 faded red bags.
faded bronze bags contain 4 faded cyan bags, 5 shiny beige bags, 5 muted red bags.
dull bronze bags contain 1 mirrored beige bag, 5 muted violet bags, 1 wavy lime bag.
dark lime bags contain 2 drab maroon bags, 5 bright indigo bags, 4 shiny black bags, 5 dotted turquoise bags.
drab red bags contain 5 bright red bags, 2 vibrant brown bags.
dotted salmon bags contain 3 vibrant turquoise bags, 2 dull beige bags, 3 light turquoise bags.
dull gray bags contain 3 striped green bags, 3 wavy coral bags, 1 dark gray bag, 2 light indigo bags.
faded black bags contain 4 muted fuchsia bags, 4 wavy coral bags, 1 drab tomato bag.
muted magenta bags contain 2 posh chartreuse bags, 4 pale violet bags.
light tan bags contain 2 posh turquoise bags, 3 vibrant white bags, 1 light black bag.
dark blue bags contain 3 plaid indigo bags, 2 posh black bags.
dull indigo bags contain 4 light gray bags, 3 dotted tan bags, 4 dull coral bags.
dim fuchsia bags contain 3 vibrant yellow bags, 3 mirrored cyan bags, 4 mirrored brown bags.
shiny beige bags contain 2 dull silver bags, 3 bright lime bags, 5 dull magenta bags.
light cyan bags contain 3 vibrant violet bags, 2 mirrored tomato bags, 2 vibrant coral bags, 4 mirrored silver bags.
clear turquoise bags contain 4 drab tomato bags, 3 shiny gold bags, 4 drab gold bags.
pale teal bags contain 2 wavy maroon bags, 2 dotted olive bags, 4 shiny white bags, 2 drab turquoise bags.
dark purple bags contain 1 wavy indigo bag, 3 bright black bags, 3 dotted teal bags.
bright white bags contain 5 wavy red bags, 2 mirrored cyan bags, 3 drab green bags.
mirrored aqua bags contain 1 faded violet bag, 5 dotted purple bags.
shiny lime bags contain 4 dark aqua bags.
pale bronze bags contain 1 clear crimson bag.
vibrant white bags contain 5 plaid lavender bags, 1 drab red bag, 4 vibrant brown bags.
plaid tan bags contain 5 dim crimson bags.
posh olive bags contain 3 bright red bags.
plaid brown bags contain 5 vibrant turquoise bags.
mirrored tomato bags contain 2 dotted chartreuse bags, 3 light aqua bags, 3 posh beige bags.
plaid blue bags contain 5 striped green bags, 1 plaid purple bag, 4 muted gold bags.
shiny tan bags contain 5 striped coral bags, 1 dull brown bag.
shiny gold bags contain 1 dull magenta bag, 5 dark white bags, 4 faded turquoise bags.
dull salmon bags contain 2 plaid gold bags, 2 light indigo bags.
striped tomato bags contain 2 striped tan bags, 4 light blue bags, 4 drab tan bags.
drab tomato bags contain 3 dim teal bags, 4 striped yellow bags, 3 bright red bags.
faded olive bags contain 1 drab plum bag, 1 pale aqua bag, 3 light blue bags.
dotted indigo bags contain 2 clear tomato bags.
dark white bags contain 5 light aqua bags, 2 dim teal bags, 2 muted fuchsia bags, 5 light purple bags.
dull orange bags contain 4 pale gold bags, 5 posh brown bags, 2 mirrored brown bags, 3 dark bronze bags.
bright maroon bags contain 1 mirrored yellow bag, 4 light teal bags.
bright silver bags contain 1 vibrant coral bag, 3 dim teal bags, 5 light purple bags.
muted olive bags contain 5 plaid orange bags, 1 muted magenta bag.
dull silver bags contain no other bags.
pale maroon bags contain 2 pale bronze bags.
light gray bags contain 4 vibrant yellow bags, 2 pale red bags.
drab teal bags contain 2 light crimson bags, 3 vibrant brown bags, 3 vibrant tan bags.
bright gold bags contain 1 wavy red bag, 5 wavy coral bags.
plaid chartreuse bags contain 2 dim coral bags, 4 drab silver bags, 5 dim chartreuse bags, 3 light purple bags.
clear blue bags contain 2 pale tomato bags, 4 dull gold bags, 4 dim fuchsia bags, 4 pale coral bags.
vibrant purple bags contain 5 faded orange bags.
plaid aqua bags contain 3 muted cyan bags, 2 wavy gray bags, 4 drab green bags, 4 pale beige bags.
muted lime bags contain 1 muted tan bag.
faded coral bags contain 3 drab turquoise bags, 1 shiny plum bag, 5 mirrored green bags, 5 clear white bags.
vibrant lime bags contain 5 posh coral bags.
faded green bags contain 3 pale orange bags, 5 dull turquoise bags, 1 mirrored crimson bag.
mirrored gray bags contain 5 dim indigo bags.
wavy maroon bags contain 4 mirrored bronze bags, 1 striped olive bag, 2 dull salmon bags, 3 shiny crimson bags.
dark violet bags contain 2 light purple bags.
dark green bags contain 2 dim cyan bags.
pale black bags contain 1 mirrored gold bag.
bright yellow bags contain 2 vibrant crimson bags, 3 plaid lime bags, 2 dotted gold bags.
muted teal bags contain 1 pale violet bag, 4 dull silver bags.
dim beige bags contain 5 wavy red bags.
muted purple bags contain 4 clear cyan bags.
plaid fuchsia bags contain 3 dark coral bags.
plaid bronze bags contain 5 plaid orange bags, 2 drab indigo bags.
faded indigo bags contain 1 dark chartreuse bag, 4 dull green bags, 1 mirrored magenta bag.
posh plum bags contain 3 dark chartreuse bags, 3 dotted turquoise bags, 4 dull maroon bags, 1 posh bronze bag.
pale gold bags contain 4 striped brown bags.
mirrored chartreuse bags contain 4 bright silver bags, 3 mirrored tomato bags, 4 wavy orange bags.
pale orange bags contain 2 posh fuchsia bags, 2 clear salmon bags, 2 bright green bags.
clear brown bags contain 4 light lime bags, 4 bright green bags, 5 pale yellow bags, 2 drab cyan bags.
shiny plum bags contain 5 vibrant gray bags, 3 bright blue bags, 5 dark tomato bags.
wavy white bags contain 4 plaid lime bags, 4 posh maroon bags, 5 drab lime bags, 1 vibrant crimson bag.
faded red bags contain 1 dull coral bag, 5 clear cyan bags, 4 plaid chartreuse bags, 3 plaid orange bags.
plaid red bags contain 5 pale blue bags, 4 light crimson bags, 3 faded fuchsia bags.
bright cyan bags contain 3 dark white bags, 2 light crimson bags, 1 bright aqua bag.
muted lavender bags contain 1 light green bag, 4 striped silver bags, 3 posh crimson bags.
wavy crimson bags contain 1 light purple bag, 4 bright blue bags, 2 dull coral bags, 1 wavy beige bag.
faded aqua bags contain 5 muted brown bags.
mirrored fuchsia bags contain 1 faded beige bag, 3 muted gold bags.
dark chartreuse bags contain 5 bright lime bags.
plaid green bags contain 4 mirrored tan bags, 1 mirrored tomato bag, 5 pale indigo bags, 1 mirrored plum bag.
shiny black bags contain 3 plaid chartreuse bags.
dotted purple bags contain 2 dim teal bags.
faded tan bags contain 2 bright fuchsia bags, 5 shiny fuchsia bags, 1 muted fuchsia bag, 1 mirrored brown bag.
drab brown bags contain 1 striped orange bag, 4 dotted tomato bags.
dull olive bags contain 1 striped black bag, 1 vibrant magenta bag.
mirrored plum bags contain 1 clear gold bag, 5 pale green bags.
dim tomato bags contain 4 drab gold bags, 2 shiny aqua bags.
light lavender bags contain 1 muted violet bag.
dim gray bags contain 3 light purple bags, 1 posh crimson bag, 1 faded brown bag.
muted aqua bags contain 4 dull beige bags, 4 dull red bags.
faded silver bags contain 1 mirrored cyan bag.
shiny green bags contain 5 dull maroon bags.
muted chartreuse bags contain 2 clear tan bags.
plaid plum bags contain 1 dotted lime bag, 4 clear brown bags, 4 dull red bags.
dotted silver bags contain 1 posh coral bag.
dim crimson bags contain 4 faded violet bags, 1 striped silver bag.
bright brown bags contain 1 bright coral bag, 3 posh brown bags, 4 drab tan bags.
wavy cyan bags contain 3 clear gold bags, 1 mirrored salmon bag, 3 bright fuchsia bags, 2 light bronze bags.
dull violet bags contain 5 striped white bags, 4 light blue bags, 4 dim black bags.
vibrant olive bags contain 2 vibrant coral bags.
bright coral bags contain 2 vibrant tan bags, 3 shiny indigo bags, 2 plaid indigo bags.
dim turquoise bags contain 1 pale violet bag.
striped crimson bags contain 2 faded gray bags.
clear green bags contain 3 mirrored olive bags, 3 shiny tomato bags.
faded violet bags contain 2 wavy coral bags, 2 dull tan bags, 1 dull silver bag, 1 bright orange bag.
pale chartreuse bags contain 4 shiny crimson bags, 2 clear bronze bags.
light plum bags contain 3 drab bronze bags, 1 bright bronze bag, 1 posh yellow bag.
pale tomato bags contain 1 dim teal bag, 5 drab cyan bags, 3 muted coral bags, 2 dim chartreuse bags.
plaid coral bags contain 1 striped tan bag, 3 vibrant cyan bags, 3 light beige bags, 2 dotted green bags.
bright gray bags contain 4 mirrored teal bags, 4 striped brown bags, 1 dim green bag, 4 clear cyan bags.
drab fuchsia bags contain 2 mirrored salmon bags, 4 posh orange bags, 3 faded crimson bags, 3 pale plum bags.
light tomato bags contain 2 dotted gold bags, 1 dotted bronze bag.
muted violet bags contain 2 light chartreuse bags.
drab tan bags contain 2 light green bags, 5 bright red bags, 4 shiny beige bags.
drab chartreuse bags contain 2 drab salmon bags, 2 dark brown bags, 4 clear turquoise bags.
drab violet bags contain 4 faded red bags.
posh cyan bags contain 4 bright violet bags.
posh orange bags contain 4 pale plum bags, 5 posh aqua bags.
plaid silver bags contain 1 dotted brown bag, 3 drab gold bags, 4 clear yellow bags.
mirrored silver bags contain 3 shiny beige bags, 1 drab silver bag.
faded gray bags contain no other bags.
wavy tomato bags contain 1 bright brown bag, 3 striped red bags, 2 vibrant maroon bags.
posh violet bags contain 2 dim aqua bags.
bright blue bags contain 5 light lime bags, 2 faded violet bags, 3 light aqua bags, 4 vibrant coral bags.
dark teal bags contain 5 muted fuchsia bags.
striped fuchsia bags contain 1 wavy turquoise bag, 5 wavy green bags, 4 posh gold bags.
posh maroon bags contain 2 dull red bags.
shiny purple bags contain 2 clear tan bags.
wavy lime bags contain 2 dark coral bags, 1 shiny gold bag.
wavy silver bags contain 4 dotted white bags.
shiny silver bags contain 2 plaid gold bags, 2 dim green bags, 5 plaid lime bags, 3 dull red bags.
wavy red bags contain 3 vibrant brown bags, 4 bright indigo bags.
dull chartreuse bags contain 4 dotted lime bags, 2 bright silver bags, 3 dull red bags, 4 wavy maroon bags.
vibrant silver bags contain 1 bright fuchsia bag, 3 drab lavender bags, 2 drab olive bags, 3 dotted teal bags.
striped gray bags contain 5 plaid orange bags, 1 wavy coral bag.
striped green bags contain 4 wavy coral bags, 4 shiny gold bags, 3 dark brown bags, 5 vibrant brown bags.
mirrored violet bags contain 3 dim silver bags, 1 posh tomato bag, 1 light salmon bag.
dull purple bags contain 1 light gray bag, 3 wavy yellow bags, 1 wavy salmon bag.
mirrored beige bags contain 4 dark cyan bags, 5 dull green bags.
posh lime bags contain 3 posh chartreuse bags.
vibrant tan bags contain 2 dull plum bags, 1 striped brown bag, 4 vibrant coral bags.
dotted orange bags contain 1 mirrored olive bag, 5 drab silver bags.
clear indigo bags contain 3 light lime bags, 4 dull coral bags.
pale gray bags contain 1 faded black bag, 3 dim green bags, 4 wavy lavender bags, 2 posh brown bags.
posh gold bags contain 5 dark tan bags, 2 dotted olive bags, 5 dark aqua bags.
striped chartreuse bags contain 2 dull magenta bags, 1 posh tomato bag.
mirrored bronze bags contain 2 faded fuchsia bags.
clear salmon bags contain 4 posh bronze bags, 5 clear plum bags, 5 dull blue bags.
posh purple bags contain 5 dim gray bags, 3 faded brown bags.
faded lime bags contain 5 dim turquoise bags, 3 dark indigo bags, 2 vibrant gray bags, 1 muted silver bag.
wavy beige bags contain 1 dark bronze bag, 4 dull plum bags, 4 mirrored silver bags.
clear yellow bags contain 2 vibrant teal bags.
vibrant plum bags contain 4 muted chartreuse bags, 4 posh silver bags.
striped yellow bags contain 2 dull maroon bags, 5 bright red bags, 2 posh chartreuse bags.
dark coral bags contain 3 dull tan bags.
dull magenta bags contain no other bags.
dark gold bags contain 1 dotted indigo bag, 4 shiny teal bags, 4 dotted silver bags.
dim tan bags contain 1 striped lavender bag, 1 shiny tomato bag.
muted maroon bags contain 2 dull salmon bags, 4 dim chartreuse bags, 3 bright aqua bags, 2 faded indigo bags.
vibrant tomato bags contain 2 dark silver bags, 3 plaid purple bags.
dotted lime bags contain 3 shiny crimson bags, 2 pale yellow bags.
muted fuchsia bags contain 1 dull tan bag.
bright tan bags contain 5 pale gold bags, 5 drab teal bags, 2 light blue bags.
dark crimson bags contain 4 shiny orange bags, 3 faded purple bags, 3 bright white bags.
striped tan bags contain 4 dotted turquoise bags, 4 drab lime bags, 5 dim teal bags.
posh fuchsia bags contain 2 dotted olive bags, 2 mirrored beige bags, 3 shiny bronze bags.
pale silver bags contain 4 vibrant lavender bags, 4 clear beige bags, 4 striped gold bags.
posh aqua bags contain 4 drab lime bags, 4 dull tan bags, 5 vibrant tan bags.
plaid salmon bags contain 5 dim coral bags, 2 wavy bronze bags.
mirrored orange bags contain 4 vibrant gray bags.
dim yellow bags contain 5 pale tan bags, 4 dark black bags.
dotted coral bags contain 4 dotted chartreuse bags, 2 bright red bags, 1 vibrant white bag, 1 vibrant brown bag.
muted crimson bags contain 4 striped orange bags, 5 pale yellow bags, 3 posh blue bags, 1 muted red bag.
striped lavender bags contain 3 striped brown bags.
striped maroon bags contain 2 shiny yellow bags.
vibrant blue bags contain 3 faded cyan bags, 1 shiny lime bag, 3 dark tomato bags.
pale lavender bags contain 4 plaid magenta bags, 4 striped blue bags.
dull tan bags contain 4 shiny indigo bags, 2 light purple bags, 4 faded cyan bags.
dotted beige bags contain 3 drab indigo bags.
light indigo bags contain 1 faded cyan bag, 5 bright aqua bags, 1 shiny indigo bag.
vibrant crimson bags contain 4 dotted fuchsia bags.
wavy blue bags contain 4 wavy teal bags, 1 dull blue bag.
vibrant chartreuse bags contain 4 striped orange bags.
vibrant cyan bags contain 5 wavy coral bags.
faded brown bags contain 5 faded turquoise bags.
faded magenta bags contain 1 dull indigo bag, 4 plaid aqua bags, 4 dim crimson bags.
mirrored coral bags contain 4 drab crimson bags, 2 light salmon bags, 2 clear indigo bags.
faded cyan bags contain no other bags.
dark brown bags contain 5 light purple bags.
wavy violet bags contain 3 dull coral bags, 1 bright aqua bag, 3 shiny lavender bags.
posh tomato bags contain 4 vibrant chartreuse bags, 4 mirrored teal bags.
pale crimson bags contain 1 plaid orange bag, 1 dark violet bag, 3 plaid lavender bags.
dark fuchsia bags contain 4 plaid beige bags, 2 plaid chartreuse bags.
plaid magenta bags contain 3 clear lavender bags, 5 mirrored brown bags, 5 shiny bronze bags.
striped blue bags contain 1 dull bronze bag, 1 dotted fuchsia bag, 1 light lavender bag, 1 clear turquoise bag.
dotted olive bags contain 4 dotted turquoise bags, 5 dotted bronze bags, 3 pale yellow bags, 4 pale red bags.
posh silver bags contain 3 pale violet bags, 1 plaid salmon bag, 1 posh coral bag.
dotted chartreuse bags contain 3 bright blue bags.
light coral bags contain 4 shiny fuchsia bags, 2 pale red bags, 1 muted silver bag, 2 bright cyan bags.
pale brown bags contain 5 light aqua bags.
dotted black bags contain 2 plaid purple bags, 1 mirrored aqua bag, 5 posh beige bags.
posh coral bags contain 3 dark aqua bags, 2 pale yellow bags, 5 plaid blue bags, 4 dim aqua bags.
shiny gray bags contain 1 bright gold bag, 1 muted bronze bag, 5 striped green bags, 5 shiny teal bags.
drab orange bags contain 5 plaid salmon bags, 2 vibrant beige bags.
plaid yellow bags contain 4 clear teal bags, 2 bright red bags.
striped violet bags contain 4 mirrored fuchsia bags, 4 vibrant white bags, 3 dim teal bags.
dim aqua bags contain 1 muted fuchsia bag, 1 dull tan bag.
light orange bags contain 2 bright red bags, 4 dark white bags, 1 dim chartreuse bag, 5 faded fuchsia bags.
faded salmon bags contain 5 wavy gray bags.
shiny yellow bags contain 2 vibrant plum bags, 3 dim teal bags, 1 plaid tan bag, 5 posh plum bags.
vibrant beige bags contain 2 wavy lavender bags, 4 posh chartreuse bags, 3 pale teal bags, 5 wavy lime bags.
light fuchsia bags contain 3 clear brown bags, 3 bright lavender bags.
pale magenta bags contain 4 posh silver bags.
dark maroon bags contain 3 drab turquoise bags.
faded beige bags contain 1 vibrant white bag, 4 drab red bags, 1 drab lavender bag.
bright bronze bags contain 1 pale bronze bag, 3 muted silver bags, 2 striped coral bags, 3 clear gray bags.
light silver bags contain 3 dotted lavender bags, 2 wavy lavender bags.
muted salmon bags contain 2 drab tan bags, 5 wavy tomato bags.
bright black bags contain 5 plaid tan bags.
dim chartreuse bags contain 5 muted gold bags, 5 bright blue bags, 5 faded cyan bags.
shiny white bags contain 4 bright tan bags.
bright red bags contain 3 dull silver bags.
dark aqua bags contain 2 dull red bags.
drab plum bags contain 4 muted brown bags, 5 muted plum bags.
muted yellow bags contain 5 light purple bags, 3 dotted silver bags, 3 faded turquoise bags.
light violet bags contain 1 pale red bag, 4 dim silver bags, 2 mirrored bronze bags.
pale lime bags contain 4 bright lavender bags.
pale tan bags contain 4 striped green bags, 2 dotted chartreuse bags.
dim green bags contain 1 light lime bag, 1 shiny beige bag.
mirrored gold bags contain 4 mirrored white bags.
dim silver bags contain 5 pale coral bags, 3 wavy coral bags.
dull aqua bags contain 3 posh indigo bags, 5 dotted coral bags, 1 dark salmon bag, 3 striped crimson bags.
posh yellow bags contain 1 dark bronze bag, 2 mirrored white bags, 2 light crimson bags.
mirrored magenta bags contain 1 bright violet bag, 2 drab lavender bags, 3 pale violet bags, 2 plaid salmon bags.
shiny chartreuse bags contain 2 dotted purple bags, 5 wavy red bags, 3 plaid beige bags.
light black bags contain 1 dark chartreuse bag, 3 faded tomato bags.
clear plum bags contain 5 vibrant brown bags, 3 dim coral bags, 4 mirrored brown bags, 1 faded black bag.
pale violet bags contain 2 dull tan bags.
bright fuchsia bags contain 4 dull orange bags.
dotted teal bags contain 5 bright red bags, 3 wavy red bags, 1 dull coral bag, 3 clear plum bags.
dotted blue bags contain 2 wavy beige bags, 3 muted purple bags.
muted gray bags contain 3 faded aqua bags, 1 shiny olive bag, 5 clear salmon bags, 1 vibrant violet bag.
dull beige bags contain 1 wavy lavender bag, 4 dark bronze bags, 5 dull tan bags.
drab turquoise bags contain 3 posh gray bags, 5 drab red bags.
vibrant yellow bags contain 2 shiny aqua bags, 4 light chartreuse bags.
posh brown bags contain 3 bright green bags, 5 posh lavender bags.
faded gold bags contain 4 vibrant maroon bags, 4 dotted purple bags.
dotted turquoise bags contain 5 clear plum bags, 3 muted gold bags, 4 dark violet bags.
dotted tan bags contain 5 dim aqua bags, 4 striped violet bags.
posh crimson bags contain 4 striped blue bags, 5 dull magenta bags, 2 bright coral bags.
muted white bags contain 5 dull olive bags.
vibrant teal bags contain 5 dotted turquoise bags, 1 striped tan bag, 1 drab tan bag.
dotted yellow bags contain 3 plaid turquoise bags, 2 posh yellow bags, 4 striped blue bags, 5 posh black bags.
posh magenta bags contain 5 mirrored black bags.
dotted green bags contain 4 dim crimson bags, 1 shiny lavender bag, 4 bright salmon bags, 1 plaid gray bag.
bright green bags contain 3 bright aqua bags, 3 dull maroon bags, 4 dark brown bags.
dark gray bags contain 5 muted purple bags, 2 striped blue bags, 4 faded lavender bags.
bright crimson bags contain 2 striped olive bags, 3 muted blue bags.
muted cyan bags contain 3 shiny tomato bags.
light yellow bags contain 2 striped red bags, 4 shiny crimson bags.
pale aqua bags contain 5 shiny yellow bags, 3 dark lavender bags, 3 posh white bags.
clear red bags contain 1 dotted silver bag, 1 dull teal bag, 1 faded maroon bag, 1 dotted salmon bag.
pale red bags contain 2 faded gray bags.
dotted maroon bags contain 5 posh aqua bags, 3 dull silver bags.
dull blue bags contain 4 light crimson bags, 3 light lime bags, 1 dark orange bag, 5 light indigo bags.
posh turquoise bags contain 1 muted gold bag, 5 striped lavender bags, 3 dull salmon bags, 5 vibrant chartreuse bags.
striped magenta bags contain 1 posh silver bag, 5 dark brown bags.
pale blue bags contain 2 muted gold bags, 4 vibrant brown bags, 1 light lavender bag.
vibrant violet bags contain 5 bright red bags.
faded fuchsia bags contain 2 light lime bags, 4 bright lime bags, 3 pale violet bags.
shiny coral bags contain 1 clear plum bag, 5 muted chartreuse bags, 1 muted violet bag, 5 striped yellow bags.
pale olive bags contain 4 plaid lime bags, 1 posh salmon bag.
wavy tan bags contain 3 faded gray bags.
faded chartreuse bags contain 3 dim coral bags, 1 mirrored bronze bag, 3 posh bronze bags.
mirrored brown bags contain 1 faded violet bag, 4 dull maroon bags, 5 dotted magenta bags.
clear white bags contain 5 muted magenta bags, 4 dull magenta bags, 3 pale plum bags, 4 drab indigo bags.
drab maroon bags contain 2 clear beige bags, 3 wavy beige bags, 5 faded purple bags.
striped silver bags contain 3 drab tomato bags.
faded plum bags contain 1 clear teal bag, 3 bright aqua bags.
plaid violet bags contain 2 drab violet bags, 4 muted turquoise bags, 5 muted indigo bags.
clear black bags contain 5 muted fuchsia bags, 1 muted coral bag, 2 light black bags.
vibrant maroon bags contain 1 dark lavender bag, 1 pale crimson bag, 4 bright indigo bags, 5 mirrored maroon bags.
drab indigo bags contain 2 dim coral bags, 1 drab green bag, 2 shiny lavender bags.
drab olive bags contain 2 dark aqua bags, 4 striped brown bags.
dull crimson bags contain 3 dull cyan bags.
wavy teal bags contain 4 striped orange bags, 2 drab cyan bags.
dark red bags contain 2 dull maroon bags, 4 muted plum bags, 4 dull plum bags.
striped salmon bags contain 3 bright red bags, 1 light aqua bag, 4 wavy gold bags.
mirrored tan bags contain 5 dotted olive bags, 2 dim tomato bags, 2 mirrored tomato bags, 4 clear teal bags.
striped white bags contain 2 pale coral bags, 2 shiny green bags.
shiny tomato bags contain 5 pale coral bags, 5 dull beige bags.
vibrant indigo bags contain 2 dim black bags, 4 dim blue bags, 3 dim white bags.
wavy lavender bags contain 4 faded bronze bags, 4 muted red bags, 3 light lime bags, 4 muted gold bags.
shiny turquoise bags contain 2 dull red bags, 5 faded gray bags, 1 muted turquoise bag.
shiny lavender bags contain 5 bright aqua bags.
posh tan bags contain 1 shiny yellow bag, 3 drab magenta bags.
light green bags contain 4 bright red bags, 1 vibrant coral bag.
drab black bags contain 5 faded tomato bags, 3 dotted chartreuse bags.
clear chartreuse bags contain 3 wavy bronze bags, 4 plaid purple bags, 3 dark orange bags.
dull black bags contain 1 wavy teal bag, 3 light lavender bags, 2 striped indigo bags.
wavy black bags contain 2 clear orange bags, 4 muted purple bags.
pale plum bags contain 1 bright coral bag, 1 drab tan bag, 1 plaid fuchsia bag, 1 dotted fuchsia bag.
dotted violet bags contain 3 bright black bags.
posh red bags contain 3 bright black bags.
plaid lime bags contain 5 posh beige bags, 1 dotted turquoise bag.
wavy aqua bags contain 1 dark yellow bag, 3 drab indigo bags.
dim magenta bags contain 3 dark violet bags.
drab aqua bags contain 5 posh orange bags, 1 dark silver bag, 4 plaid purple bags, 2 wavy teal bags.
dull brown bags contain 4 light lime bags.
striped orange bags contain 5 light crimson bags, 3 muted tan bags, 5 dotted coral bags, 3 plaid blue bags.
muted brown bags contain 1 posh blue bag, 4 dotted magenta bags, 3 dull coral bags.
faded blue bags contain 5 striped black bags, 1 vibrant yellow bag.
plaid indigo bags contain 3 dark brown bags, 5 light purple bags, 4 light aqua bags, 3 light green bags.
plaid turquoise bags contain 5 dotted teal bags.
light turquoise bags contain 2 dull salmon bags, 5 dotted tan bags.
dim purple bags contain 4 muted white bags, 5 drab purple bags.
pale coral bags contain 5 posh gray bags.
clear lime bags contain 3 dim magenta bags, 3 plaid tomato bags, 1 drab magenta bag, 3 shiny purple bags.
dim black bags contain 3 clear gold bags, 4 muted violet bags.
light maroon bags contain 4 muted yellow bags, 1 pale cyan bag, 2 mirrored turquoise bags, 4 dull lavender bags.
clear magenta bags contain 2 shiny magenta bags, 2 muted chartreuse bags.
striped bronze bags contain 5 clear tan bags, 1 drab lavender bag, 2 pale crimson bags.
dark salmon bags contain 1 vibrant plum bag, 5 drab tan bags, 4 drab coral bags, 4 dull tan bags.
vibrant salmon bags contain 2 muted olive bags.
dim gold bags contain 2 dim olive bags, 5 plaid olive bags, 2 posh orange bags.
wavy chartreuse bags contain 4 shiny yellow bags, 4 vibrant blue bags.
vibrant brown bags contain 3 striped brown bags, 4 muted red bags, 2 shiny indigo bags.
plaid maroon bags contain 2 muted teal bags, 2 pale yellow bags, 2 bright beige bags, 5 striped yellow bags.
dim indigo bags contain 4 dull tomato bags, 4 clear cyan bags, 2 shiny salmon bags, 1 bright aqua bag.
muted red bags contain 3 dull tan bags, 4 dull magenta bags, 1 bright aqua bag.
posh beige bags contain 5 shiny black bags, 3 dotted magenta bags, 3 drab blue bags, 2 muted coral bags.
pale fuchsia bags contain 3 dark brown bags, 5 posh gold bags.
dark bronze bags contain 1 dim green bag, 5 posh chartreuse bags.
dim coral bags contain 3 dull coral bags, 3 striped brown bags.
drab crimson bags contain 2 dark bronze bags, 4 shiny indigo bags, 3 dull tan bags.
bright indigo bags contain 3 bright blue bags.
pale yellow bags contain 5 dim aqua bags, 1 vibrant brown bag, 2 vibrant tan bags, 3 wavy lavender bags.
drab salmon bags contain 1 dotted indigo bag, 3 muted chartreuse bags, 5 dark olive bags.
muted orange bags contain 4 faded lime bags, 2 dull coral bags, 5 vibrant magenta bags, 4 dull magenta bags.
striped gold bags contain 2 dull silver bags, 5 bright lavender bags, 5 dim teal bags, 5 dark coral bags.
posh chartreuse bags contain 3 dim teal bags, 5 light aqua bags.
shiny blue bags contain 3 dull tan bags, 5 muted magenta bags.
muted silver bags contain 3 wavy blue bags, 2 dim teal bags, 5 muted bronze bags.
shiny bronze bags contain 1 light green bag, 4 vibrant magenta bags.
wavy coral bags contain no other bags.
shiny orange bags contain 2 muted purple bags.
posh teal bags contain 4 clear plum bags.
striped turquoise bags contain 3 muted indigo bags.
dim bronze bags contain 2 shiny silver bags, 1 light silver bag, 2 dim indigo bags, 4 dim tomato bags.
plaid white bags contain 4 drab turquoise bags.
wavy indigo bags contain 3 clear gold bags, 5 mirrored bronze bags.
faded teal bags contain 4 mirrored white bags.
shiny fuchsia bags contain 3 drab indigo bags.
dim red bags contain 3 clear bronze bags.
dotted brown bags contain 4 wavy maroon bags, 5 drab green bags, 3 dark purple bags.
dark tomato bags contain 3 vibrant coral bags, 5 dull coral bags, 2 drab cyan bags, 1 posh blue bag.
clear teal bags contain 3 dark white bags.
dark silver bags contain 3 dark cyan bags, 4 plaid salmon bags.
wavy fuchsia bags contain 4 bright brown bags, 4 bright aqua bags, 5 light orange bags.
light bronze bags contain 4 clear plum bags.
striped purple bags contain 1 dim indigo bag.
clear tomato bags contain 4 mirrored tomato bags, 3 muted indigo bags, 1 striped tan bag.
muted turquoise bags contain 5 faded beige bags, 4 clear crimson bags, 2 bright teal bags.
dull cyan bags contain 5 mirrored aqua bags, 2 shiny aqua bags, 3 light black bags, 4 bright coral bags.
plaid crimson bags contain 2 mirrored teal bags, 2 dull fuchsia bags.
shiny maroon bags contain 1 posh gold bag.
dim white bags contain 5 striped brown bags, 2 dull magenta bags, 5 plaid tan bags.
muted green bags contain 2 dull magenta bags, 5 clear cyan bags.
plaid teal bags contain 2 dark tan bags, 3 pale lime bags.
dotted lavender bags contain 2 posh aqua bags, 3 dull cyan bags.
light salmon bags contain 5 dark silver bags.
faded white bags contain 2 wavy maroon bags, 3 dull cyan bags.
dull tomato bags contain 2 dim aqua bags, 4 posh lavender bags, 1 faded red bag.
dark olive bags contain 5 clear bronze bags, 2 drab plum bags.
pale indigo bags contain 2 mirrored beige bags, 5 wavy turquoise bags, 4 striped green bags, 2 dotted lavender bags.
plaid purple bags contain 1 light lime bag.
clear purple bags contain 3 vibrant white bags.
dark yellow bags contain 2 pale olive bags, 4 pale cyan bags, 5 bright teal bags.
muted beige bags contain 2 posh lime bags, 5 shiny gray bags, 2 dull blue bags.
vibrant orange bags contain 5 posh crimson bags, 4 light chartreuse bags.
light magenta bags contain 2 plaid maroon bags, 1 posh beige bag, 5 pale salmon bags.
dotted crimson bags contain 5 dark chartreuse bags.
striped coral bags contain 2 dim aqua bags.
striped aqua bags contain 3 posh salmon bags, 3 dull red bags.
mirrored salmon bags contain 5 bright red bags, 2 light green bags, 3 clear black bags, 5 posh brown bags.
posh white bags contain 4 drab violet bags, 2 dotted silver bags.
posh blue bags contain 4 dull maroon bags, 3 vibrant coral bags.
dim orange bags contain 2 dull olive bags.
shiny teal bags contain 1 faded tomato bag, 4 muted violet bags.
mirrored maroon bags contain 3 dull blue bags.
dark lavender bags contain 1 drab red bag, 3 shiny indigo bags, 4 faded beige bags, 1 drab turquoise bag.
shiny olive bags contain 3 dark violet bags, 1 striped gold bag, 2 mirrored lime bags.
bright violet bags contain 2 wavy bronze bags, 3 drab olive bags, 5 mirrored olive bags, 2 wavy lavender bags.
clear olive bags contain 5 faded turquoise bags.
mirrored lavender bags contain 1 light white bag, 4 light purple bags, 3 wavy lavender bags, 2 shiny lime bags.
pale turquoise bags contain 4 dark tan bags.
shiny salmon bags contain 1 shiny gold bag, 5 drab turquoise bags.
vibrant gray bags contain 3 posh brown bags.
dark indigo bags contain 1 mirrored black bag, 5 dull beige bags, 4 shiny beige bags, 3 drab lavender bags.
light teal bags contain 5 dark olive bags, 5 vibrant chartreuse bags, 3 plaid salmon bags, 5 light yellow bags.
clear violet bags contain 3 light crimson bags.
clear tan bags contain 3 striped orange bags, 4 wavy lavender bags, 3 striped silver bags.
clear bronze bags contain 2 plaid beige bags.
clear gray bags contain 4 dotted cyan bags, 4 vibrant plum bags.
drab cyan bags contain 1 light aqua bag, 1 drab teal bag, 3 bright orange bags, 3 dark white bags.
plaid beige bags contain 3 dull green bags.
wavy gold bags contain 4 shiny olive bags, 3 bright tan bags.
clear aqua bags contain 3 posh chartreuse bags, 4 drab silver bags, 5 clear gray bags.
bright chartreuse bags contain 2 light violet bags, 3 vibrant gray bags.
plaid black bags contain 2 posh gray bags.
light beige bags contain 4 dotted olive bags, 5 dull olive bags, 1 faded orange bag.
mirrored teal bags contain 4 mirrored aqua bags.
bright magenta bags contain 1 mirrored magenta bag, 3 bright blue bags, 1 vibrant blue bag, 2 drab gold bags.
dim maroon bags contain 4 light bronze bags, 5 clear violet bags.
light lime bags contain 4 plaid indigo bags.
posh lavender bags contain 4 dark brown bags.
clear beige bags contain 4 posh silver bags, 3 dull coral bags, 2 posh gray bags.
drab bronze bags contain 4 plaid maroon bags.
mirrored purple bags contain 3 dim magenta bags.
dark magenta bags contain 4 faded maroon bags, 1 drab crimson bag, 5 dotted brown bags, 2 bright teal bags.
dim brown bags contain 3 muted olive bags, 5 drab green bags, 1 mirrored olive bag.
dark plum bags contain 2 vibrant tan bags.
bright turquoise bags contain 1 mirrored aqua bag, 3 clear plum bags.
muted black bags contain 5 faded cyan bags, 5 pale tan bags, 2 dotted chartreuse bags.
dotted gray bags contain 3 posh plum bags.
vibrant black bags contain 2 vibrant magenta bags, 5 faded cyan bags.
mirrored cyan bags contain 2 clear cyan bags, 4 light aqua bags, 5 drab blue bags, 1 drab gold bag.
wavy purple bags contain 5 striped magenta bags, 3 clear maroon bags, 1 mirrored green bag, 1 pale black bag.
drab blue bags contain 3 mirrored lime bags, 1 mirrored blue bag.
clear maroon bags contain 5 bright orange bags.
shiny cyan bags contain 2 clear gray bags, 5 pale crimson bags.
pale cyan bags contain 2 wavy turquoise bags, 5 wavy salmon bags.
plaid gold bags contain 1 clear lavender bag, 1 bright beige bag.
mirrored lime bags contain 2 dull tan bags, 3 shiny beige bags.
drab green bags contain 1 vibrant yellow bag.
dull red bags contain 5 plaid blue bags, 5 clear brown bags, 3 pale salmon bags, 2 dark orange bags.
bright beige bags contain 4 dull silver bags, 5 vibrant brown bags, 4 drab red bags, 2 pale violet bags.
clear silver bags contain 4 drab indigo bags, 2 clear salmon bags.
posh bronze bags contain 5 bright indigo bags, 5 dotted purple bags, 1 dark violet bag, 2 dark orange bags.
posh salmon bags contain 5 bright red bags, 3 striped green bags, 3 dark brown bags.
clear cyan bags contain 5 dark chartreuse bags, 1 bright indigo bag, 4 pale yellow bags, 2 vibrant coral bags.
mirrored blue bags contain 2 vibrant white bags.
mirrored yellow bags contain 5 dotted gray bags, 4 dull maroon bags, 2 striped violet bags, 5 clear tomato bags.
striped teal bags contain 2 clear black bags, 3 pale coral bags.
faded orange bags contain 2 dark bronze bags.
mirrored indigo bags contain 3 light tomato bags, 2 shiny crimson bags.
pale green bags contain 4 light chartreuse bags.
plaid cyan bags contain 4 plaid fuchsia bags, 2 shiny teal bags, 3 dotted fuchsia bags, 3 dim red bags.
muted gold bags contain 2 dull tan bags, 1 faded bronze bag, 4 dull maroon bags.
wavy green bags contain 5 pale coral bags, 1 dull blue bag, 4 drab blue bags, 1 striped tan bag.
light chartreuse bags contain 4 striped brown bags, 5 plaid purple bags, 4 drab cyan bags, 3 dull plum bags.
dotted cyan bags contain 4 shiny black bags.
light purple bags contain no other bags.
dotted aqua bags contain 4 light gray bags, 2 light purple bags, 5 mirrored lime bags.
drab gold bags contain 2 bright green bags, 5 bright indigo bags.
posh gray bags contain 5 bright orange bags, 5 bright blue bags.
striped red bags contain 4 drab green bags, 1 clear cyan bag.
dotted bronze bags contain 5 light orange bags.
muted plum bags contain 2 bright black bags, 3 dotted tomato bags, 2 vibrant brown bags.
mirrored black bags contain 3 plaid chartreuse bags, 2 shiny indigo bags, 2 shiny beige bags.
drab lavender bags contain 5 drab cyan bags, 1 muted purple bag, 1 wavy red bag, 3 drab crimson bags.
vibrant turquoise bags contain 3 shiny beige bags, 3 striped brown bags, 5 dim teal bags.
muted tan bags contain 1 plaid purple bag, 3 shiny beige bags, 1 drab gold bag.
pale beige bags contain 5 bright silver bags.
wavy olive bags contain 4 dotted turquoise bags, 4 dull silver bags, 1 bright gold bag.
dim olive bags contain 5 light lavender bags, 4 shiny tomato bags, 4 clear cyan bags.
wavy salmon bags contain 4 bright aqua bags.
dotted gold bags contain 3 shiny red bags, 3 dull fuchsia bags.
shiny violet bags contain 3 dotted tomato bags, 1 drab coral bag.
striped plum bags contain 4 drab beige bags, 3 clear tan bags, 5 light aqua bags, 1 shiny fuchsia bag.
clear lavender bags contain 2 bright aqua bags, 3 dull silver bags, 3 bright green bags, 2 bright orange bags.
faded maroon bags contain 5 dark indigo bags, 1 posh fuchsia bag.
vibrant red bags contain 4 striped fuchsia bags, 3 drab orange bags, 1 clear brown bag, 1 plaid turquoise bag.
dull coral bags contain 2 dim teal bags, 3 faded bronze bags.
pale salmon bags contain 3 dull magenta bags, 1 light crimson bag.
dotted magenta bags contain 4 dull maroon bags, 2 bright lime bags, 4 plaid indigo bags, 4 faded cyan bags.
wavy gray bags contain 4 muted gray bags, 3 shiny magenta bags, 1 posh teal bag.
light red bags contain 4 shiny chartreuse bags.
dim blue bags contain 4 vibrant orange bags.
muted bronze bags contain 5 mirrored aqua bags, 4 dim green bags.
drab lime bags contain 1 drab cyan bag, 3 pale crimson bags, 4 bright green bags, 3 drab lavender bags.
light white bags contain 5 bright green bags.
bright teal bags contain 4 shiny brown bags, 4 dark silver bags.
striped beige bags contain 2 shiny magenta bags.
wavy magenta bags contain 5 pale bronze bags, 5 pale plum bags, 3 muted silver bags.
dark orange bags contain 1 drab tomato bag, 3 striped brown bags, 1 dim teal bag, 5 bright beige bags.
striped indigo bags contain 1 vibrant gold bag, 1 shiny green bag.
clear coral bags contain 2 shiny gray bags.
faded yellow bags contain 4 faded gold bags, 2 bright turquoise bags, 5 dark silver bags, 3 wavy coral bags.
dim plum bags contain 1 clear purple bag, 4 light brown bags.
mirrored turquoise bags contain 5 wavy indigo bags, 3 dark fuchsia bags, 5 plaid white bags, 2 dim turquoise bags.
posh black bags contain 2 striped black bags, 5 dim teal bags, 3 bright silver bags, 5 posh beige bags.
dotted fuchsia bags contain 1 faded turquoise bag, 2 shiny lavender bags, 4 posh salmon bags, 1 clear olive bag.
faded lavender bags contain 2 striped yellow bags, 1 posh lavender bag.
dim lime bags contain 2 wavy gray bags, 5 clear gray bags.
vibrant bronze bags contain 3 drab tomato bags, 5 bright tan bags.
dull plum bags contain 5 bright red bags, 4 dull magenta bags.
dim teal bags contain 4 light purple bags, 4 plaid lavender bags, 1 dull magenta bag.
dull yellow bags contain 4 vibrant orange bags, 1 dark tomato bag, 5 pale tan bags.
dull green bags contain 2 bright blue bags, 5 dull red bags.
light crimson bags contain 5 dull maroon bags, 4 muted gold bags.
dark black bags contain 1 dim silver bag, 3 plaid magenta bags.
bright lavender bags contain 4 muted fuchsia bags.
drab coral bags contain 4 shiny chartreuse bags, 3 posh yellow bags, 3 wavy indigo bags.
mirrored crimson bags contain 3 posh maroon bags, 5 striped olive bags, 3 mirrored magenta bags.
muted coral bags contain 3 wavy violet bags, 1 dotted chartreuse bag, 1 shiny beige bag.
vibrant gold bags contain 2 dull orange bags, 1 clear chartreuse bag.
wavy orange bags contain 5 dark bronze bags.
mirrored white bags contain 5 clear gold bags, 3 drab tomato bags, 4 dotted bronze bags, 3 striped orange bags.
clear gold bags contain 3 drab indigo bags, 4 wavy violet bags, 2 shiny salmon bags, 4 light brown bags.
shiny magenta bags contain 5 drab silver bags, 2 muted gold bags.
dim violet bags contain 1 posh lime bag, 4 shiny orange bags, 2 posh chartreuse bags.
striped olive bags contain 4 plaid indigo bags, 5 dim chartreuse bags, 4 clear lavender bags.
plaid gray bags contain 3 shiny gold bags, 2 dull coral bags.
clear crimson bags contain 4 shiny aqua bags, 3 light crimson bags, 5 dim chartreuse bags.
drab silver bags contain 1 dim teal bag, 3 faded cyan bags, 1 shiny indigo bag.
mirrored green bags contain 5 dotted lime bags, 4 pale cyan bags.
bright aqua bags contain no other bags.
bright plum bags contain 4 dim aqua bags, 2 dull crimson bags, 1 wavy maroon bag.
vibrant lavender bags contain 1 plaid tan bag, 3 vibrant brown bags, 3 drab gold bags, 4 faded red bags.
pale white bags contain 3 bright brown bags, 4 mirrored beige bags.
plaid lavender bags contain 1 dull magenta bag, 2 dull silver bags, 1 shiny indigo bag.
bright salmon bags contain 1 striped coral bag, 4 plaid lavender bags, 1 muted red bag, 1 drab red bag.
plaid olive bags contain 5 faded turquoise bags, 4 dim green bags, 2 striped beige bags.
wavy plum bags contain 1 clear lavender bag, 2 faded brown bags.
clear fuchsia bags contain 1 muted bronze bag.
wavy turquoise bags contain 5 shiny lime bags, 1 drab olive bag, 4 dim white bags, 1 dotted gray bag.
vibrant aqua bags contain 2 faded lavender bags.
dotted white bags contain 3 muted crimson bags, 5 mirrored white bags, 1 mirrored fuchsia bag.
bright purple bags contain 2 dotted chartreuse bags, 4 posh cyan bags, 3 bright plum bags.
light aqua bags contain 1 plaid lavender bag, 3 wavy coral bags, 5 shiny indigo bags.
drab yellow bags contain 4 shiny teal bags, 2 dotted green bags, 5 vibrant silver bags, 3 dotted turquoise bags.
mirrored olive bags contain 1 dull plum bag.
light olive bags contain 1 shiny coral bag, 4 drab white bags, 3 dim turquoise bags, 4 dull gold bags.
shiny indigo bags contain no other bags.
dull gold bags contain 3 dark indigo bags.
bright tomato bags contain 5 muted blue bags.
faded purple bags contain 4 bright orange bags, 2 faded violet bags.
drab magenta bags contain 3 wavy lavender bags, 2 drab cyan bags, 2 clear beige bags, 4 bright indigo bags.
striped lime bags contain 4 light tan bags.
light gold bags contain 2 pale plum bags.
striped black bags contain 1 plaid salmon bag, 2 plaid beige bags, 4 dotted teal bags, 2 posh chartreuse bags.
faded tomato bags contain 2 striped yellow bags, 4 muted red bags.
dull fuchsia bags contain 5 dotted olive bags, 2 muted purple bags.
pale purple bags contain 4 posh silver bags, 4 wavy yellow bags.
bright olive bags contain 5 shiny fuchsia bags, 5 dull crimson bags, 5 drab red bags, 5 posh turquoise bags.
vibrant fuchsia bags contain 1 vibrant beige bag, 5 shiny magenta bags.
faded turquoise bags contain 5 light lime bags, 4 dark white bags.
plaid orange bags contain 5 vibrant coral bags, 4 light crimson bags, 4 plaid chartreuse bags, 1 dull green bag.
posh indigo bags contain 3 wavy green bags, 2 shiny orange bags, 5 faded violet bags, 2 dotted coral bags.
mirrored red bags contain 4 mirrored olive bags, 1 dark silver bag, 1 dull red bag.
dim salmon bags contain 1 striped salmon bag, 5 faded gray bags.
dim cyan bags contain 3 wavy olive bags, 5 drab purple bags, 3 mirrored bronze bags.
light blue bags contain 2 striped bronze bags, 4 dull white bags, 1 posh bronze bag.
dull turquoise bags contain 4 striped red bags, 1 light lavender bag, 5 plaid bronze bags, 1 mirrored brown bag.
vibrant coral bags contain 1 bright orange bag.
striped cyan bags contain 2 dark white bags, 4 drab red bags, 2 plaid salmon bags.
muted tomato bags contain 4 drab red bags, 3 vibrant silver bags, 4 clear fuchsia bags, 3 wavy white bags.
dotted red bags contain 1 light blue bag.
dark beige bags contain 2 posh lime bags, 3 striped black bags.
dark cyan bags contain 1 dim chartreuse bag, 2 shiny beige bags, 4 dotted magenta bags, 4 light chartreuse bags.
dull lime bags contain 3 muted chartreuse bags.
light brown bags contain 3 mirrored brown bags.
vibrant magenta bags contain 1 dim green bag.
shiny brown bags contain 5 bright brown bags, 3 faded cyan bags, 5 clear tan bags, 2 plaid maroon bags.
drab purple bags contain 1 shiny indigo bag, 4 striped yellow bags.

66
2020/d07/ex2/ex2.py Executable file
View file

@ -0,0 +1,66 @@
#!/usr/bin/env python
import re
import sys
from collections import defaultdict
from copy import deepcopy
from dataclasses import dataclass
from typing import Dict, List, Set, Tuple
@dataclass(eq=True, frozen=True) # Hashable
class ColorInfo:
num: int
color: str
Graph = Dict[str, Set[ColorInfo]]
def extract_info(line: str) -> Tuple[str, Set[ColorInfo]]:
color_pattern = re.compile("(.*) contain ")
match = color_pattern.search(line)
assert match is not None
color = match.group(1).replace("bags", "bag")
line = line[match.end() : -1] # Remove period at end of line
if line == "no other bags":
return color, set()
colors: Set[ColorInfo] = set()
pattern = re.compile("([0-9]+) (.*)")
for col in line.split(", "):
match = pattern.search(col)
assert match is not None
colors |= {
ColorInfo(int(match.group(1)), match.group(2).replace("bags", "bag"))
}
return color, colors
def to_graph(raw: List[str]) -> Graph:
return {color: inside for color, inside in map(extract_info, raw)}
def num_bags(graph: Graph, col: str) -> int:
return sum(
contained.num * (1 + num_bags(graph, contained.color))
for contained in graph[col]
)
def solve(raw: List[str]) -> int:
graph = to_graph(raw)
return num_bags(graph, "shiny gold bag")
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

594
2020/d07/ex2/input Normal file
View file

@ -0,0 +1,594 @@
shiny aqua bags contain 1 dark white bag.
muted blue bags contain 1 vibrant lavender bag, 4 dotted silver bags, 2 dim indigo bags.
drab gray bags contain 5 mirrored white bags, 1 light green bag, 5 shiny lavender bags, 5 faded aqua bags.
muted indigo bags contain 4 muted chartreuse bags, 2 dotted teal bags.
drab white bags contain 2 dull fuchsia bags, 1 vibrant bronze bag.
dim lavender bags contain 4 muted tan bags.
dotted tomato bags contain 1 mirrored lime bag, 2 vibrant white bags.
clear orange bags contain 5 clear violet bags, 2 dull beige bags, 2 dark chartreuse bags.
bright lime bags contain no other bags.
striped brown bags contain 3 bright orange bags.
vibrant green bags contain 3 shiny fuchsia bags.
plaid tomato bags contain 3 faded chartreuse bags, 2 wavy salmon bags, 1 faded white bag, 3 mirrored maroon bags.
drab beige bags contain 2 shiny bronze bags, 4 pale violet bags, 3 bright tomato bags, 4 pale red bags.
posh green bags contain 2 dull lavender bags, 4 clear plum bags, 2 dark gray bags.
dull maroon bags contain 3 dull magenta bags, 1 dull tan bag, 1 faded cyan bag, 5 dull silver bags.
faded crimson bags contain 2 muted purple bags, 4 dotted olive bags, 5 drab silver bags.
wavy bronze bags contain 3 dark orange bags, 2 dark brown bags, 5 bright silver bags.
dark turquoise bags contain 5 dull plum bags.
dull lavender bags contain 4 dotted maroon bags, 3 muted brown bags, 4 drab black bags, 4 dull cyan bags.
dotted plum bags contain 1 shiny bronze bag, 3 clear brown bags, 3 muted indigo bags.
dull white bags contain 3 clear tan bags, 5 shiny gold bags, 2 drab crimson bags.
dull teal bags contain 2 bright tomato bags.
shiny crimson bags contain 3 light green bags, 5 striped brown bags, 3 faded fuchsia bags.
wavy brown bags contain 1 drab crimson bag, 2 wavy indigo bags.
dark tan bags contain 2 faded gray bags, 4 shiny salmon bags.
shiny red bags contain 4 dull chartreuse bags, 5 pale tomato bags.
bright orange bags contain no other bags.
wavy yellow bags contain 5 light indigo bags, 5 dark gray bags, 5 plaid indigo bags, 4 faded red bags.
faded bronze bags contain 4 faded cyan bags, 5 shiny beige bags, 5 muted red bags.
dull bronze bags contain 1 mirrored beige bag, 5 muted violet bags, 1 wavy lime bag.
dark lime bags contain 2 drab maroon bags, 5 bright indigo bags, 4 shiny black bags, 5 dotted turquoise bags.
drab red bags contain 5 bright red bags, 2 vibrant brown bags.
dotted salmon bags contain 3 vibrant turquoise bags, 2 dull beige bags, 3 light turquoise bags.
dull gray bags contain 3 striped green bags, 3 wavy coral bags, 1 dark gray bag, 2 light indigo bags.
faded black bags contain 4 muted fuchsia bags, 4 wavy coral bags, 1 drab tomato bag.
muted magenta bags contain 2 posh chartreuse bags, 4 pale violet bags.
light tan bags contain 2 posh turquoise bags, 3 vibrant white bags, 1 light black bag.
dark blue bags contain 3 plaid indigo bags, 2 posh black bags.
dull indigo bags contain 4 light gray bags, 3 dotted tan bags, 4 dull coral bags.
dim fuchsia bags contain 3 vibrant yellow bags, 3 mirrored cyan bags, 4 mirrored brown bags.
shiny beige bags contain 2 dull silver bags, 3 bright lime bags, 5 dull magenta bags.
light cyan bags contain 3 vibrant violet bags, 2 mirrored tomato bags, 2 vibrant coral bags, 4 mirrored silver bags.
clear turquoise bags contain 4 drab tomato bags, 3 shiny gold bags, 4 drab gold bags.
pale teal bags contain 2 wavy maroon bags, 2 dotted olive bags, 4 shiny white bags, 2 drab turquoise bags.
dark purple bags contain 1 wavy indigo bag, 3 bright black bags, 3 dotted teal bags.
bright white bags contain 5 wavy red bags, 2 mirrored cyan bags, 3 drab green bags.
mirrored aqua bags contain 1 faded violet bag, 5 dotted purple bags.
shiny lime bags contain 4 dark aqua bags.
pale bronze bags contain 1 clear crimson bag.
vibrant white bags contain 5 plaid lavender bags, 1 drab red bag, 4 vibrant brown bags.
plaid tan bags contain 5 dim crimson bags.
posh olive bags contain 3 bright red bags.
plaid brown bags contain 5 vibrant turquoise bags.
mirrored tomato bags contain 2 dotted chartreuse bags, 3 light aqua bags, 3 posh beige bags.
plaid blue bags contain 5 striped green bags, 1 plaid purple bag, 4 muted gold bags.
shiny tan bags contain 5 striped coral bags, 1 dull brown bag.
shiny gold bags contain 1 dull magenta bag, 5 dark white bags, 4 faded turquoise bags.
dull salmon bags contain 2 plaid gold bags, 2 light indigo bags.
striped tomato bags contain 2 striped tan bags, 4 light blue bags, 4 drab tan bags.
drab tomato bags contain 3 dim teal bags, 4 striped yellow bags, 3 bright red bags.
faded olive bags contain 1 drab plum bag, 1 pale aqua bag, 3 light blue bags.
dotted indigo bags contain 2 clear tomato bags.
dark white bags contain 5 light aqua bags, 2 dim teal bags, 2 muted fuchsia bags, 5 light purple bags.
dull orange bags contain 4 pale gold bags, 5 posh brown bags, 2 mirrored brown bags, 3 dark bronze bags.
bright maroon bags contain 1 mirrored yellow bag, 4 light teal bags.
bright silver bags contain 1 vibrant coral bag, 3 dim teal bags, 5 light purple bags.
muted olive bags contain 5 plaid orange bags, 1 muted magenta bag.
dull silver bags contain no other bags.
pale maroon bags contain 2 pale bronze bags.
light gray bags contain 4 vibrant yellow bags, 2 pale red bags.
drab teal bags contain 2 light crimson bags, 3 vibrant brown bags, 3 vibrant tan bags.
bright gold bags contain 1 wavy red bag, 5 wavy coral bags.
plaid chartreuse bags contain 2 dim coral bags, 4 drab silver bags, 5 dim chartreuse bags, 3 light purple bags.
clear blue bags contain 2 pale tomato bags, 4 dull gold bags, 4 dim fuchsia bags, 4 pale coral bags.
vibrant purple bags contain 5 faded orange bags.
plaid aqua bags contain 3 muted cyan bags, 2 wavy gray bags, 4 drab green bags, 4 pale beige bags.
muted lime bags contain 1 muted tan bag.
faded coral bags contain 3 drab turquoise bags, 1 shiny plum bag, 5 mirrored green bags, 5 clear white bags.
vibrant lime bags contain 5 posh coral bags.
faded green bags contain 3 pale orange bags, 5 dull turquoise bags, 1 mirrored crimson bag.
mirrored gray bags contain 5 dim indigo bags.
wavy maroon bags contain 4 mirrored bronze bags, 1 striped olive bag, 2 dull salmon bags, 3 shiny crimson bags.
dark violet bags contain 2 light purple bags.
dark green bags contain 2 dim cyan bags.
pale black bags contain 1 mirrored gold bag.
bright yellow bags contain 2 vibrant crimson bags, 3 plaid lime bags, 2 dotted gold bags.
muted teal bags contain 1 pale violet bag, 4 dull silver bags.
dim beige bags contain 5 wavy red bags.
muted purple bags contain 4 clear cyan bags.
plaid fuchsia bags contain 3 dark coral bags.
plaid bronze bags contain 5 plaid orange bags, 2 drab indigo bags.
faded indigo bags contain 1 dark chartreuse bag, 4 dull green bags, 1 mirrored magenta bag.
posh plum bags contain 3 dark chartreuse bags, 3 dotted turquoise bags, 4 dull maroon bags, 1 posh bronze bag.
pale gold bags contain 4 striped brown bags.
mirrored chartreuse bags contain 4 bright silver bags, 3 mirrored tomato bags, 4 wavy orange bags.
pale orange bags contain 2 posh fuchsia bags, 2 clear salmon bags, 2 bright green bags.
clear brown bags contain 4 light lime bags, 4 bright green bags, 5 pale yellow bags, 2 drab cyan bags.
shiny plum bags contain 5 vibrant gray bags, 3 bright blue bags, 5 dark tomato bags.
wavy white bags contain 4 plaid lime bags, 4 posh maroon bags, 5 drab lime bags, 1 vibrant crimson bag.
faded red bags contain 1 dull coral bag, 5 clear cyan bags, 4 plaid chartreuse bags, 3 plaid orange bags.
plaid red bags contain 5 pale blue bags, 4 light crimson bags, 3 faded fuchsia bags.
bright cyan bags contain 3 dark white bags, 2 light crimson bags, 1 bright aqua bag.
muted lavender bags contain 1 light green bag, 4 striped silver bags, 3 posh crimson bags.
wavy crimson bags contain 1 light purple bag, 4 bright blue bags, 2 dull coral bags, 1 wavy beige bag.
faded aqua bags contain 5 muted brown bags.
mirrored fuchsia bags contain 1 faded beige bag, 3 muted gold bags.
dark chartreuse bags contain 5 bright lime bags.
plaid green bags contain 4 mirrored tan bags, 1 mirrored tomato bag, 5 pale indigo bags, 1 mirrored plum bag.
shiny black bags contain 3 plaid chartreuse bags.
dotted purple bags contain 2 dim teal bags.
faded tan bags contain 2 bright fuchsia bags, 5 shiny fuchsia bags, 1 muted fuchsia bag, 1 mirrored brown bag.
drab brown bags contain 1 striped orange bag, 4 dotted tomato bags.
dull olive bags contain 1 striped black bag, 1 vibrant magenta bag.
mirrored plum bags contain 1 clear gold bag, 5 pale green bags.
dim tomato bags contain 4 drab gold bags, 2 shiny aqua bags.
light lavender bags contain 1 muted violet bag.
dim gray bags contain 3 light purple bags, 1 posh crimson bag, 1 faded brown bag.
muted aqua bags contain 4 dull beige bags, 4 dull red bags.
faded silver bags contain 1 mirrored cyan bag.
shiny green bags contain 5 dull maroon bags.
muted chartreuse bags contain 2 clear tan bags.
plaid plum bags contain 1 dotted lime bag, 4 clear brown bags, 4 dull red bags.
dotted silver bags contain 1 posh coral bag.
dim crimson bags contain 4 faded violet bags, 1 striped silver bag.
bright brown bags contain 1 bright coral bag, 3 posh brown bags, 4 drab tan bags.
wavy cyan bags contain 3 clear gold bags, 1 mirrored salmon bag, 3 bright fuchsia bags, 2 light bronze bags.
dull violet bags contain 5 striped white bags, 4 light blue bags, 4 dim black bags.
vibrant olive bags contain 2 vibrant coral bags.
bright coral bags contain 2 vibrant tan bags, 3 shiny indigo bags, 2 plaid indigo bags.
dim turquoise bags contain 1 pale violet bag.
striped crimson bags contain 2 faded gray bags.
clear green bags contain 3 mirrored olive bags, 3 shiny tomato bags.
faded violet bags contain 2 wavy coral bags, 2 dull tan bags, 1 dull silver bag, 1 bright orange bag.
pale chartreuse bags contain 4 shiny crimson bags, 2 clear bronze bags.
light plum bags contain 3 drab bronze bags, 1 bright bronze bag, 1 posh yellow bag.
pale tomato bags contain 1 dim teal bag, 5 drab cyan bags, 3 muted coral bags, 2 dim chartreuse bags.
plaid coral bags contain 1 striped tan bag, 3 vibrant cyan bags, 3 light beige bags, 2 dotted green bags.
bright gray bags contain 4 mirrored teal bags, 4 striped brown bags, 1 dim green bag, 4 clear cyan bags.
drab fuchsia bags contain 2 mirrored salmon bags, 4 posh orange bags, 3 faded crimson bags, 3 pale plum bags.
light tomato bags contain 2 dotted gold bags, 1 dotted bronze bag.
muted violet bags contain 2 light chartreuse bags.
drab tan bags contain 2 light green bags, 5 bright red bags, 4 shiny beige bags.
drab chartreuse bags contain 2 drab salmon bags, 2 dark brown bags, 4 clear turquoise bags.
drab violet bags contain 4 faded red bags.
posh cyan bags contain 4 bright violet bags.
posh orange bags contain 4 pale plum bags, 5 posh aqua bags.
plaid silver bags contain 1 dotted brown bag, 3 drab gold bags, 4 clear yellow bags.
mirrored silver bags contain 3 shiny beige bags, 1 drab silver bag.
faded gray bags contain no other bags.
wavy tomato bags contain 1 bright brown bag, 3 striped red bags, 2 vibrant maroon bags.
posh violet bags contain 2 dim aqua bags.
bright blue bags contain 5 light lime bags, 2 faded violet bags, 3 light aqua bags, 4 vibrant coral bags.
dark teal bags contain 5 muted fuchsia bags.
striped fuchsia bags contain 1 wavy turquoise bag, 5 wavy green bags, 4 posh gold bags.
posh maroon bags contain 2 dull red bags.
shiny purple bags contain 2 clear tan bags.
wavy lime bags contain 2 dark coral bags, 1 shiny gold bag.
wavy silver bags contain 4 dotted white bags.
shiny silver bags contain 2 plaid gold bags, 2 dim green bags, 5 plaid lime bags, 3 dull red bags.
wavy red bags contain 3 vibrant brown bags, 4 bright indigo bags.
dull chartreuse bags contain 4 dotted lime bags, 2 bright silver bags, 3 dull red bags, 4 wavy maroon bags.
vibrant silver bags contain 1 bright fuchsia bag, 3 drab lavender bags, 2 drab olive bags, 3 dotted teal bags.
striped gray bags contain 5 plaid orange bags, 1 wavy coral bag.
striped green bags contain 4 wavy coral bags, 4 shiny gold bags, 3 dark brown bags, 5 vibrant brown bags.
mirrored violet bags contain 3 dim silver bags, 1 posh tomato bag, 1 light salmon bag.
dull purple bags contain 1 light gray bag, 3 wavy yellow bags, 1 wavy salmon bag.
mirrored beige bags contain 4 dark cyan bags, 5 dull green bags.
posh lime bags contain 3 posh chartreuse bags.
vibrant tan bags contain 2 dull plum bags, 1 striped brown bag, 4 vibrant coral bags.
dotted orange bags contain 1 mirrored olive bag, 5 drab silver bags.
clear indigo bags contain 3 light lime bags, 4 dull coral bags.
pale gray bags contain 1 faded black bag, 3 dim green bags, 4 wavy lavender bags, 2 posh brown bags.
posh gold bags contain 5 dark tan bags, 2 dotted olive bags, 5 dark aqua bags.
striped chartreuse bags contain 2 dull magenta bags, 1 posh tomato bag.
mirrored bronze bags contain 2 faded fuchsia bags.
clear salmon bags contain 4 posh bronze bags, 5 clear plum bags, 5 dull blue bags.
posh purple bags contain 5 dim gray bags, 3 faded brown bags.
faded lime bags contain 5 dim turquoise bags, 3 dark indigo bags, 2 vibrant gray bags, 1 muted silver bag.
wavy beige bags contain 1 dark bronze bag, 4 dull plum bags, 4 mirrored silver bags.
clear yellow bags contain 2 vibrant teal bags.
vibrant plum bags contain 4 muted chartreuse bags, 4 posh silver bags.
striped yellow bags contain 2 dull maroon bags, 5 bright red bags, 2 posh chartreuse bags.
dark coral bags contain 3 dull tan bags.
dull magenta bags contain no other bags.
dark gold bags contain 1 dotted indigo bag, 4 shiny teal bags, 4 dotted silver bags.
dim tan bags contain 1 striped lavender bag, 1 shiny tomato bag.
muted maroon bags contain 2 dull salmon bags, 4 dim chartreuse bags, 3 bright aqua bags, 2 faded indigo bags.
vibrant tomato bags contain 2 dark silver bags, 3 plaid purple bags.
dotted lime bags contain 3 shiny crimson bags, 2 pale yellow bags.
muted fuchsia bags contain 1 dull tan bag.
bright tan bags contain 5 pale gold bags, 5 drab teal bags, 2 light blue bags.
dark crimson bags contain 4 shiny orange bags, 3 faded purple bags, 3 bright white bags.
striped tan bags contain 4 dotted turquoise bags, 4 drab lime bags, 5 dim teal bags.
posh fuchsia bags contain 2 dotted olive bags, 2 mirrored beige bags, 3 shiny bronze bags.
pale silver bags contain 4 vibrant lavender bags, 4 clear beige bags, 4 striped gold bags.
posh aqua bags contain 4 drab lime bags, 4 dull tan bags, 5 vibrant tan bags.
plaid salmon bags contain 5 dim coral bags, 2 wavy bronze bags.
mirrored orange bags contain 4 vibrant gray bags.
dim yellow bags contain 5 pale tan bags, 4 dark black bags.
dotted coral bags contain 4 dotted chartreuse bags, 2 bright red bags, 1 vibrant white bag, 1 vibrant brown bag.
muted crimson bags contain 4 striped orange bags, 5 pale yellow bags, 3 posh blue bags, 1 muted red bag.
striped lavender bags contain 3 striped brown bags.
striped maroon bags contain 2 shiny yellow bags.
vibrant blue bags contain 3 faded cyan bags, 1 shiny lime bag, 3 dark tomato bags.
pale lavender bags contain 4 plaid magenta bags, 4 striped blue bags.
dull tan bags contain 4 shiny indigo bags, 2 light purple bags, 4 faded cyan bags.
dotted beige bags contain 3 drab indigo bags.
light indigo bags contain 1 faded cyan bag, 5 bright aqua bags, 1 shiny indigo bag.
vibrant crimson bags contain 4 dotted fuchsia bags.
wavy blue bags contain 4 wavy teal bags, 1 dull blue bag.
vibrant chartreuse bags contain 4 striped orange bags.
vibrant cyan bags contain 5 wavy coral bags.
faded brown bags contain 5 faded turquoise bags.
faded magenta bags contain 1 dull indigo bag, 4 plaid aqua bags, 4 dim crimson bags.
mirrored coral bags contain 4 drab crimson bags, 2 light salmon bags, 2 clear indigo bags.
faded cyan bags contain no other bags.
dark brown bags contain 5 light purple bags.
wavy violet bags contain 3 dull coral bags, 1 bright aqua bag, 3 shiny lavender bags.
posh tomato bags contain 4 vibrant chartreuse bags, 4 mirrored teal bags.
pale crimson bags contain 1 plaid orange bag, 1 dark violet bag, 3 plaid lavender bags.
dark fuchsia bags contain 4 plaid beige bags, 2 plaid chartreuse bags.
plaid magenta bags contain 3 clear lavender bags, 5 mirrored brown bags, 5 shiny bronze bags.
striped blue bags contain 1 dull bronze bag, 1 dotted fuchsia bag, 1 light lavender bag, 1 clear turquoise bag.
dotted olive bags contain 4 dotted turquoise bags, 5 dotted bronze bags, 3 pale yellow bags, 4 pale red bags.
posh silver bags contain 3 pale violet bags, 1 plaid salmon bag, 1 posh coral bag.
dotted chartreuse bags contain 3 bright blue bags.
light coral bags contain 4 shiny fuchsia bags, 2 pale red bags, 1 muted silver bag, 2 bright cyan bags.
pale brown bags contain 5 light aqua bags.
dotted black bags contain 2 plaid purple bags, 1 mirrored aqua bag, 5 posh beige bags.
posh coral bags contain 3 dark aqua bags, 2 pale yellow bags, 5 plaid blue bags, 4 dim aqua bags.
shiny gray bags contain 1 bright gold bag, 1 muted bronze bag, 5 striped green bags, 5 shiny teal bags.
drab orange bags contain 5 plaid salmon bags, 2 vibrant beige bags.
plaid yellow bags contain 4 clear teal bags, 2 bright red bags.
striped violet bags contain 4 mirrored fuchsia bags, 4 vibrant white bags, 3 dim teal bags.
dim aqua bags contain 1 muted fuchsia bag, 1 dull tan bag.
light orange bags contain 2 bright red bags, 4 dark white bags, 1 dim chartreuse bag, 5 faded fuchsia bags.
faded salmon bags contain 5 wavy gray bags.
shiny yellow bags contain 2 vibrant plum bags, 3 dim teal bags, 1 plaid tan bag, 5 posh plum bags.
vibrant beige bags contain 2 wavy lavender bags, 4 posh chartreuse bags, 3 pale teal bags, 5 wavy lime bags.
light fuchsia bags contain 3 clear brown bags, 3 bright lavender bags.
pale magenta bags contain 4 posh silver bags.
dark maroon bags contain 3 drab turquoise bags.
faded beige bags contain 1 vibrant white bag, 4 drab red bags, 1 drab lavender bag.
bright bronze bags contain 1 pale bronze bag, 3 muted silver bags, 2 striped coral bags, 3 clear gray bags.
light silver bags contain 3 dotted lavender bags, 2 wavy lavender bags.
muted salmon bags contain 2 drab tan bags, 5 wavy tomato bags.
bright black bags contain 5 plaid tan bags.
dim chartreuse bags contain 5 muted gold bags, 5 bright blue bags, 5 faded cyan bags.
shiny white bags contain 4 bright tan bags.
bright red bags contain 3 dull silver bags.
dark aqua bags contain 2 dull red bags.
drab plum bags contain 4 muted brown bags, 5 muted plum bags.
muted yellow bags contain 5 light purple bags, 3 dotted silver bags, 3 faded turquoise bags.
light violet bags contain 1 pale red bag, 4 dim silver bags, 2 mirrored bronze bags.
pale lime bags contain 4 bright lavender bags.
pale tan bags contain 4 striped green bags, 2 dotted chartreuse bags.
dim green bags contain 1 light lime bag, 1 shiny beige bag.
mirrored gold bags contain 4 mirrored white bags.
dim silver bags contain 5 pale coral bags, 3 wavy coral bags.
dull aqua bags contain 3 posh indigo bags, 5 dotted coral bags, 1 dark salmon bag, 3 striped crimson bags.
posh yellow bags contain 1 dark bronze bag, 2 mirrored white bags, 2 light crimson bags.
mirrored magenta bags contain 1 bright violet bag, 2 drab lavender bags, 3 pale violet bags, 2 plaid salmon bags.
shiny chartreuse bags contain 2 dotted purple bags, 5 wavy red bags, 3 plaid beige bags.
light black bags contain 1 dark chartreuse bag, 3 faded tomato bags.
clear plum bags contain 5 vibrant brown bags, 3 dim coral bags, 4 mirrored brown bags, 1 faded black bag.
pale violet bags contain 2 dull tan bags.
bright fuchsia bags contain 4 dull orange bags.
dotted teal bags contain 5 bright red bags, 3 wavy red bags, 1 dull coral bag, 3 clear plum bags.
dotted blue bags contain 2 wavy beige bags, 3 muted purple bags.
muted gray bags contain 3 faded aqua bags, 1 shiny olive bag, 5 clear salmon bags, 1 vibrant violet bag.
dull beige bags contain 1 wavy lavender bag, 4 dark bronze bags, 5 dull tan bags.
drab turquoise bags contain 3 posh gray bags, 5 drab red bags.
vibrant yellow bags contain 2 shiny aqua bags, 4 light chartreuse bags.
posh brown bags contain 3 bright green bags, 5 posh lavender bags.
faded gold bags contain 4 vibrant maroon bags, 4 dotted purple bags.
dotted turquoise bags contain 5 clear plum bags, 3 muted gold bags, 4 dark violet bags.
dotted tan bags contain 5 dim aqua bags, 4 striped violet bags.
posh crimson bags contain 4 striped blue bags, 5 dull magenta bags, 2 bright coral bags.
muted white bags contain 5 dull olive bags.
vibrant teal bags contain 5 dotted turquoise bags, 1 striped tan bag, 1 drab tan bag.
dotted yellow bags contain 3 plaid turquoise bags, 2 posh yellow bags, 4 striped blue bags, 5 posh black bags.
posh magenta bags contain 5 mirrored black bags.
dotted green bags contain 4 dim crimson bags, 1 shiny lavender bag, 4 bright salmon bags, 1 plaid gray bag.
bright green bags contain 3 bright aqua bags, 3 dull maroon bags, 4 dark brown bags.
dark gray bags contain 5 muted purple bags, 2 striped blue bags, 4 faded lavender bags.
bright crimson bags contain 2 striped olive bags, 3 muted blue bags.
muted cyan bags contain 3 shiny tomato bags.
light yellow bags contain 2 striped red bags, 4 shiny crimson bags.
pale aqua bags contain 5 shiny yellow bags, 3 dark lavender bags, 3 posh white bags.
clear red bags contain 1 dotted silver bag, 1 dull teal bag, 1 faded maroon bag, 1 dotted salmon bag.
pale red bags contain 2 faded gray bags.
dotted maroon bags contain 5 posh aqua bags, 3 dull silver bags.
dull blue bags contain 4 light crimson bags, 3 light lime bags, 1 dark orange bag, 5 light indigo bags.
posh turquoise bags contain 1 muted gold bag, 5 striped lavender bags, 3 dull salmon bags, 5 vibrant chartreuse bags.
striped magenta bags contain 1 posh silver bag, 5 dark brown bags.
pale blue bags contain 2 muted gold bags, 4 vibrant brown bags, 1 light lavender bag.
vibrant violet bags contain 5 bright red bags.
faded fuchsia bags contain 2 light lime bags, 4 bright lime bags, 3 pale violet bags.
shiny coral bags contain 1 clear plum bag, 5 muted chartreuse bags, 1 muted violet bag, 5 striped yellow bags.
pale olive bags contain 4 plaid lime bags, 1 posh salmon bag.
wavy tan bags contain 3 faded gray bags.
faded chartreuse bags contain 3 dim coral bags, 1 mirrored bronze bag, 3 posh bronze bags.
mirrored brown bags contain 1 faded violet bag, 4 dull maroon bags, 5 dotted magenta bags.
clear white bags contain 5 muted magenta bags, 4 dull magenta bags, 3 pale plum bags, 4 drab indigo bags.
drab maroon bags contain 2 clear beige bags, 3 wavy beige bags, 5 faded purple bags.
striped silver bags contain 3 drab tomato bags.
faded plum bags contain 1 clear teal bag, 3 bright aqua bags.
plaid violet bags contain 2 drab violet bags, 4 muted turquoise bags, 5 muted indigo bags.
clear black bags contain 5 muted fuchsia bags, 1 muted coral bag, 2 light black bags.
vibrant maroon bags contain 1 dark lavender bag, 1 pale crimson bag, 4 bright indigo bags, 5 mirrored maroon bags.
drab indigo bags contain 2 dim coral bags, 1 drab green bag, 2 shiny lavender bags.
drab olive bags contain 2 dark aqua bags, 4 striped brown bags.
dull crimson bags contain 3 dull cyan bags.
wavy teal bags contain 4 striped orange bags, 2 drab cyan bags.
dark red bags contain 2 dull maroon bags, 4 muted plum bags, 4 dull plum bags.
striped salmon bags contain 3 bright red bags, 1 light aqua bag, 4 wavy gold bags.
mirrored tan bags contain 5 dotted olive bags, 2 dim tomato bags, 2 mirrored tomato bags, 4 clear teal bags.
striped white bags contain 2 pale coral bags, 2 shiny green bags.
shiny tomato bags contain 5 pale coral bags, 5 dull beige bags.
vibrant indigo bags contain 2 dim black bags, 4 dim blue bags, 3 dim white bags.
wavy lavender bags contain 4 faded bronze bags, 4 muted red bags, 3 light lime bags, 4 muted gold bags.
shiny turquoise bags contain 2 dull red bags, 5 faded gray bags, 1 muted turquoise bag.
shiny lavender bags contain 5 bright aqua bags.
posh tan bags contain 1 shiny yellow bag, 3 drab magenta bags.
light green bags contain 4 bright red bags, 1 vibrant coral bag.
drab black bags contain 5 faded tomato bags, 3 dotted chartreuse bags.
clear chartreuse bags contain 3 wavy bronze bags, 4 plaid purple bags, 3 dark orange bags.
dull black bags contain 1 wavy teal bag, 3 light lavender bags, 2 striped indigo bags.
wavy black bags contain 2 clear orange bags, 4 muted purple bags.
pale plum bags contain 1 bright coral bag, 1 drab tan bag, 1 plaid fuchsia bag, 1 dotted fuchsia bag.
dotted violet bags contain 3 bright black bags.
posh red bags contain 3 bright black bags.
plaid lime bags contain 5 posh beige bags, 1 dotted turquoise bag.
wavy aqua bags contain 1 dark yellow bag, 3 drab indigo bags.
dim magenta bags contain 3 dark violet bags.
drab aqua bags contain 5 posh orange bags, 1 dark silver bag, 4 plaid purple bags, 2 wavy teal bags.
dull brown bags contain 4 light lime bags.
striped orange bags contain 5 light crimson bags, 3 muted tan bags, 5 dotted coral bags, 3 plaid blue bags.
muted brown bags contain 1 posh blue bag, 4 dotted magenta bags, 3 dull coral bags.
faded blue bags contain 5 striped black bags, 1 vibrant yellow bag.
plaid indigo bags contain 3 dark brown bags, 5 light purple bags, 4 light aqua bags, 3 light green bags.
plaid turquoise bags contain 5 dotted teal bags.
light turquoise bags contain 2 dull salmon bags, 5 dotted tan bags.
dim purple bags contain 4 muted white bags, 5 drab purple bags.
pale coral bags contain 5 posh gray bags.
clear lime bags contain 3 dim magenta bags, 3 plaid tomato bags, 1 drab magenta bag, 3 shiny purple bags.
dim black bags contain 3 clear gold bags, 4 muted violet bags.
light maroon bags contain 4 muted yellow bags, 1 pale cyan bag, 2 mirrored turquoise bags, 4 dull lavender bags.
clear magenta bags contain 2 shiny magenta bags, 2 muted chartreuse bags.
striped bronze bags contain 5 clear tan bags, 1 drab lavender bag, 2 pale crimson bags.
dark salmon bags contain 1 vibrant plum bag, 5 drab tan bags, 4 drab coral bags, 4 dull tan bags.
vibrant salmon bags contain 2 muted olive bags.
dim gold bags contain 2 dim olive bags, 5 plaid olive bags, 2 posh orange bags.
wavy chartreuse bags contain 4 shiny yellow bags, 4 vibrant blue bags.
vibrant brown bags contain 3 striped brown bags, 4 muted red bags, 2 shiny indigo bags.
plaid maroon bags contain 2 muted teal bags, 2 pale yellow bags, 2 bright beige bags, 5 striped yellow bags.
dim indigo bags contain 4 dull tomato bags, 4 clear cyan bags, 2 shiny salmon bags, 1 bright aqua bag.
muted red bags contain 3 dull tan bags, 4 dull magenta bags, 1 bright aqua bag.
posh beige bags contain 5 shiny black bags, 3 dotted magenta bags, 3 drab blue bags, 2 muted coral bags.
pale fuchsia bags contain 3 dark brown bags, 5 posh gold bags.
dark bronze bags contain 1 dim green bag, 5 posh chartreuse bags.
dim coral bags contain 3 dull coral bags, 3 striped brown bags.
drab crimson bags contain 2 dark bronze bags, 4 shiny indigo bags, 3 dull tan bags.
bright indigo bags contain 3 bright blue bags.
pale yellow bags contain 5 dim aqua bags, 1 vibrant brown bag, 2 vibrant tan bags, 3 wavy lavender bags.
drab salmon bags contain 1 dotted indigo bag, 3 muted chartreuse bags, 5 dark olive bags.
muted orange bags contain 4 faded lime bags, 2 dull coral bags, 5 vibrant magenta bags, 4 dull magenta bags.
striped gold bags contain 2 dull silver bags, 5 bright lavender bags, 5 dim teal bags, 5 dark coral bags.
posh chartreuse bags contain 3 dim teal bags, 5 light aqua bags.
shiny blue bags contain 3 dull tan bags, 5 muted magenta bags.
muted silver bags contain 3 wavy blue bags, 2 dim teal bags, 5 muted bronze bags.
shiny bronze bags contain 1 light green bag, 4 vibrant magenta bags.
wavy coral bags contain no other bags.
shiny orange bags contain 2 muted purple bags.
posh teal bags contain 4 clear plum bags.
striped turquoise bags contain 3 muted indigo bags.
dim bronze bags contain 2 shiny silver bags, 1 light silver bag, 2 dim indigo bags, 4 dim tomato bags.
plaid white bags contain 4 drab turquoise bags.
wavy indigo bags contain 3 clear gold bags, 5 mirrored bronze bags.
faded teal bags contain 4 mirrored white bags.
shiny fuchsia bags contain 3 drab indigo bags.
dim red bags contain 3 clear bronze bags.
dotted brown bags contain 4 wavy maroon bags, 5 drab green bags, 3 dark purple bags.
dark tomato bags contain 3 vibrant coral bags, 5 dull coral bags, 2 drab cyan bags, 1 posh blue bag.
clear teal bags contain 3 dark white bags.
dark silver bags contain 3 dark cyan bags, 4 plaid salmon bags.
wavy fuchsia bags contain 4 bright brown bags, 4 bright aqua bags, 5 light orange bags.
light bronze bags contain 4 clear plum bags.
striped purple bags contain 1 dim indigo bag.
clear tomato bags contain 4 mirrored tomato bags, 3 muted indigo bags, 1 striped tan bag.
muted turquoise bags contain 5 faded beige bags, 4 clear crimson bags, 2 bright teal bags.
dull cyan bags contain 5 mirrored aqua bags, 2 shiny aqua bags, 3 light black bags, 4 bright coral bags.
plaid crimson bags contain 2 mirrored teal bags, 2 dull fuchsia bags.
shiny maroon bags contain 1 posh gold bag.
dim white bags contain 5 striped brown bags, 2 dull magenta bags, 5 plaid tan bags.
muted green bags contain 2 dull magenta bags, 5 clear cyan bags.
plaid teal bags contain 2 dark tan bags, 3 pale lime bags.
dotted lavender bags contain 2 posh aqua bags, 3 dull cyan bags.
light salmon bags contain 5 dark silver bags.
faded white bags contain 2 wavy maroon bags, 3 dull cyan bags.
dull tomato bags contain 2 dim aqua bags, 4 posh lavender bags, 1 faded red bag.
dark olive bags contain 5 clear bronze bags, 2 drab plum bags.
pale indigo bags contain 2 mirrored beige bags, 5 wavy turquoise bags, 4 striped green bags, 2 dotted lavender bags.
plaid purple bags contain 1 light lime bag.
clear purple bags contain 3 vibrant white bags.
dark yellow bags contain 2 pale olive bags, 4 pale cyan bags, 5 bright teal bags.
muted beige bags contain 2 posh lime bags, 5 shiny gray bags, 2 dull blue bags.
vibrant orange bags contain 5 posh crimson bags, 4 light chartreuse bags.
light magenta bags contain 2 plaid maroon bags, 1 posh beige bag, 5 pale salmon bags.
dotted crimson bags contain 5 dark chartreuse bags.
striped coral bags contain 2 dim aqua bags.
striped aqua bags contain 3 posh salmon bags, 3 dull red bags.
mirrored salmon bags contain 5 bright red bags, 2 light green bags, 3 clear black bags, 5 posh brown bags.
posh white bags contain 4 drab violet bags, 2 dotted silver bags.
posh blue bags contain 4 dull maroon bags, 3 vibrant coral bags.
dim orange bags contain 2 dull olive bags.
shiny teal bags contain 1 faded tomato bag, 4 muted violet bags.
mirrored maroon bags contain 3 dull blue bags.
dark lavender bags contain 1 drab red bag, 3 shiny indigo bags, 4 faded beige bags, 1 drab turquoise bag.
shiny olive bags contain 3 dark violet bags, 1 striped gold bag, 2 mirrored lime bags.
bright violet bags contain 2 wavy bronze bags, 3 drab olive bags, 5 mirrored olive bags, 2 wavy lavender bags.
clear olive bags contain 5 faded turquoise bags.
mirrored lavender bags contain 1 light white bag, 4 light purple bags, 3 wavy lavender bags, 2 shiny lime bags.
pale turquoise bags contain 4 dark tan bags.
shiny salmon bags contain 1 shiny gold bag, 5 drab turquoise bags.
vibrant gray bags contain 3 posh brown bags.
dark indigo bags contain 1 mirrored black bag, 5 dull beige bags, 4 shiny beige bags, 3 drab lavender bags.
light teal bags contain 5 dark olive bags, 5 vibrant chartreuse bags, 3 plaid salmon bags, 5 light yellow bags.
clear violet bags contain 3 light crimson bags.
clear tan bags contain 3 striped orange bags, 4 wavy lavender bags, 3 striped silver bags.
clear bronze bags contain 2 plaid beige bags.
clear gray bags contain 4 dotted cyan bags, 4 vibrant plum bags.
drab cyan bags contain 1 light aqua bag, 1 drab teal bag, 3 bright orange bags, 3 dark white bags.
plaid beige bags contain 3 dull green bags.
wavy gold bags contain 4 shiny olive bags, 3 bright tan bags.
clear aqua bags contain 3 posh chartreuse bags, 4 drab silver bags, 5 clear gray bags.
bright chartreuse bags contain 2 light violet bags, 3 vibrant gray bags.
plaid black bags contain 2 posh gray bags.
light beige bags contain 4 dotted olive bags, 5 dull olive bags, 1 faded orange bag.
mirrored teal bags contain 4 mirrored aqua bags.
bright magenta bags contain 1 mirrored magenta bag, 3 bright blue bags, 1 vibrant blue bag, 2 drab gold bags.
dim maroon bags contain 4 light bronze bags, 5 clear violet bags.
light lime bags contain 4 plaid indigo bags.
posh lavender bags contain 4 dark brown bags.
clear beige bags contain 4 posh silver bags, 3 dull coral bags, 2 posh gray bags.
drab bronze bags contain 4 plaid maroon bags.
mirrored purple bags contain 3 dim magenta bags.
dark magenta bags contain 4 faded maroon bags, 1 drab crimson bag, 5 dotted brown bags, 2 bright teal bags.
dim brown bags contain 3 muted olive bags, 5 drab green bags, 1 mirrored olive bag.
dark plum bags contain 2 vibrant tan bags.
bright turquoise bags contain 1 mirrored aqua bag, 3 clear plum bags.
muted black bags contain 5 faded cyan bags, 5 pale tan bags, 2 dotted chartreuse bags.
dotted gray bags contain 3 posh plum bags.
vibrant black bags contain 2 vibrant magenta bags, 5 faded cyan bags.
mirrored cyan bags contain 2 clear cyan bags, 4 light aqua bags, 5 drab blue bags, 1 drab gold bag.
wavy purple bags contain 5 striped magenta bags, 3 clear maroon bags, 1 mirrored green bag, 1 pale black bag.
drab blue bags contain 3 mirrored lime bags, 1 mirrored blue bag.
clear maroon bags contain 5 bright orange bags.
shiny cyan bags contain 2 clear gray bags, 5 pale crimson bags.
pale cyan bags contain 2 wavy turquoise bags, 5 wavy salmon bags.
plaid gold bags contain 1 clear lavender bag, 1 bright beige bag.
mirrored lime bags contain 2 dull tan bags, 3 shiny beige bags.
drab green bags contain 1 vibrant yellow bag.
dull red bags contain 5 plaid blue bags, 5 clear brown bags, 3 pale salmon bags, 2 dark orange bags.
bright beige bags contain 4 dull silver bags, 5 vibrant brown bags, 4 drab red bags, 2 pale violet bags.
clear silver bags contain 4 drab indigo bags, 2 clear salmon bags.
posh bronze bags contain 5 bright indigo bags, 5 dotted purple bags, 1 dark violet bag, 2 dark orange bags.
posh salmon bags contain 5 bright red bags, 3 striped green bags, 3 dark brown bags.
clear cyan bags contain 5 dark chartreuse bags, 1 bright indigo bag, 4 pale yellow bags, 2 vibrant coral bags.
mirrored blue bags contain 2 vibrant white bags.
mirrored yellow bags contain 5 dotted gray bags, 4 dull maroon bags, 2 striped violet bags, 5 clear tomato bags.
striped teal bags contain 2 clear black bags, 3 pale coral bags.
faded orange bags contain 2 dark bronze bags.
mirrored indigo bags contain 3 light tomato bags, 2 shiny crimson bags.
pale green bags contain 4 light chartreuse bags.
plaid cyan bags contain 4 plaid fuchsia bags, 2 shiny teal bags, 3 dotted fuchsia bags, 3 dim red bags.
muted gold bags contain 2 dull tan bags, 1 faded bronze bag, 4 dull maroon bags.
wavy green bags contain 5 pale coral bags, 1 dull blue bag, 4 drab blue bags, 1 striped tan bag.
light chartreuse bags contain 4 striped brown bags, 5 plaid purple bags, 4 drab cyan bags, 3 dull plum bags.
dotted cyan bags contain 4 shiny black bags.
light purple bags contain no other bags.
dotted aqua bags contain 4 light gray bags, 2 light purple bags, 5 mirrored lime bags.
drab gold bags contain 2 bright green bags, 5 bright indigo bags.
posh gray bags contain 5 bright orange bags, 5 bright blue bags.
striped red bags contain 4 drab green bags, 1 clear cyan bag.
dotted bronze bags contain 5 light orange bags.
muted plum bags contain 2 bright black bags, 3 dotted tomato bags, 2 vibrant brown bags.
mirrored black bags contain 3 plaid chartreuse bags, 2 shiny indigo bags, 2 shiny beige bags.
drab lavender bags contain 5 drab cyan bags, 1 muted purple bag, 1 wavy red bag, 3 drab crimson bags.
vibrant turquoise bags contain 3 shiny beige bags, 3 striped brown bags, 5 dim teal bags.
muted tan bags contain 1 plaid purple bag, 3 shiny beige bags, 1 drab gold bag.
pale beige bags contain 5 bright silver bags.
wavy olive bags contain 4 dotted turquoise bags, 4 dull silver bags, 1 bright gold bag.
dim olive bags contain 5 light lavender bags, 4 shiny tomato bags, 4 clear cyan bags.
wavy salmon bags contain 4 bright aqua bags.
dotted gold bags contain 3 shiny red bags, 3 dull fuchsia bags.
shiny violet bags contain 3 dotted tomato bags, 1 drab coral bag.
striped plum bags contain 4 drab beige bags, 3 clear tan bags, 5 light aqua bags, 1 shiny fuchsia bag.
clear lavender bags contain 2 bright aqua bags, 3 dull silver bags, 3 bright green bags, 2 bright orange bags.
faded maroon bags contain 5 dark indigo bags, 1 posh fuchsia bag.
vibrant red bags contain 4 striped fuchsia bags, 3 drab orange bags, 1 clear brown bag, 1 plaid turquoise bag.
dull coral bags contain 2 dim teal bags, 3 faded bronze bags.
pale salmon bags contain 3 dull magenta bags, 1 light crimson bag.
dotted magenta bags contain 4 dull maroon bags, 2 bright lime bags, 4 plaid indigo bags, 4 faded cyan bags.
wavy gray bags contain 4 muted gray bags, 3 shiny magenta bags, 1 posh teal bag.
light red bags contain 4 shiny chartreuse bags.
dim blue bags contain 4 vibrant orange bags.
muted bronze bags contain 5 mirrored aqua bags, 4 dim green bags.
drab lime bags contain 1 drab cyan bag, 3 pale crimson bags, 4 bright green bags, 3 drab lavender bags.
light white bags contain 5 bright green bags.
bright teal bags contain 4 shiny brown bags, 4 dark silver bags.
striped beige bags contain 2 shiny magenta bags.
wavy magenta bags contain 5 pale bronze bags, 5 pale plum bags, 3 muted silver bags.
dark orange bags contain 1 drab tomato bag, 3 striped brown bags, 1 dim teal bag, 5 bright beige bags.
striped indigo bags contain 1 vibrant gold bag, 1 shiny green bag.
clear coral bags contain 2 shiny gray bags.
faded yellow bags contain 4 faded gold bags, 2 bright turquoise bags, 5 dark silver bags, 3 wavy coral bags.
dim plum bags contain 1 clear purple bag, 4 light brown bags.
mirrored turquoise bags contain 5 wavy indigo bags, 3 dark fuchsia bags, 5 plaid white bags, 2 dim turquoise bags.
posh black bags contain 2 striped black bags, 5 dim teal bags, 3 bright silver bags, 5 posh beige bags.
dotted fuchsia bags contain 1 faded turquoise bag, 2 shiny lavender bags, 4 posh salmon bags, 1 clear olive bag.
faded lavender bags contain 2 striped yellow bags, 1 posh lavender bag.
dim lime bags contain 2 wavy gray bags, 5 clear gray bags.
vibrant bronze bags contain 3 drab tomato bags, 5 bright tan bags.
dull plum bags contain 5 bright red bags, 4 dull magenta bags.
dim teal bags contain 4 light purple bags, 4 plaid lavender bags, 1 dull magenta bag.
dull yellow bags contain 4 vibrant orange bags, 1 dark tomato bag, 5 pale tan bags.
dull green bags contain 2 bright blue bags, 5 dull red bags.
light crimson bags contain 5 dull maroon bags, 4 muted gold bags.
dark black bags contain 1 dim silver bag, 3 plaid magenta bags.
bright lavender bags contain 4 muted fuchsia bags.
drab coral bags contain 4 shiny chartreuse bags, 3 posh yellow bags, 3 wavy indigo bags.
mirrored crimson bags contain 3 posh maroon bags, 5 striped olive bags, 3 mirrored magenta bags.
muted coral bags contain 3 wavy violet bags, 1 dotted chartreuse bag, 1 shiny beige bag.
vibrant gold bags contain 2 dull orange bags, 1 clear chartreuse bag.
wavy orange bags contain 5 dark bronze bags.
mirrored white bags contain 5 clear gold bags, 3 drab tomato bags, 4 dotted bronze bags, 3 striped orange bags.
clear gold bags contain 3 drab indigo bags, 4 wavy violet bags, 2 shiny salmon bags, 4 light brown bags.
shiny magenta bags contain 5 drab silver bags, 2 muted gold bags.
dim violet bags contain 1 posh lime bag, 4 shiny orange bags, 2 posh chartreuse bags.
striped olive bags contain 4 plaid indigo bags, 5 dim chartreuse bags, 4 clear lavender bags.
plaid gray bags contain 3 shiny gold bags, 2 dull coral bags.
clear crimson bags contain 4 shiny aqua bags, 3 light crimson bags, 5 dim chartreuse bags.
drab silver bags contain 1 dim teal bag, 3 faded cyan bags, 1 shiny indigo bag.
mirrored green bags contain 5 dotted lime bags, 4 pale cyan bags.
bright aqua bags contain no other bags.
bright plum bags contain 4 dim aqua bags, 2 dull crimson bags, 1 wavy maroon bag.
vibrant lavender bags contain 1 plaid tan bag, 3 vibrant brown bags, 3 drab gold bags, 4 faded red bags.
pale white bags contain 3 bright brown bags, 4 mirrored beige bags.
plaid lavender bags contain 1 dull magenta bag, 2 dull silver bags, 1 shiny indigo bag.
bright salmon bags contain 1 striped coral bag, 4 plaid lavender bags, 1 muted red bag, 1 drab red bag.
plaid olive bags contain 5 faded turquoise bags, 4 dim green bags, 2 striped beige bags.
wavy plum bags contain 1 clear lavender bag, 2 faded brown bags.
clear fuchsia bags contain 1 muted bronze bag.
wavy turquoise bags contain 5 shiny lime bags, 1 drab olive bag, 4 dim white bags, 1 dotted gray bag.
vibrant aqua bags contain 2 faded lavender bags.
dotted white bags contain 3 muted crimson bags, 5 mirrored white bags, 1 mirrored fuchsia bag.
bright purple bags contain 2 dotted chartreuse bags, 4 posh cyan bags, 3 bright plum bags.
light aqua bags contain 1 plaid lavender bag, 3 wavy coral bags, 5 shiny indigo bags.
drab yellow bags contain 4 shiny teal bags, 2 dotted green bags, 5 vibrant silver bags, 3 dotted turquoise bags.
mirrored olive bags contain 1 dull plum bag.
light olive bags contain 1 shiny coral bag, 4 drab white bags, 3 dim turquoise bags, 4 dull gold bags.
shiny indigo bags contain no other bags.
dull gold bags contain 3 dark indigo bags.
bright tomato bags contain 5 muted blue bags.
faded purple bags contain 4 bright orange bags, 2 faded violet bags.
drab magenta bags contain 3 wavy lavender bags, 2 drab cyan bags, 2 clear beige bags, 4 bright indigo bags.
striped lime bags contain 4 light tan bags.
light gold bags contain 2 pale plum bags.
striped black bags contain 1 plaid salmon bag, 2 plaid beige bags, 4 dotted teal bags, 2 posh chartreuse bags.
faded tomato bags contain 2 striped yellow bags, 4 muted red bags.
dull fuchsia bags contain 5 dotted olive bags, 2 muted purple bags.
pale purple bags contain 4 posh silver bags, 4 wavy yellow bags.
bright olive bags contain 5 shiny fuchsia bags, 5 dull crimson bags, 5 drab red bags, 5 posh turquoise bags.
vibrant fuchsia bags contain 1 vibrant beige bag, 5 shiny magenta bags.
faded turquoise bags contain 5 light lime bags, 4 dark white bags.
plaid orange bags contain 5 vibrant coral bags, 4 light crimson bags, 4 plaid chartreuse bags, 1 dull green bag.
posh indigo bags contain 3 wavy green bags, 2 shiny orange bags, 5 faded violet bags, 2 dotted coral bags.
mirrored red bags contain 4 mirrored olive bags, 1 dark silver bag, 1 dull red bag.
dim salmon bags contain 1 striped salmon bag, 5 faded gray bags.
dim cyan bags contain 3 wavy olive bags, 5 drab purple bags, 3 mirrored bronze bags.
light blue bags contain 2 striped bronze bags, 4 dull white bags, 1 posh bronze bag.
dull turquoise bags contain 4 striped red bags, 1 light lavender bag, 5 plaid bronze bags, 1 mirrored brown bag.
vibrant coral bags contain 1 bright orange bag.
striped cyan bags contain 2 dark white bags, 4 drab red bags, 2 plaid salmon bags.
muted tomato bags contain 4 drab red bags, 3 vibrant silver bags, 4 clear fuchsia bags, 3 wavy white bags.
dotted red bags contain 1 light blue bag.
dark beige bags contain 2 posh lime bags, 3 striped black bags.
dark cyan bags contain 1 dim chartreuse bag, 2 shiny beige bags, 4 dotted magenta bags, 4 light chartreuse bags.
dull lime bags contain 3 muted chartreuse bags.
light brown bags contain 3 mirrored brown bags.
vibrant magenta bags contain 1 dim green bag.
shiny brown bags contain 5 bright brown bags, 3 faded cyan bags, 5 clear tan bags, 2 plaid maroon bags.
drab purple bags contain 1 shiny indigo bag, 4 striped yellow bags.

51
2020/d08/ex1/ex1.py Executable file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env python
import sys
from typing import List, Tuple
def run(code: List[Tuple[str, int]]) -> int:
accumulator = 0
rip = 0
def acc(val: int) -> None:
nonlocal accumulator
nonlocal rip
accumulator += val
rip += 1
def nop(val: int) -> None:
nonlocal rip
rip += 1
def jmp(val: int) -> None:
nonlocal rip
rip += val
instrs = {
"acc": acc,
"jmp": jmp,
"nop": nop,
}
seen = set()
while rip not in seen:
seen |= {rip}
func = instrs[code[rip][0]]
func(code[rip][1])
return accumulator
def solve(raw: List[str]) -> int:
return run([(line[:3], int(line[3:])) for line in raw])
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

675
2020/d08/ex1/input Normal file
View file

@ -0,0 +1,675 @@
acc -8
jmp +5
acc +0
acc +44
acc +42
jmp +324
acc -17
jmp +1
acc -17
jmp +51
acc -13
acc +4
jmp +1
nop +608
jmp +274
acc -17
jmp +169
acc +28
nop +508
jmp +1
jmp +570
acc +22
acc -14
jmp +377
acc -13
acc +27
jmp +474
acc -5
jmp +1
acc +12
jmp +37
jmp +184
acc +36
acc +32
acc -8
jmp +465
acc -13
acc +18
jmp +169
acc +20
acc +26
acc +23
jmp +333
jmp +584
acc +9
acc +28
acc +28
nop +571
jmp +143
acc +39
acc +39
acc -16
jmp +361
acc +48
acc +3
acc +15
nop +4
jmp +504
acc +6
jmp +285
acc +26
acc +33
jmp +1
acc +36
jmp +577
acc +36
jmp +6
nop +498
acc +42
jmp +496
acc +10
jmp +74
acc +17
acc +16
acc +30
jmp +254
acc -3
acc +16
acc -2
nop +106
jmp +541
acc -15
jmp +579
jmp +165
acc +22
acc -6
acc +29
acc -19
jmp +342
acc -19
jmp +340
acc +13
acc +25
acc +29
jmp +269
acc -14
acc +27
acc +41
acc +49
jmp +181
nop +350
jmp +1
nop +437
acc +34
jmp +494
acc +19
acc +2
acc +44
jmp +558
acc +10
jmp +44
nop +4
nop -80
nop +540
jmp +16
acc +28
jmp +14
acc +13
nop +399
acc +29
nop -60
jmp -6
acc +41
acc +30
jmp +232
acc +28
nop +495
acc +15
acc +48
jmp +157
nop +483
jmp -59
acc +5
acc +30
acc +30
acc +2
jmp +349
acc +11
acc +27
acc +1
jmp +367
acc +8
acc +45
acc +11
jmp +171
jmp -113
acc +48
jmp -38
acc +12
jmp +145
acc +8
nop +29
nop +319
jmp +154
nop +166
jmp +395
nop +15
jmp +237
acc +22
acc +3
acc +42
acc +1
jmp +288
jmp -63
nop +489
acc +33
jmp +247
jmp +1
acc -8
acc +9
jmp +413
acc -17
acc +3
acc +3
jmp +432
nop -17
acc +36
nop +198
acc +45
jmp +109
nop +242
acc +40
acc +11
jmp +448
jmp +437
acc +3
acc +49
acc +27
jmp +221
nop +158
jmp +143
acc +50
jmp -70
acc +46
acc +8
acc +35
acc -3
jmp +104
acc +11
acc +0
jmp +34
nop +132
jmp +425
jmp +219
acc -12
acc +48
jmp +21
jmp +434
acc +30
acc +1
acc +40
jmp +435
jmp +132
acc +40
jmp +236
jmp +179
jmp -149
acc +25
acc +40
acc -9
acc +49
jmp +445
nop +399
acc -14
nop +374
acc +0
jmp +152
acc +39
nop +322
acc +49
nop +117
jmp -19
acc +24
jmp +385
acc +17
acc +39
acc +44
acc -8
jmp -58
acc -18
nop -76
jmp +66
acc +14
jmp +427
acc +11
acc +47
acc +9
jmp +1
acc +42
jmp -7
acc -16
acc -13
jmp +409
acc +1
acc +35
acc +34
jmp +371
acc +24
acc +46
acc -4
jmp +367
acc +19
acc +27
acc -8
acc +41
jmp -184
nop -185
acc +23
acc -8
acc +35
jmp -9
acc -7
nop -101
nop +121
acc +37
jmp -72
acc +24
jmp +1
nop -124
jmp +163
acc +37
acc -12
jmp +331
acc -12
acc +1
jmp +232
jmp -233
jmp -72
acc +28
jmp +169
acc +43
acc +18
nop +108
jmp -184
acc -4
acc -10
nop +317
acc +48
jmp +173
nop +45
jmp -73
acc +35
jmp +198
acc -15
acc +46
acc +31
jmp +41
nop +169
jmp +1
nop -92
nop -271
jmp -113
jmp +1
nop -42
jmp +42
nop -283
acc +22
nop +200
jmp -17
jmp +1
acc +49
nop +35
nop -185
jmp +298
acc +1
jmp +1
nop +301
acc +19
jmp -34
jmp +163
jmp +1
acc +49
jmp -115
jmp -62
acc +8
acc +5
acc -6
jmp -146
acc -4
nop -202
acc +47
jmp -114
acc +8
jmp +57
acc +37
jmp +61
jmp +267
acc +2
acc +28
nop -20
jmp -186
acc +24
nop +269
acc +48
acc +45
jmp -22
acc +11
acc +36
jmp -267
acc +7
nop -45
nop -231
jmp +32
nop +220
acc +19
jmp -250
acc +33
jmp -169
acc +45
acc -13
acc +0
acc +44
jmp +6
acc +42
jmp +84
acc +48
jmp -332
jmp +213
acc -16
acc +31
acc +17
acc +3
jmp -75
jmp +1
acc +11
acc +4
jmp -271
acc -12
nop +97
nop +11
jmp -43
acc +30
jmp +1
jmp +49
jmp -379
nop -51
acc +0
acc -8
nop -191
jmp -346
jmp -255
acc +2
acc +21
acc -16
nop +217
jmp -30
acc +31
jmp -270
jmp -324
jmp +130
acc +49
nop +179
jmp -37
acc +11
acc +15
acc +29
acc +17
jmp -237
acc +47
acc -13
acc +6
jmp +169
nop +54
acc -12
jmp -233
nop +33
acc +17
acc +14
acc +21
jmp -275
acc -8
acc +1
nop +229
jmp +1
jmp +119
jmp -193
nop +217
jmp +95
acc -2
acc +1
acc +41
jmp -332
acc +44
nop -343
acc +23
jmp -165
acc +7
acc -12
nop -339
jmp +9
nop -390
acc -17
acc +43
jmp -138
nop -247
acc +42
acc +0
jmp +170
acc +48
jmp -139
acc +6
acc +13
acc +35
jmp -85
nop -117
jmp -307
acc +25
acc -10
acc -14
acc +0
jmp -355
jmp +102
acc -8
acc +47
acc +36
jmp +42
acc +33
acc +17
acc +46
jmp -331
jmp +1
acc -11
jmp +1
acc +27
jmp +147
acc -14
nop -28
acc +32
jmp -482
acc +11
nop -390
jmp -485
acc -12
acc +37
acc +33
acc +28
jmp -32
acc +42
acc -11
jmp -460
acc +36
acc +6
acc +39
jmp +80
nop +123
acc -13
jmp -97
acc +25
acc +46
acc +13
nop -450
jmp +84
acc +3
nop -260
jmp +1
acc +22
jmp -510
acc -4
acc +17
acc -19
jmp -420
acc -14
acc +26
acc +29
acc +17
jmp -458
acc -10
acc +23
nop -2
jmp -196
acc -5
jmp -416
acc +49
jmp -165
acc +4
acc +7
acc +20
nop -217
jmp +103
jmp +5
acc -1
acc +2
jmp +1
jmp +84
acc -14
jmp -518
jmp +1
acc +30
acc +21
jmp -202
nop -18
jmp -344
jmp -88
nop -472
acc -5
acc +13
jmp -295
nop -315
acc +41
nop -317
jmp -299
nop +105
jmp -86
acc +7
jmp -226
nop -277
acc +21
acc +13
acc +47
jmp -283
acc -11
acc -1
jmp -408
acc +47
nop -553
acc +37
acc -11
jmp -468
acc +43
nop -299
acc +40
acc +2
jmp -275
acc +24
acc -14
acc +13
acc +36
jmp -249
acc +35
jmp -45
acc +47
acc +31
acc -19
jmp -151
jmp -33
acc +6
jmp -160
jmp -553
acc +25
jmp +1
nop -267
jmp -430
acc +23
nop +63
acc +37
jmp -434
nop -579
jmp +11
acc +25
acc -17
acc +22
acc +27
jmp +15
jmp -546
acc -4
acc +41
acc +0
jmp -261
acc +20
jmp -404
jmp -408
acc +26
jmp -464
acc +34
nop -80
acc -12
jmp -43
jmp -410
acc -13
acc -3
jmp -310
nop -433
acc -7
acc -11
acc +9
jmp -29
nop -564
acc -5
acc -16
acc +36
jmp -587
jmp -115
acc +24
acc +35
nop -638
jmp -573
acc +31
acc +14
jmp -609
acc +25
acc -10
acc +18
jmp -308
acc +25
acc +33
acc +21
acc -12
jmp -172
nop -37
acc +12
jmp -316
acc +41
acc +14
jmp -415
acc +40
jmp -112
jmp -613
acc +26
nop -151
jmp -471
acc +50
acc +16
nop -119
acc +46
jmp +1

62
2020/d08/ex2/ex2.py Executable file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env python
import sys
from copy import deepcopy
from typing import List, Tuple
def run(code: List[Tuple[str, int]]) -> Tuple[int, bool]:
accumulator = 0
rip = 0
def acc(val: int) -> None:
nonlocal accumulator
nonlocal rip
accumulator += val
rip += 1
def nop(val: int) -> None:
nonlocal rip
rip += 1
def jmp(val: int) -> None:
nonlocal rip
rip += val
instrs = {
"acc": acc,
"jmp": jmp,
"nop": nop,
}
seen = set()
while rip not in seen and rip < len(code):
seen |= {rip}
func = instrs[code[rip][0]]
func(code[rip][1])
return accumulator, rip == len(code)
def solve(raw: List[str]) -> int:
code = [(line[:3], int(line[3:])) for line in raw]
lut = {"jmp": "nop", "nop": "jmp"}
for i in range(len(code)):
if code[i][0] not in lut:
continue
new_code = deepcopy(code)
new_code[i] = lut[new_code[i][0]], new_code[i][1]
val, halted = run(new_code)
if halted:
return val
assert False # Sanity check
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

675
2020/d08/ex2/input Normal file
View file

@ -0,0 +1,675 @@
acc -8
jmp +5
acc +0
acc +44
acc +42
jmp +324
acc -17
jmp +1
acc -17
jmp +51
acc -13
acc +4
jmp +1
nop +608
jmp +274
acc -17
jmp +169
acc +28
nop +508
jmp +1
jmp +570
acc +22
acc -14
jmp +377
acc -13
acc +27
jmp +474
acc -5
jmp +1
acc +12
jmp +37
jmp +184
acc +36
acc +32
acc -8
jmp +465
acc -13
acc +18
jmp +169
acc +20
acc +26
acc +23
jmp +333
jmp +584
acc +9
acc +28
acc +28
nop +571
jmp +143
acc +39
acc +39
acc -16
jmp +361
acc +48
acc +3
acc +15
nop +4
jmp +504
acc +6
jmp +285
acc +26
acc +33
jmp +1
acc +36
jmp +577
acc +36
jmp +6
nop +498
acc +42
jmp +496
acc +10
jmp +74
acc +17
acc +16
acc +30
jmp +254
acc -3
acc +16
acc -2
nop +106
jmp +541
acc -15
jmp +579
jmp +165
acc +22
acc -6
acc +29
acc -19
jmp +342
acc -19
jmp +340
acc +13
acc +25
acc +29
jmp +269
acc -14
acc +27
acc +41
acc +49
jmp +181
nop +350
jmp +1
nop +437
acc +34
jmp +494
acc +19
acc +2
acc +44
jmp +558
acc +10
jmp +44
nop +4
nop -80
nop +540
jmp +16
acc +28
jmp +14
acc +13
nop +399
acc +29
nop -60
jmp -6
acc +41
acc +30
jmp +232
acc +28
nop +495
acc +15
acc +48
jmp +157
nop +483
jmp -59
acc +5
acc +30
acc +30
acc +2
jmp +349
acc +11
acc +27
acc +1
jmp +367
acc +8
acc +45
acc +11
jmp +171
jmp -113
acc +48
jmp -38
acc +12
jmp +145
acc +8
nop +29
nop +319
jmp +154
nop +166
jmp +395
nop +15
jmp +237
acc +22
acc +3
acc +42
acc +1
jmp +288
jmp -63
nop +489
acc +33
jmp +247
jmp +1
acc -8
acc +9
jmp +413
acc -17
acc +3
acc +3
jmp +432
nop -17
acc +36
nop +198
acc +45
jmp +109
nop +242
acc +40
acc +11
jmp +448
jmp +437
acc +3
acc +49
acc +27
jmp +221
nop +158
jmp +143
acc +50
jmp -70
acc +46
acc +8
acc +35
acc -3
jmp +104
acc +11
acc +0
jmp +34
nop +132
jmp +425
jmp +219
acc -12
acc +48
jmp +21
jmp +434
acc +30
acc +1
acc +40
jmp +435
jmp +132
acc +40
jmp +236
jmp +179
jmp -149
acc +25
acc +40
acc -9
acc +49
jmp +445
nop +399
acc -14
nop +374
acc +0
jmp +152
acc +39
nop +322
acc +49
nop +117
jmp -19
acc +24
jmp +385
acc +17
acc +39
acc +44
acc -8
jmp -58
acc -18
nop -76
jmp +66
acc +14
jmp +427
acc +11
acc +47
acc +9
jmp +1
acc +42
jmp -7
acc -16
acc -13
jmp +409
acc +1
acc +35
acc +34
jmp +371
acc +24
acc +46
acc -4
jmp +367
acc +19
acc +27
acc -8
acc +41
jmp -184
nop -185
acc +23
acc -8
acc +35
jmp -9
acc -7
nop -101
nop +121
acc +37
jmp -72
acc +24
jmp +1
nop -124
jmp +163
acc +37
acc -12
jmp +331
acc -12
acc +1
jmp +232
jmp -233
jmp -72
acc +28
jmp +169
acc +43
acc +18
nop +108
jmp -184
acc -4
acc -10
nop +317
acc +48
jmp +173
nop +45
jmp -73
acc +35
jmp +198
acc -15
acc +46
acc +31
jmp +41
nop +169
jmp +1
nop -92
nop -271
jmp -113
jmp +1
nop -42
jmp +42
nop -283
acc +22
nop +200
jmp -17
jmp +1
acc +49
nop +35
nop -185
jmp +298
acc +1
jmp +1
nop +301
acc +19
jmp -34
jmp +163
jmp +1
acc +49
jmp -115
jmp -62
acc +8
acc +5
acc -6
jmp -146
acc -4
nop -202
acc +47
jmp -114
acc +8
jmp +57
acc +37
jmp +61
jmp +267
acc +2
acc +28
nop -20
jmp -186
acc +24
nop +269
acc +48
acc +45
jmp -22
acc +11
acc +36
jmp -267
acc +7
nop -45
nop -231
jmp +32
nop +220
acc +19
jmp -250
acc +33
jmp -169
acc +45
acc -13
acc +0
acc +44
jmp +6
acc +42
jmp +84
acc +48
jmp -332
jmp +213
acc -16
acc +31
acc +17
acc +3
jmp -75
jmp +1
acc +11
acc +4
jmp -271
acc -12
nop +97
nop +11
jmp -43
acc +30
jmp +1
jmp +49
jmp -379
nop -51
acc +0
acc -8
nop -191
jmp -346
jmp -255
acc +2
acc +21
acc -16
nop +217
jmp -30
acc +31
jmp -270
jmp -324
jmp +130
acc +49
nop +179
jmp -37
acc +11
acc +15
acc +29
acc +17
jmp -237
acc +47
acc -13
acc +6
jmp +169
nop +54
acc -12
jmp -233
nop +33
acc +17
acc +14
acc +21
jmp -275
acc -8
acc +1
nop +229
jmp +1
jmp +119
jmp -193
nop +217
jmp +95
acc -2
acc +1
acc +41
jmp -332
acc +44
nop -343
acc +23
jmp -165
acc +7
acc -12
nop -339
jmp +9
nop -390
acc -17
acc +43
jmp -138
nop -247
acc +42
acc +0
jmp +170
acc +48
jmp -139
acc +6
acc +13
acc +35
jmp -85
nop -117
jmp -307
acc +25
acc -10
acc -14
acc +0
jmp -355
jmp +102
acc -8
acc +47
acc +36
jmp +42
acc +33
acc +17
acc +46
jmp -331
jmp +1
acc -11
jmp +1
acc +27
jmp +147
acc -14
nop -28
acc +32
jmp -482
acc +11
nop -390
jmp -485
acc -12
acc +37
acc +33
acc +28
jmp -32
acc +42
acc -11
jmp -460
acc +36
acc +6
acc +39
jmp +80
nop +123
acc -13
jmp -97
acc +25
acc +46
acc +13
nop -450
jmp +84
acc +3
nop -260
jmp +1
acc +22
jmp -510
acc -4
acc +17
acc -19
jmp -420
acc -14
acc +26
acc +29
acc +17
jmp -458
acc -10
acc +23
nop -2
jmp -196
acc -5
jmp -416
acc +49
jmp -165
acc +4
acc +7
acc +20
nop -217
jmp +103
jmp +5
acc -1
acc +2
jmp +1
jmp +84
acc -14
jmp -518
jmp +1
acc +30
acc +21
jmp -202
nop -18
jmp -344
jmp -88
nop -472
acc -5
acc +13
jmp -295
nop -315
acc +41
nop -317
jmp -299
nop +105
jmp -86
acc +7
jmp -226
nop -277
acc +21
acc +13
acc +47
jmp -283
acc -11
acc -1
jmp -408
acc +47
nop -553
acc +37
acc -11
jmp -468
acc +43
nop -299
acc +40
acc +2
jmp -275
acc +24
acc -14
acc +13
acc +36
jmp -249
acc +35
jmp -45
acc +47
acc +31
acc -19
jmp -151
jmp -33
acc +6
jmp -160
jmp -553
acc +25
jmp +1
nop -267
jmp -430
acc +23
nop +63
acc +37
jmp -434
nop -579
jmp +11
acc +25
acc -17
acc +22
acc +27
jmp +15
jmp -546
acc -4
acc +41
acc +0
jmp -261
acc +20
jmp -404
jmp -408
acc +26
jmp -464
acc +34
nop -80
acc -12
jmp -43
jmp -410
acc -13
acc -3
jmp -310
nop -433
acc -7
acc -11
acc +9
jmp -29
nop -564
acc -5
acc -16
acc +36
jmp -587
jmp -115
acc +24
acc +35
nop -638
jmp -573
acc +31
acc +14
jmp -609
acc +25
acc -10
acc +18
jmp -308
acc +25
acc +33
acc +21
acc -12
jmp -172
nop -37
acc +12
jmp -316
acc +41
acc +14
jmp -415
acc +40
jmp -112
jmp -613
acc +26
nop -151
jmp -471
acc +50
acc +16
nop -119
acc +46
jmp +1

32
2020/d09/ex1/ex1.py Executable file
View file

@ -0,0 +1,32 @@
#!/usr/bin/env python
import itertools
import sys
from typing import List
def find_invalid(nums: List[int]) -> int:
for i in range(25, len(nums)):
num = nums[i]
found = False
for lhs, rhs in itertools.combinations(nums[i - 25 : i], 2):
if lhs + rhs == num:
found = True
break
if not found:
return num
assert False # Sanity check
def solve(raw: List[str]) -> int:
return find_invalid([int(line) for line in raw])
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

1000
2020/d09/ex1/input Normal file

File diff suppressed because it is too large Load diff

42
2020/d09/ex2/ex2.py Executable file
View file

@ -0,0 +1,42 @@
#!/usr/bin/env python
import itertools
import sys
from typing import List
def find_invalid(nums: List[int]) -> int:
for i in range(25, len(nums)):
num = nums[i]
found = False
for lhs, rhs in itertools.combinations(nums[i - 25 : i], 2):
if lhs + rhs == num:
found = True
break
if not found:
return num
assert False # Sanity check
def find_weakness(nums: List[int], invalid: int) -> int:
for i in range(len(nums) - 2):
for j in range(i + 2, len(nums)):
if sum(nums[i:j]) == invalid:
return min(nums[i:j]) + max(nums[i:j])
assert False # Sanity check((
def solve(raw: List[str]) -> int:
nums = [int(line) for line in raw]
invalid = find_invalid(nums)
return find_weakness(nums, invalid)
def main() -> None:
input = [line.strip() for line in sys.stdin.readlines()]
print(solve(input))
if __name__ == "__main__":
main()

Some files were not shown because too many files have changed in this diff Show more