advent of code 2025 in ts and nix

feat: add vis for day 10

dunkirk.sh 93a01046 b9ac8f35

verified
Changed files
+1828
scripts
shared
vis
+10
scripts/generate-vis.ts
···
description:
"3D visualization of junction boxes being connected by their shortest distances. Watch circuits form as connections merge isolated boxes into larger groups.",
},
};
const dayCards = days
···
description:
"3D visualization of junction boxes being connected by their shortest distances. Watch circuits form as connections merge isolated boxes into larger groups.",
},
+
"09": {
+
title: "Movie Theater Floor",
+
description:
+
"Find the largest rectangle using red tiles as opposite corners. Part 1 allows any rectangle, Part 2 requires rectangles to only contain red/green tiles.",
+
},
+
"10": {
+
title: "Factory Machines",
+
description:
+
"Configure indicator lights by pressing buttons that toggle specific lights. Find the minimum number of button presses to match the target configuration.",
+
},
};
const dayCards = days
+197
shared/10/input.txt
···
···
+
[...###.#.#] (1,8) (0,4,5,6) (2,3,4,5,6,7,8) (5) (0,3,5) (0,1,5,6,7,9) (0,7,9) (0,1,2,3,5,6,8,9) (0,1,2,3,4,5,7,8,9) (0,2,4,6,7,8,9) (1,2,3,4,6,7,8,9) (0,9) {65,41,48,35,50,67,76,68,55,61}
+
[##.#..] (0,2,3,5) (0,2,3,4) (0,1,2,4) (1,4) (2,3,4,5) (1,4,5) (0,3,4) (3) {56,191,62,82,236,212}
+
[...#.] (2,3,4) (1,2) (1,2,3,4) (0,2,3) (3) (0,3,4) {194,25,212,218,39}
+
[###..] (1,2) (1,2,3) (3,4) (0,1,2) (1,3,4) {12,52,35,43,28}
+
[#..####] (0,3,4,5,6) (0,1,3,5,6) (0,1,2,6) (0,3) (0,1,2,3) (4,5) (3,4) {47,46,31,136,104,19,27}
+
[#.#.#] (0,1,2) (1,2,3) (0,2,3) (1,2) (0,4) (1,3) {35,44,50,27,10}
+
[.#...###.] (4,5,6) (3,5,6) (0,2,4,6) (0,2,6,8) (0,1,8) (1,3) (0,1,2,4,5,7,8) (2,5,7) {39,33,32,11,41,35,37,15,29}
+
[.#.####] (0,1) (0,4,5,6) (1,3,4,5) (1,5) (1,2,3) (1,2,3,6) (0,1,3,4,6) {43,87,30,61,37,26,44}
+
[.######.] (0,3,4,5,7) (1,2,4,5,6,7) (1,2,3,4,6,7) (0,1,2) (5,7) (0,1,2,3,4,6) (0,4,5) (2,3) (0,2,3,4,5,7) (0,1,5,7) {34,43,49,20,33,47,21,47}
+
[.#####] (0,3) (0,1,3,5) (1,2,3,4,5) (2) (0,1,2) {34,170,162,185,153,168}
+
[.#.#] (1,3) (0,2,3) {154,10,154,164}
+
[..#.##] (0,3,4) (2,4,5) (0,1,3,4,5) (0,1,3,5) {28,12,2,28,23,14}
+
[...#.] (1,2,3,4) (3) (1,2,4) (0,3) (1,4) {168,22,12,188,22}
+
[##...] (1,2,4) (2,3) (2,3,4) (1,2) (1,2,3) (0,2) (4) {3,30,36,15,11}
+
[..##] (1) (1,2) (2,3) (2) (0,1,3) (0,3) {11,11,143,25}
+
[.###..#..] (1,2,4,5,7,8) (0,3,4,5,7,8) (1,3,7,8) (5,7) (6) (0,1,3,4,6) (0,1,2,4,5,6,7,8) (1,3,4,6,7) (0,2,3,4,7,8) (1,5,6) (3,4,5,6,7,8) {49,151,36,57,71,160,141,79,63}
+
[.#.#] (1,3) (2,3) (1,2) (0,1) (0,1,3) {23,48,18,47}
+
[.#......#] (0,2,4,6) (1,4,5) (0,2,3) (0,2,4,7,8) (1,3,5,6,7,8) (3,7) (2,3,4,7,8) (1,8) (0,2) {42,20,228,213,224,19,14,205,201}
+
[#..#.] (4) (0,1,3) (2,3,4) (1) (0,3) (3,4) (1,2,4) {14,29,10,18,29}
+
[.#####.#] (0,1,5,7) (0,4,5,6,7) (2,6) (2,3,5) (1,4,5) (3,5,7) (1,2,3,4,5,6,7) {13,42,24,35,37,68,25,45}
+
[###.###.#] (4,6,7) (2,4,6,7) (0,1,4,5) (2,3,4,5,6,7,8) (1,8) (1,2,3,4,6,8) (2,5,6) (0,2,3,5,6,8) (0,5,6,7,8) (1,2,4,6,8) {27,15,61,25,57,58,94,57,47}
+
[##.##....] (0,1,2,5,6,7,8) (0,1,2,3,6,7) (0,1,2,6,7) (2,3,6) (0,3,4,7,8) (0,1,2,4,6) (5,7,8) (4,6,7) {47,45,61,37,32,209,77,249,211}
+
[.##.##.#.#] (2,4,7,9) (1,4,5,8) (0,1,3,5) (1,4,5) (7) (1,2,8,9) (2,3,7,8) (0,1,2,3,4,7,8) (0,5) (0,2,3) (1,2,5,6,7,8,9) (0,1,2,3,5,9) (4,6,7,9) {69,76,81,72,49,58,6,51,46,40}
+
[##..] (0,2) (0,1,3) (0,1) {26,6,20,2}
+
[.#.#.#.] (0,1,6) (0,3,4) (1,2,3,6) (1,2,3,4,5) (1,2,3,5,6) (0,1,2,3) {21,33,28,34,7,7,22}
+
[#..##.####] (8) (3,5) (1,3,4,6) (4,5,7,8) (2,3,4,6,9) (0,1,4,6,7,9) (1,2,3,4,5,6) (1,4,5,6,7) (1,5,6,7) (6,9) (3,6) (0,1,2,3,4,5,8,9) {25,161,35,166,175,74,190,42,29,50}
+
[#..#.] (0,2,4) (1,4) (0,3) {22,5,20,2,25}
+
[.......#..] (0,3,4,5) (2,3,5,6,8,9) (1,2,3,5,7,8) (0,1,3,4,7) (0,2,3,4,5,6,7) (1,2,5,6,7) (0,1,3,6,8,9) (0,2,6) (0,2) (0,1,3,4,5,7,8) {79,31,88,74,43,75,58,49,44,20}
+
[.##..###.] (0,2) (1,6) (7,8) (1,3,7) (2,3) (3,4,7,8) (0,2,3,4,5,7) (4,7) (1,2,5,6,7) (0,2,3,4,5,8) {19,38,37,33,26,30,21,65,31}
+
[###..#..] (5,6) (0,4) (0,1,2,4,5,7) (0,3,5) (1,2,3,5,6) (0,2) (0,1,2,4,7) (0,3,6) {55,49,51,38,32,53,23,32}
+
[..##.#] (1,5) (0,1,2,3,4) (0,1,3) (2,4) (0,3,4) (0,2,4,5) {122,133,27,118,28,20}
+
[#...#.#] (0,1,2,6) (1,3,6) (0,3,4,5,6) (1) (0,1,4,5,6) (0,4,5) (2,3,4,5,6) (2,3,4) {47,37,38,37,55,37,47}
+
[##.###] (0,1,3,4,5) (1,4) (0,5) (1,3,4,5) (1,2,3,5) (0,2,3,4,5) {36,43,22,54,47,57}
+
[.##...#..] (0,1,3,4,5,7) (0,1,2,3,4,6,8) (0,4,8) (1,5,6,7) (0,1,5,6,7,8) (0,2,4,5,7,8) (0,1,3,5,6) {78,68,23,32,40,77,62,58,53}
+
[..##.....] (0,4,6,7,8) (1,2,3,5,7) (3,6) (1,3,4) (0,1,2,4,5,6,7,8) (0,1,2,3,4,5) (0,5,6) (2,5,6) {34,44,55,49,35,59,55,33,18}
+
[.##.#.#..#] (1,2,3,6,8,9) (1,2,5,7,8) (3,7,9) (1,2,4,6,9) (1,2,4,6,8,9) (1,2,5,6,7,8,9) (0,2,5,6,7,8) (0,3,4,6,7,9) (0,2,5,6,7,8,9) {20,44,61,26,25,34,59,55,44,62}
+
[#.#.] (0,1,3) (0,2) {213,18,195,18}
+
[#..##.] (3,4) (0,1,2,5) (2,5) (0,2,3,4) (0,1,3,4,5) (0,5) {27,12,27,15,15,41}
+
[.##..] (0) (1,2,3) (0,4) (1,2) (0,1,2,3) (3,4) (1,3) {42,207,201,207,36}
+
[.##.#..] (1,2,3,4,5) (0,3) (2,3,4) (1,3,6) (1,2,4,5,6) (0,1,3,4) (0) {34,123,34,153,35,14,114}
+
[#.#.#.#] (1,3,5,6) (0,5) (3,6) (1,2,3,4) (0,2) {33,22,29,26,16,26,10}
+
[#...##...] (0,1,2,4,5,6,7) (0,1,2,8) (0,2,3,4,6,7,8) (0,2,3) (1,2,3,4,6,7,8) (0,1,2,3,5,6,8) (1,3,5,6) (1,2,4,5,6) (0,5,6,8) {53,48,74,47,55,29,61,48,42}
+
[##.#.] (1,3,4) (0,4) (1,4) (0,1,2,3) (1,2,4) {177,213,173,193,44}
+
[.#.#.##.#] (1,3,7) (8) (0,1) (4,5) (4,5,8) (0,3,4,5,6,7,8) (2,7) (2,4,6) (0,2,3) {22,15,30,9,21,9,15,17,24}
+
[#......#.#] (0,1,2,4,6,7,8) (1,3,7,9) (5,7) (0,2,4,6) (2,4,5,7,9) (3,5,7) (0,1,2,5,6,9) (0,7,8) {54,27,50,24,36,58,34,77,28,35}
+
[#.#..##] (0,1,3) (0,2) (1,2,4,6) (3,5) (5,6) (0,4,6) (0,1,3,5,6) (2,6) {33,28,31,20,26,14,44}
+
[#..##] (0,1) (2,3) (1,3,4) (0,1,4) {175,177,0,2,168}
+
[.###...##.] (8) (0,3,4,5,6,7,8,9) (0,4,5,9) (0,1,2,3,5,7,8) (2,3,4,5,6,7,9) (1,2,3,6,7,9) (0,1,2,3,4,5,7,8) (2,3,5,8,9) (6,8,9) (1,2,3,4,5,6,7,9) (1,4,6,8,9) (0,3,6,9) (0,2,3,7) {65,50,69,97,72,86,95,82,68,117}
+
[#..#.#....] (0,2,4,7) (1,8,9) (0,1,3,4,6,7,8,9) (8) (0,1,3,4,5,6,9) (1,3,5,6,7) (0,3,5,6,7) (1,3) (0,3,5) (0,1,4,8) (0,1,2,4,5,7,8,9) {80,81,27,53,70,31,38,56,62,53}
+
[#...] (0,1,2) (1,3) (1,2) (0,2) (2,3) {19,41,38,23}
+
[.##..] (1,2) (1,3,4) (0,3) {20,29,9,40,20}
+
[..#.#.] (3,4,5) (2,3,5) (0,1,2,5) (3,5) (0,1,2) (2,3,4,5) (2,3) {27,27,76,67,25,72}
+
[##.##...#] (7,8) (0,2,4,5,7,8) (1,4,6,7) (2,4,5,6) (2,3,4,5,6) (0,1,3,5,6,8) (1,5,7,8) (0,2,5,8) (0,1,3,6) (2,3,4,5,6,7,8) (0,2,3) {56,44,44,48,44,68,60,44,61}
+
[#..#.] (0,2,3,4) (0,1,2,3) (1,2,3) (2,4) {12,13,132,25,119}
+
[..#...#] (1,2,4) (2,3,4) (2) (0,1,4,5,6) (2,4) (0,1,2,4) (0,2,3,4,5) (0,2,4,5,6) (0,1,2,3,6) {58,42,71,22,64,34,49}
+
[..##.] (0,2,4) (0,1,2,3) (0,1,4) (1,4) (2,3,4) (1,2,4) {22,44,18,11,41}
+
[#.#.] (0,1,3) (0,2) {21,1,20,1}
+
[#...] (0,3) (0,1,3) (0,2,3) (1) (1,2,3) (2,3) {120,35,134,153}
+
[.#.##.#] (1,3,4,6) (0,1,2,4,5,6) (0,1,2,4,5) (0,2,6) (2,3,5) (4) {54,48,67,27,55,47,50}
+
[##.#] (0,2,3) (0,1,3) {18,17,1,18}
+
[#.##.....#] (0,2,3,9) (6,8) (1,6,7) (4,5,6) (0,1,3,4,8,9) (3,4,5,6,8) (0,3,7,8) (0,2,3) {22,19,19,28,16,15,36,20,12,1}
+
[##.#.] (0,2,3) (0,1,4) (1,3,4) (1,4) (0,1,3) (1,3) {19,62,1,36,42}
+
[#.###] (1,3,4) (0,2,3,4) (2,3) {12,19,30,49,31}
+
[...##] (0,1,4) (1,2,3,4) (0,2) (0,3) (3,4) (1,2) (0) {18,19,18,18,18}
+
[#..#..#.#] (0,1,4) (5,7,8) (2,5,6,7,8) (0,4,5,6) (0,2,3,4,6,8) (1,3,4,5,6,7) (0,2,3,5,6,7,8) (0,1,2,3,4,6,7) (1,2,3,6,7,8) (2,4,5,7) {209,187,45,48,215,71,78,64,43}
+
[##....#.] (2,3,4,7) (1,4,5) (0,3,4,5) (0,1,2,5,7) (1,4) (0,1,4,6) (0,3,4) (0,6,7) {30,38,108,107,138,10,17,108}
+
[..###.###.] (0,9) (1,7) (0,1,2,3,5,6) (2,5,7,8) (0,2,3,4,5,7,9) (1,2,3,4,5,7,8,9) (1,2,3,4,5,6) (0,1,2,5,6,8) (0,1,2,4,5,6,7,8) (0,1,2,5) (0,1,2,4,6,7,8,9) {82,105,103,33,55,85,74,77,79,37}
+
[#.#.#.##.] (1,2,3,4,5,6,7) (1,6,8) (2,3,5) (5,6) (1,2,4,6,7) (0,1,2,7,8) (0,2,3,4,5,7,8) (0,1,3,4,5,6,8) {37,45,79,49,42,52,30,59,40}
+
[#...##.] (0,2,3,4,5) (0,3,6) (0,4,5) (1,3,5,6) (1,2,4,5) (4,6) (0,2,3,4,5,6) {27,18,22,34,33,29,45}
+
[#..##.#.] (0,1,4) (0,5,7) (1,2,4,5,6) (2) (0,5) (3,4,6,7) (0,2,3,4,6) {24,171,185,10,181,178,176,7}
+
[#..#.##.] (0,3,4,6) (4,6) (0,4,5) (1,2,3,4,5,7) (0,1,2,3,6) (0,1,2,4,6,7) (1,2,3) (1,2,3,4) {62,61,61,57,84,21,65,22}
+
[#.#.##.] (0,1,2,4,5) (3,6) (1,2,4,5,6) (1,3,5,6) (0,1,6) (1,2) {16,149,136,27,17,25,38}
+
[#.#.#..#.#] (0,3,6,7,9) (0,2,3,5,6,7,8,9) (3,6,8) (0,2,5,6,9) (2,3,4,7) (0,1,2,4,5,6,7,8) (0,1,3,4,5,6,7,9) (0,1,2,3,7,9) (5,8,9) (2,5,8,9) (3) {54,41,64,92,37,43,52,67,47,59}
+
[##..#.] (3,4,5) (1,5) (1,2,4) (1,4) (1,2) (0,3,5) (0) {23,47,31,10,33,12}
+
[#..##.#] (2,4) (1,3,4,5) (0,1,5,6) (0,2,4,5,6) (0,1,4,5,6) {47,41,24,12,55,59,47}
+
[#.#.##.#] (0,1,2,4,5,7) (0,2,3,6,7) (0,3,4,5) (3,4,5,6) (0,1,3,5,6,7) (1,2,4,5,6,7) (0,2,3) (2,4,5,6,7) (1,7) {32,34,35,34,44,47,32,42}
+
[..#.#....#] (0,2,3,5,6,7,8,9) (1,3,4,5,6,7,8,9) (0,2,7,8,9) (5,6,9) (3) (0,1,4,5,9) (1,5,9) (0,1,2,3,4,5,8) (2,5) (4,8) {26,38,191,38,31,233,23,8,24,46}
+
[.#....#.#.] (2,3,4,8) (0,1,2,5,6,7,9) (0,2,3,4,7,8,9) (0,2,3,5,6,7,8,9) (1,3) (4,5,6,9) (0,3,4,5,6,7,8) (0,8,9) (3,4,5,7,8,9) (0,1,2,3,4,6,8,9) (1,2,5,6,7,8,9) (3,4,5) {70,55,62,73,59,77,79,59,69,100}
+
[#...###...] (0,3,6,9) (5,8,9) (1,2,3,4,6,8,9) (1,2,5,7) (0,1,2,3,4,6,7,8) (1,2,3,4,6,7,8,9) (3,5) (1,5,6,7,8,9) (4,5,6) (1,2,3,4,5,6,7,9) {33,65,60,67,57,30,75,48,63,62}
+
[#.##] (1,2) (0,1) (0,2,3) {8,22,16,1}
+
[##..##] (1,2,5) (0,1,2,3,5) (0,3,4) (0,2,4) {20,11,21,10,17,11}
+
[.#.#] (1,3) (0,2) (0,3) {21,10,9,22}
+
[#..##.##] (0,1,2,3,4,6,7) (3,4,7) (2,3,7) (2,3,4,5,7) (2,3,5,6) (2,3,6,7) (3,4) (1,3,7) (0,4,5,6) (2,3) {3,14,61,108,49,34,27,62}
+
[########..] (0,2,3,4,9) (0,3,6,7,8,9) (0,1,2,3,4,5,6,7) (4,5,7,9) (0,1,2,3,4,7,8,9) (0,2,3,4,6,7,8,9) (1,3,5,6,8,9) (0,1,4,5,8,9) (0,2,3) (1,8) (0,5,8) {58,39,41,60,41,33,38,48,46,47}
+
[#..#.#..#] (0,3,6,7) (3,4,6,7) (0,2,5) (0,5,8) (0,6) (0,1,2,3,4,5,7,8) (1,3,4,6,7,8) (0,3,5,8) (4,7) (0,1,3,4,7,8) {49,22,13,36,43,26,47,47,35}
+
[.#.....] (1,2,3,4,5) (1,2,3,4) (1,2,3,4,6) (0,2,4,6) (0,1,2,4,5) {6,29,33,27,33,18,8}
+
[##.###.#.#] (0,2,5,6,8) (1,2,3,4,5) (0,2,3,5,7,8,9) (0,1,2,4,5,6,9) (2,3,6,7,9) (0,1,2,3,4,5,7,9) (0,2,9) (2,3,4,7,9) {38,39,69,47,42,56,30,28,17,39}
+
[..##.#.] (0,1,3,4,5) (2,5) (0,1,4,5) (1,4,6) (0,3,4) {128,128,12,21,142,126,14}
+
[###.] (1,3) (0,2,3) (3) (0,1) (2) (1) {24,41,14,44}
+
[##.##...] (0,1,4,6,7) (0,1,3,4) (4,6) (0,2,3,4) (6,7) (3,5,6) (0,2,3,5,7) {38,20,18,31,42,23,54,42}
+
[#.#..] (0,2,3) (3,4) (0,3) (4) (1,2) (0,1) {42,175,174,42,14}
+
[.#######] (0,2,6) (0,1,2,3,5,6) (1,7) (2,4,5,6,7) (1,2,4,5) (2,3,4,5,6) {2,8,22,7,20,20,22,21}
+
[.#.###.###] (3,7,8) (0,8,9) (1,2,3,4,5,7,8,9) (0,1,2,3,5,6,9) (0,1,2,3,4,6,7) (0,1,2,3,5,6,8,9) (0,4,6,8) (0,1,2,4,8,9) (0,1,5,8) {191,63,54,46,150,41,166,15,177,48}
+
[#.#.] (1,2,3) (0,2) {11,14,25,14}
+
[#...] (0,3) (1,2,3) (3) (0,1,2) (2) (0,2) {7,7,14,22}
+
[....##..] (5,7) (0,6) (2,7) (1,2,3,5,6,7) (0,3,4,5,6,7) (0,1,3,5,7) (1,4) (0,1,2,3,5,7) (0,1,2,3,4,5,7) {37,30,22,26,13,31,14,31}
+
[#...##....] (0,2,7) (2,5) (0,1,4,5,6,9) (0,1,6,7,8,9) (0,2,3,4,5,7,8) (0,2,3,4,5) (1,2,3,5,6,7,8) (0,1,2,6) (1,2,4,6) (3,8,9) {76,83,91,53,48,56,83,51,57,48}
+
[#.##.####] (0,1,3,4,6,7,8) (0,2,3,5,6,7,8) (2,4) (2,3,4,5,6,7,8) (0,1,3,4,5,7,8) (5,6) (2,3,6,7,8) {31,27,50,68,55,45,60,68,68}
+
[..#....##] (0,1,4,5,6,7,8) (0,4,6,7,8) (1,3,4,5,7,8) (1,2,6,7,8) (0,2,3,4,8) (1,2,4,5) (0,4,5,6,7) (0,1,3,4,6,7,8) {52,52,40,41,71,35,43,53,68}
+
[.#.#] (1,3) (0,2) {19,106,19,106}
+
[.#.#] (0,3) (1,2,3) (1,2) (2) (0,1,3) {20,44,28,31}
+
[####.] (0,2,4) (1,2) (0,1,2,3) (0,2,3,4) (1) {134,128,137,125,10}
+
[###...##] (0,4,5,6,7) (0,1,2,5) (1,4,5,7) (0,1,5) (2,3,4,7) (0,2,5,6,7) (0,2,3,6) (1,3,5) (0,1,2,3,6,7) (1,2,4,5,6) {201,193,197,35,42,211,32,55}
+
[..#.##] (2,3,4,5) (0,1,2,3,5) (1,4) (0,1) (0,3,4) (0,3,5) {29,31,12,23,24,17}
+
[#..#] (2) (0,1) (0,1,2) (1,2) (3) (0,1,3) {23,25,25,20}
+
[.##.##..#.] (2,4,9) (0,1,3,4,5,6,8,9) (2,4,5,6,7) (1,2,3,4,6,7,8,9) (0,4,5,7,8) (0,3,4,6,7,8,9) (1,2,4,5,6,7,9) (0,3,4,5,6,7,8) {17,16,30,28,47,16,41,41,28,36}
+
[#..#.#] (0,3,5) (1,3,4) (1,3,5) (0,2,3,5) (4,5) {24,173,9,197,12,209}
+
[..#.#] (0,1,3,4) (1,2,3) (0,1,2,4) (0,2,3) {160,25,158,146,22}
+
[###..###] (1,2,4,5,7) (0,2,3,5,7) (0,3,4,5,6,7) (1,2,6,7) (0,1) (1,2,4,7) (3,4,5,7) (0,2,3,5,6,7) {46,41,57,45,49,65,42,79}
+
[#.##] (1,2,3) (2,3) (0,2,3) {14,1,18,18}
+
[.##.######] (1,2,3,4,5) (0,2,7) (0,2,4,5,6,7,8,9) (6,8,9) (0,1,3,4,6,8,9) (5) (5,6,9) (0,1,4,5,7,8,9) (0,2,3) (0,1,2,6,7,8,9) (1,2,5,6,7,8,9) {58,38,41,16,30,38,65,43,58,72}
+
[.#...##.#] (0,1,2,3,4,6,7,8) (0,2,3,4,5,7) (0,1,5,6) (0,2,3,4,5,6,7) (0,1,2,6,7,8) (2,3,4,5,7) (0,2,4,7) (3,5,8) {220,14,230,224,217,223,32,230,32}
+
[####..#..] (0,2,5) (3,4) (0,2,4,5) (0,4,5,7) (0,2,4,5,6,8) (0,1,5,8) (0,1,2,6,7) (0,1,3,4,5,7,8) (0,1,4,5,6) (0,2,3,4,5,6,8) (0,4,5,7,8) {302,229,63,40,99,283,47,64,243}
+
[...#.#.] (0,2,3,4,5) (3,4,5,6) (0,1,3,4,6) (3,4,5) (1,2,3,4,6) (0,3,6) (0,2,5) (0,1,5) (0,2,4,5,6) {87,25,61,70,76,80,58}
+
[###......] (0,1,3,6,7,8) (3,6) (2,3,4,5,6,7) (0,4,8) (1,5,6,8) (0,1,3,4,6,7) (0,1,2,4,6,7,8) (1,2) (1,2,6) {145,188,47,160,29,35,188,157,156}
+
[...##.#] (3,4,6) (0,1,3,4,6) (0,2,3,6) (3) (0,6) (4,5,6) (0,1,2,4,5) (0,3,5) (1,4,5,6) {38,26,19,40,39,21,35}
+
[####..##] (0,1,2,4,7) (1,6) (0,1,3,6) (0,7) (2,6) (0,1,3) (1,2,4,7) (3,5,6,7) {28,38,208,23,24,12,210,43}
+
[.#.....] (0,1) (0,3,4,6) (2,3,4,6) (4,5,6) (1,2,4,5,6) (0,1,3,4,5) (3,4,6) {44,44,23,55,83,47,64}
+
[#.#.##....] (0,1,2,3,7,8) (2,4,5,7,8) (0,1,3,4,8,9) (0,5,7,9) (3,4) (0,1,2,3,4,5,8,9) (0,1,2,3,4,5,6,7,9) (0,2,3,4,6,8,9) {48,26,154,61,184,135,23,130,167,47}
+
[##.#######] (2,3,5,6,8,9) (0,5,9) (1,2,9) (0,2,3,4,5,6,7,8) (2,6,8) (0,3,5,6) (0,1,2,3,4,5,7,9) (3,4,9) (0,2,5,6,8) (3,7) {35,17,158,154,7,167,147,13,141,171}
+
[#.##.#..] (0,3) (0,2,4) (1,2,3,5,6) (0,1,2,3,6) (1,2,3,4,5,7) (2,3) (3,4) (2,3,4,7) (0,1,2,7) (0,1,6,7) {72,60,68,67,41,16,39,45}
+
[###..] (3) (1,2,3) (0,1,2,3) (3,4) (0,1,4) (0,3,4) (0,2) {37,26,24,34,18}
+
[...#...###] (2,3,5) (0,3,4,5,6,9) (3,6) (2,8) (0,1,4,5,6,7,9) (1,3) (0,1,3,4,5,6,7,8,9) (5,7,9) (0,2,4,8) {50,36,32,66,50,63,46,33,22,48}
+
[#..#] (0,1,3) (0,2,3) (1) (1,2) {16,181,165,16}
+
[#.#.] (0,2) (0,1,3) {19,15,4,15}
+
[##.####] (0,1,3) (0,4,5,6) (0,1,3,4,5,6) (0,2,4,5,6) (0,1,2,4,5,6) (2,3,4) {28,18,38,24,43,24,24}
+
[#..#..] (0,3) (1,2,3,4) (1,2,4,5) (0,1,2,3,4,5) {19,227,227,33,227,213}
+
[#.##] (1,2,3) (0,1) (1,2) (2,3) {17,49,32,12}
+
[.#.##] (0,1,3) (3,4) (2) (0,2,4) {16,13,20,28,18}
+
[##..] (2) (0) (3) (0,2) (1,3) (0,2,3) {15,15,33,31}
+
[.##.#.###.] (1,6,8) (6,7) (0,1,2) (1,5,6,7,9) (2,3,4,5,6,8,9) (7,8) (2,4,5,6,7,8) (3,6,7,9) (0,1,3,5,6,7,8,9) (1,2,3,5,6,7) (0,2,5,6,8,9) (0,2,3,4,5,8,9) {19,59,26,37,9,46,82,69,41,50}
+
[#.#...#] (0,1,4,6) (0,3) (3,6) (1,2,4,5,6) (0,1,5) (1,4,5,6) (0,1,2,3,5) (0,1,4,5,6) (1,3,4,6) {51,67,24,33,42,59,42}
+
[####] (1,3) (0,1,2,3) {12,16,12,16}
+
[.#.#.] (0,2,3) (0,3,4) (0,1) (0,2) (0,3) (3) (0,1,2) {58,8,27,181,16}
+
[..#....] (2,3) (2,6) (2,3,5) (0,1,3,4,5) (4,6) (0,3,5,6) (0,6) (1,2,4,5,6) {19,26,59,29,26,44,49}
+
[##..] (0,1,3) (3) (0) (0,1,2) {35,28,10,25}
+
[#..##.#] (0,2,3) (1,4) (1,2,3,5,6) (0,4) (2,3) (0,3,4) (4,6) (0,2,4,5,6) (0,3,4,6) {62,8,36,54,72,20,49}
+
[##..##...] (0,2,3,4,8) (0,1,8) (0,1,3,4,5,6,7,8) (0,3,4,5,6,7,8) (2,5,7,8) (0,1,2,3,6,8) (0,6,7) (3,5,8) (2,7) {57,32,170,62,35,43,37,178,72}
+
[.##...#] (0,2,3,5) (1,2,3,4,5) (0,1,2,5) (0,1,4,6) (0,5,6) {52,33,32,15,16,38,21}
+
[....#.] (0,2,3) (0,2) (3,5) (0,1,2,3,5) (1) (3,4) {12,17,12,24,5,17}
+
[....#..#..] (2,6) (0,2,3,4,5,6,7,8) (0,1,3,7,8,9) (3,4,9) (0,1,2,3,4,5,6,9) (1,3,5,7,8,9) (0,2,3,4,6,7,9) (0,1,8) (1,3,4,8) (0,1,3,4,6,7,8,9) {41,47,28,70,62,27,43,32,44,52}
+
[#.##.#.] (1,2,4,6) (1,2,3,4) (0,2,3,5,6) (0,2) (0,1,3,4,6) {28,18,46,29,18,20,29}
+
[##..#.] (1,2,4,5) (5) (0,2) (0,1,2,4) (0) (4,5) (1,3,4,5) (3,4,5) {33,34,37,192,225,221}
+
[##...##.] (0,3,4) (2,5) (1,4) (2,4,6) (0,1,3,7) (0,2,4,6,7) {164,10,193,10,185,20,173,158}
+
[.......#] (4,5) (1,2,4,7) (0,5,7) (1,4) (1,2,3,4,5,6,7) (1,2,3,4,5,7) (0,3,5,6,7) (0,1,2,5,6,7) {44,63,52,44,62,80,38,85}
+
[####..#.##] (0,3,5,8,9) (0,2,9) (1,3,5,6,7,8,9) (7,8) (0,2,3,4,5,8,9) (4,8,9) (0,1,3,4,5,6,7,9) (0,1) (0,1,2,3,4,5,7,9) (0,2,4,5,6,7) (1,3,6,8) (0,1,4,9) (4,6) {178,69,47,175,63,177,53,67,149,185}
+
[.##..####] (3,4,6) (0,3,4,5,6,7,8) (4,5,8) (0,1,2,3,5,6,7,8) (4,5) (1,2,4,7) (6) (1,3,7,8) {29,40,24,62,75,62,54,55,61}
+
[##.###.] (0,1,2,3,4) (0,3,6) (0,3,5,6) (3,5) (0,4) (0,1,3,4,5) {249,205,200,242,214,25,35}
+
[##....##] (1,3,4,6) (1,2,4,5,6,7) (0,1,3,4,5,7) (0,1,2,3,5,6) (2,3,4,5,6,7) (0,3,4,6,7) (0,4,5) {43,37,32,45,52,55,46,22}
+
[##....###.] (2,6,8,9) (3,9) (2,4,6) (5,6,7) (4,7) (0,1,2,3,7) (2) (1,5,6,9) (0,1,3,6,8,9) (3,4,5,6) (1,2,3,4,5,6,8) (0,1,3,4,6,8) (9) {37,51,76,53,52,23,82,42,55,55}
+
[..##.] (2,3) (0,2,3,4) (1,3,4) (1,2,3,4) {8,18,34,37,26}
+
[##.#....#] (2,5) (0,1,2,5,8) (3,4,5,6,8) (1,2,3,4,6,7,8) (0,1,3,4,5,6,8) (1,4,7) (2,3,5,7,8) (1,2,3,5,7) {29,65,46,36,47,40,32,38,54}
+
[###.#.#] (2,5) (0,4) (2,3) (1,2) (2) (0,3,6) (0,2,6) (0,3) (0,1,4,5,6) {88,25,56,42,38,32,51}
+
[#..###.##] (0,1,4,5,6) (0,1,3,4,5,6,7,8) (0,1,2,7,8) (1,2,3,4,5) (0,3,8) (1,3,4,5,6,7) (4,6) (0,1,3,5,6,7) (8) (0,2,3,4,5,6,7) (1,7) {175,196,12,182,43,176,171,187,52}
+
[.#.###..] (2,4,5) (2,6,7) (2,4,5,6,7) (3,4) (0,3,4,5,7) (1,2,3,4,5,7) (5) (2,5,6) (1,3,4,5,6,7) (0,2,4,6,7) {14,25,37,189,194,64,34,47}
+
[.##.] (0,1) (0,2,3) (0,1,2) (1,2) {35,31,38,20}
+
[#.#...#] (0,1,4,5) (1,2,4) (0,1,4,6) (1,2,4,5,6) (0,2,6) (1,2,3) (3,4) {42,60,34,19,63,35,39}
+
[.###...] (4) (0,2,3,4,6) (0,1,2,3,4,5) (0,2,4,5,6) (0,1,3,4,5) (1,2,3) {37,35,20,36,44,36,3}
+
[#.#..] (0,3) (2,3) (3,4) (0,3,4) (2,4) (0,1,3) {200,3,39,227,212}
+
[#.#.#...] (2) (1,7) (0,3,4,6) (3) (1,4,5,6,7) (0,2,3,5,6) {33,211,25,52,29,30,46,211}
+
[....##] (0,1,4,5) (0,1,5) (2,3,4) (1,3) (0,1,3) (1,2,5) (0) (1,2,3,4) {36,41,20,34,21,16}
+
[.##.###.#.] (0,2,3,4,9) (1,7) (1,2,3,5,6,7,8,9) (0,1,2,4,5,7,9) (3,4,5,6,7) (4,6) (2) (0,1,2,3,6,7,9) (0,6,7,8,9) {138,163,164,156,25,29,162,172,22,157}
+
[..#.#.] (0,1,2,4,5) (0,2,3) (0,2,5) (0,4,5) {53,2,34,19,21,34}
+
[#...##] (1,2,3,4) (0,3,5) (1,5) (0,1,4,5) (0,2,3,4,5) (0,2,3) (0,1,2,3) {32,41,28,39,15,30}
+
[##.###..] (0,2,5,6) (0,5,6,7) (4,5,7) (1,3,6,7) (0,2,5,7) (1) (3,4,6,7) (0,6) (1,2,3,5) {30,45,38,45,35,55,43,64}
+
[.#.#..#...] (3,7) (0,4,5,9) (3,4,6,8) (0,1,2,3,5,6,8,9) (2,3,4,5,6,7,8,9) (8,9) (0,1,2,3,4,6,8) (0,1,2) (0,1,2,4,5,7,8,9) (0,1,3,4,6) (0,1,3,7,9) (0,1,6,7,8,9) {263,243,67,237,236,61,224,76,91,99}
+
[.##.##] (0,2,3,5) (1) (0,1,2,4,5) (4,5) (1,3) (0) (0,2,3) {44,31,42,42,15,35}
+
[###.] (1,3) (1,2) (0,2) (2) (2,3) {9,155,45,146}
+
[#.#...#.#.] (0,1,2,5,6) (0,1,2,5,7) (1,2,4,5,6) (0,1,3,5,7,8,9) (2,3,4,5,6,8) (4,6) (0,1,2,3,4,5,6,8) (0,3,4,5,9) (5,6,7,8) (1,4,6,7,8) (2,3,8,9) (2,3,4,9) (0,1,2,4,5,7,8) {76,79,96,73,82,86,58,63,80,61}
+
[...###] (0,3,4) (3,4,5) (0,1,4,5) (0,2,3,4) {34,10,10,32,42,18}
+
[..##.] (1,2,4) (0,2,3) (2,3) {17,7,28,21,7}
+
[.###] (1,2,3) (0,2) {4,19,23,19}
+
[###.] (2,3) (0,1,3) (0,1) (1,2) {15,32,30,26}
+
[..#.#.] (0,2,4) (3,4) (0,1,2,4,5) (0,1,3) (1,2,3,5) {37,29,33,31,48,21}
+
[###..###] (1,3,6) (0,1,2,3,4,5,7) (0,2,4,5,6,7) (1,2,6) (0,3,6) (1,5,7) {27,26,20,16,20,37,36,37}
+
[.##.] (2,3) (1,2) (0,3) {14,1,1,14}
+
[.#.##...#] (3,4,5,6,8) (1,2,3,6,7,8) (1,2,3,5,6,7) (3,7) (2,3,4,5,6,7,8) (0,1,2,8) (0,3,4,5,7,8) {153,46,47,212,158,173,51,196,189}
+
[#.###.] (0,1,4,5) (0,1,2,5) (1,2,3) (1,2,3,4,5) (0,2,3,5) (0,3,4) (1,2) (2,3,4,5) {220,54,54,223,212,30}
+
[#.####] (1,2,3,5) (0,1,5) (1,2,3,4) (0,2,3,4) (2,3) {21,25,36,36,20,14}
+
[...#....##] (0,9) (4,5,6) (0,2,4,6,7,9) (0,2,3,4,7,8,9) (0,1,4,7) (0,3,7,8) (8,9) (0,7,8) (0,1,2,5,6,7) {65,26,36,8,49,35,47,46,18,49}
+
[.####.##] (1,2,3,5,6,7) (0,1,3,4,6,7) (1,2,3,4,5,6) (0,2,4,7) (1,3,5) (3,4,5,6,7) (4,7) (0,1,4,6,7) (0,7) {19,35,12,42,55,27,40,46}
+
[.#.###] (0,2,3,5) (1,3,4,5) (0,1,2,4) (1,5) (1,2,3,5) {29,50,39,38,35,43}
+
[..#..##.#] (2,3,8) (1,5) (1,4,5,6,7,8) (1,3,4,5,7,8) (2,3,4,5,7) (0,1,3,4) (0,1,3,4,6) (0,2,3,4,5,7,8) {28,173,36,70,64,171,30,46,60}
+
[.##.] (1) (0,2,3) (1,2) {3,11,10,3}
+
[#.#....##] (1,2,3,8) (1,2,3,4,5) (0,1,3,7) (0,1,2,3,6,7) (0,1,2,3,7,8) (4) (1,2,3,4,5,7,8) {27,49,45,49,31,19,6,42,35}
+
[##..] (1) (0,1,2) (2,3) (0) {22,19,28,9}
+
[##..###] (1,2,3,4,5) (2,3,4,5) (0,2,4,5) (1,4) (0,2,4) (3) (0,1,3,6) (1,3,6) {37,171,27,179,33,24,158}
+
[.####.] (1,2,3,4) (0,4) (0,1,3) (1,2,3) (2,3,4,5) (1,2,3,4,5) (0,2) {44,38,47,45,44,21}
+
[.##.#...#] (1,6,8) (2,3,4,5,8) (0,1,2,3,6,8) (0,2,3,4,7,8) (5,7) (0,1,2,3,4,5,8) (1,3,4,5) (0,1,4) (1,2,3,6,7,8) (4,5,6,7) (0,1,2,4,5,6,8) {59,172,61,70,85,56,141,54,164}
+
[.##......] (7,8) (3,5) (1,2) (1,3,5,6,8) (2,3,4,5,6) (0,4,7,8) (2,4) (1,2,3,4,5,6,7) {4,35,43,56,44,56,47,41,33}
+
[#....#....] (0,1,2,3,4,5,7,8,9) (2,4,5,9) (3,5,6) (3,9) (0,3,5,9) (0,1,4) (0,1,3,5,6,8) (0,1,2,4,5,6,7,8) (0,2,5,6,7,8,9) (0,1,3,6,8,9) (4,6,8) {217,50,191,56,54,220,203,176,191,209}
+
[.#..#.] (0,2,4) (1,3) (1,3,5) (1,2,3,5) (0,1,2,3) (3) (0,3,4,5) {145,21,28,151,139,132}
+
[#..###] (3,4) (2) (1,3,5) (1,2,3,5) (0,1,2) (0,2,4,5) (0,2,3,4) (0,2,3) {42,19,63,44,38,13}
+
[#.#......] (0,2,4,6,7) (0,3,4,6,8) (0,3,4,5,8) (0,1,4,6) (2,4,5) (2,3,5) (1,3,5,7) (3,8) {32,17,39,53,46,56,18,25,25}
+
[###......#] (0,1,2,5) (5,6,9) (0,2,8,9) (0,2,3,5) (2) (0,1,2,3,4,5,6,7) (0,1,2,3,5,6,7,9) (7) (0,3,4) {73,56,84,44,19,78,52,49,9,44}
+
[#.##] (1,2) (2) (0,1,3) (0,1,2) {21,27,190,4}
+
[...#..#.##] (0,2,3,4,6,7,8,9) (0,2,3,4,8,9) (0,1,2,5,6,8,9) (2,3) (0,1,2,5,6,7,8) (1,2,5,8) (0,1,2,3,5,7,8,9) (2,7) (0,3,8,9) (2,4,9) {36,32,70,37,11,32,14,33,37,42}
+934
vis/10/generate.ts
···
···
+
const scriptDir = import.meta.dir;
+
const file = await Bun.file(`${scriptDir}/../../shared/10/input.txt`).text();
+
+
interface Machine {
+
target: boolean[];
+
buttons: number[][];
+
joltages: number[];
+
}
+
+
// Parse input
+
const machines: Machine[] = file
+
.trim()
+
.split("\n")
+
.map((line) => {
+
const lightsMatch = line.match(/\[([.#]+)\]/);
+
const target = lightsMatch![1].split("").map((c) => c === "#");
+
+
const buttonsMatch = line.matchAll(/\(([0-9,]+)\)/g);
+
const buttons: number[][] = [];
+
for (const match of buttonsMatch) {
+
const indices = match[1].split(",").map(Number);
+
buttons.push(indices);
+
}
+
+
const joltagesMatch = line.match(/\{([0-9,]+)\}/);
+
const joltages = joltagesMatch ? joltagesMatch[1].split(",").map(Number) : [];
+
+
return { target, buttons, joltages };
+
});
+
+
// Solve one machine
+
function solveMachine(machine: Machine): { solution: number[]; steps: any[] } {
+
const n = machine.target.length;
+
const m = machine.buttons.length;
+
+
const matrix: number[][] = [];
+
for (let i = 0; i < n; i++) {
+
const row: number[] = [];
+
for (let j = 0; j < m; j++) {
+
row.push(machine.buttons[j].includes(i) ? 1 : 0);
+
}
+
row.push(machine.target[i] ? 1 : 0);
+
matrix.push(row);
+
}
+
+
const steps = [JSON.parse(JSON.stringify(matrix))];
+
const pivotCols: number[] = [];
+
+
for (let col = 0; col < m; col++) {
+
let pivotRow = -1;
+
for (let row = pivotCols.length; row < n; row++) {
+
if (matrix[row][col] === 1) {
+
pivotRow = row;
+
break;
+
}
+
}
+
+
if (pivotRow === -1) continue;
+
+
const targetRow = pivotCols.length;
+
if (pivotRow !== targetRow) {
+
[matrix[pivotRow], matrix[targetRow]] = [
+
matrix[targetRow],
+
matrix[pivotRow],
+
];
+
steps.push(JSON.parse(JSON.stringify(matrix)));
+
}
+
+
pivotCols.push(col);
+
+
for (let row = 0; row < n; row++) {
+
if (row !== targetRow && matrix[row][col] === 1) {
+
for (let c = 0; c <= m; c++) {
+
matrix[row][c] ^= matrix[targetRow][c];
+
}
+
steps.push(JSON.parse(JSON.stringify(matrix)));
+
}
+
}
+
}
+
+
// Identify free variables
+
const isPivot = new Array(m).fill(false);
+
pivotCols.forEach((col) => (isPivot[col] = true));
+
const freeVars: number[] = [];
+
for (let j = 0; j < m; j++) {
+
if (!isPivot[j]) freeVars.push(j);
+
}
+
+
// Try all combinations of free variables to find minimum
+
let minPresses = Infinity;
+
let bestSolution: number[] = [];
+
+
const numCombinations = 1 << freeVars.length;
+
for (let combo = 0; combo < numCombinations; combo++) {
+
const solution: number[] = new Array(m).fill(0);
+
+
// Set free variables according to combo
+
for (let i = 0; i < freeVars.length; i++) {
+
solution[freeVars[i]] = (combo >> i) & 1;
+
}
+
+
// Back-substitution for pivot variables
+
for (let i = pivotCols.length - 1; i >= 0; i--) {
+
const col = pivotCols[i];
+
solution[col] = matrix[i][m];
+
+
for (let j = col + 1; j < m; j++) {
+
if (matrix[i][j] === 1) {
+
solution[col] ^= solution[j];
+
}
+
}
+
}
+
+
const presses = solution.reduce((sum, x) => sum + x, 0);
+
if (presses < minPresses) {
+
minPresses = presses;
+
bestSolution = solution;
+
}
+
}
+
+
return { solution: bestSolution, steps };
+
}
+
+
// Solve Part 2: joltage configuration
+
function solveMachinePart2(machine: Machine): number[] {
+
const n = machine.joltages.length;
+
const m = machine.buttons.length;
+
const target = machine.joltages;
+
+
// Build coefficient matrix A
+
const A: number[][] = [];
+
for (let i = 0; i < n; i++) {
+
const row: number[] = [];
+
for (let j = 0; j < m; j++) {
+
row.push(machine.buttons[j].includes(i) ? 1 : 0);
+
}
+
A.push(row);
+
}
+
+
// Build augmented matrix [A | b]
+
const matrix: number[][] = [];
+
for (let i = 0; i < n; i++) {
+
matrix.push([...A[i], target[i]]);
+
}
+
+
// Gaussian elimination
+
const pivotCols: number[] = [];
+
for (let col = 0; col < m; col++) {
+
let pivotRow = -1;
+
for (let row = pivotCols.length; row < n; row++) {
+
if (matrix[row][col] !== 0) {
+
pivotRow = row;
+
break;
+
}
+
}
+
+
if (pivotRow === -1) continue;
+
+
const targetRow = pivotCols.length;
+
if (pivotRow !== targetRow) {
+
[matrix[pivotRow], matrix[targetRow]] = [
+
matrix[targetRow],
+
matrix[pivotRow],
+
];
+
}
+
+
pivotCols.push(col);
+
+
// Scale row so pivot is 1
+
const pivot = matrix[targetRow][col];
+
for (let c = 0; c <= m; c++) {
+
matrix[targetRow][c] /= pivot;
+
}
+
+
// Eliminate column in other rows
+
for (let row = 0; row < n; row++) {
+
if (row !== targetRow && matrix[row][col] !== 0) {
+
const factor = matrix[row][col];
+
for (let c = 0; c <= m; c++) {
+
matrix[row][c] -= factor * matrix[targetRow][c];
+
}
+
}
+
}
+
}
+
+
// Identify free variables
+
const isPivot = new Array(m).fill(false);
+
pivotCols.forEach((col) => (isPivot[col] = true));
+
const freeVars: number[] = [];
+
for (let j = 0; j < m; j++) {
+
if (!isPivot[j]) freeVars.push(j);
+
}
+
+
if (freeVars.length > 15) {
+
return new Array(m).fill(0);
+
}
+
+
let minPresses = Infinity;
+
let bestSolution: number[] = [];
+
+
const maxTarget = Math.max(...target);
+
const maxFreeValue = Math.min(maxTarget * 2, 200);
+
+
function searchFreeVars(idx: number, currentSol: number[]) {
+
if (idx === freeVars.length) {
+
const sol = [...currentSol];
+
let valid = true;
+
for (let i = pivotCols.length - 1; i >= 0; i--) {
+
const col = pivotCols[i];
+
let val = matrix[i][m];
+
for (let j = col + 1; j < m; j++) {
+
val -= matrix[i][j] * sol[j];
+
}
+
sol[col] = val;
+
+
if (val < -1e-9 || Math.abs(val - Math.round(val)) > 1e-9) {
+
valid = false;
+
break;
+
}
+
}
+
+
if (valid) {
+
const intSol = sol.map((x) => Math.round(Math.max(0, x)));
+
const presses = intSol.reduce((sum, x) => sum + x, 0);
+
if (presses < minPresses) {
+
minPresses = presses;
+
bestSolution = intSol;
+
}
+
}
+
return;
+
}
+
+
for (let val = 0; val <= maxFreeValue; val++) {
+
currentSol[freeVars[idx]] = val;
+
searchFreeVars(idx + 1, currentSol);
+
}
+
}
+
+
searchFreeVars(0, new Array(m).fill(0));
+
+
return bestSolution;
+
}
+
+
const machinesData = JSON.stringify(machines);
+
+
const html = `<!DOCTYPE html>
+
<html lang="en">
+
<head>
+
<meta charset="UTF-8">
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
+
<title>AoC 2025 Day 10 - Factory</title>
+
<style>
+
* {
+
box-sizing: border-box;
+
}
+
body {
+
background: #1e1e2e;
+
color: #cdd6f4;
+
font-family: "Source Code Pro", monospace;
+
font-size: 14pt;
+
font-weight: 300;
+
padding: 20px;
+
display: flex;
+
flex-direction: column;
+
align-items: center;
+
min-height: 100vh;
+
margin: 0;
+
}
+
h1 {
+
color: #a6e3a1;
+
text-shadow: 0 0 2px #a6e3a1, 0 0 5px #a6e3a1;
+
margin-bottom: 10px;
+
font-size: 1em;
+
font-weight: normal;
+
}
+
.controls {
+
background: #11111b;
+
border: 1px solid #313244;
+
padding: 15px;
+
margin: 15px 0;
+
max-width: 1200px;
+
border-radius: 4px;
+
width: 100%;
+
}
+
.control-row {
+
display: flex;
+
gap: 15px;
+
align-items: center;
+
margin-bottom: 15px;
+
flex-wrap: wrap;
+
justify-content: center;
+
}
+
.control-row:last-child {
+
margin-bottom: 0;
+
}
+
button {
+
background: #11111b;
+
color: #a6e3a1;
+
border: 1px solid #313244;
+
padding: 8px 16px;
+
cursor: pointer;
+
font-family: inherit;
+
font-size: 14px;
+
border-radius: 3px;
+
}
+
button:hover {
+
background: #181825;
+
}
+
button:disabled {
+
opacity: 0.5;
+
cursor: not-allowed;
+
}
+
.speed-control {
+
display: flex;
+
align-items: center;
+
gap: 8px;
+
font-size: 13px;
+
color: #a6adc8;
+
}
+
.speed-control input[type="range"] {
+
width: 120px;
+
height: 6px;
+
background: #313244;
+
outline: none;
+
-webkit-appearance: none;
+
border-radius: 3px;
+
}
+
.speed-control input[type="range"]::-webkit-slider-thumb {
+
-webkit-appearance: none;
+
appearance: none;
+
width: 14px;
+
height: 14px;
+
background: #a6e3a1;
+
cursor: pointer;
+
border-radius: 50%;
+
border: 1px solid #313244;
+
}
+
.speed-control input[type="range"]::-moz-range-thumb {
+
width: 14px;
+
height: 14px;
+
background: #a6e3a1;
+
cursor: pointer;
+
border-radius: 50%;
+
border: 1px solid #313244;
+
}
+
.machine-display {
+
background: #11111b;
+
border: 1px solid #313244;
+
padding: 20px;
+
margin: 20px 0;
+
max-width: 1200px;
+
border-radius: 4px;
+
width: 100%;
+
}
+
.lights {
+
display: flex;
+
gap: 10px;
+
justify-content: center;
+
margin: 20px 0;
+
flex-wrap: wrap;
+
}
+
.light {
+
width: 50px;
+
height: 50px;
+
border-radius: 50%;
+
border: 2px solid #313244;
+
display: flex;
+
flex-direction: column;
+
align-items: center;
+
justify-content: center;
+
font-size: 9px;
+
transition: all 0.3s ease;
+
overflow: hidden;
+
text-align: center;
+
padding: 3px;
+
line-height: 1.1;
+
}
+
.light.off {
+
background: #1e1e2e;
+
color: #6c7086;
+
}
+
.light.on {
+
background: #a6e3a1;
+
color: #1e1e2e;
+
box-shadow: 0 0 10px #a6e3a1;
+
}
+
.light.target {
+
border-color: #f9e2af;
+
border-width: 3px;
+
}
+
.buttons-grid {
+
display: grid;
+
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
+
gap: 10px;
+
margin: 20px 0;
+
}
+
.button-display {
+
background: #181825;
+
border: 1px solid #313244;
+
padding: 10px;
+
border-radius: 4px;
+
text-align: center;
+
cursor: pointer;
+
transition: all 0.2s ease;
+
}
+
.button-display:hover {
+
background: #313244;
+
}
+
.button-display.pressed {
+
background: #a6e3a1;
+
color: #1e1e2e;
+
border-color: #a6e3a1;
+
}
+
.button-label {
+
font-size: 12px;
+
margin-bottom: 5px;
+
color: #a6adc8;
+
}
+
.button-toggles {
+
font-size: 11px;
+
color: #6c7086;
+
}
+
.stats {
+
background: #11111b;
+
border: 1px solid #313244;
+
padding: 10px 15px;
+
margin: 10px 0;
+
max-width: 1200px;
+
border-radius: 4px;
+
text-align: center;
+
font-size: 13px;
+
color: #a6adc8;
+
width: 100%;
+
margin-top: auto;
+
}
+
.info {
+
margin: 10px 0;
+
text-align: center;
+
color: #f9e2af;
+
}
+
a {
+
text-decoration: none;
+
color: #a6e3a1;
+
outline: 0;
+
}
+
a:hover, a:focus {
+
text-decoration: underline;
+
}
+
</style>
+
</head>
+
<body>
+
<h1>AoC 2025 Day 10 - Factory Machines</h1>
+
+
<div class="controls">
+
<div class="control-row">
+
<button id="togglePart" style="color: #f9e2af; font-weight: bold;">Part 1</button>
+
<button id="prev">← Previous Machine</button>
+
<button id="play">▶ Play</button>
+
<button id="next">Next Machine →</button>
+
<button id="reset">↺ Reset</button>
+
<div class="speed-control">
+
<label for="speed">Speed:</label>
+
<input type="range" id="speed" min="1" max="25" value="5" step="1">
+
<span id="speedValue">5x</span>
+
</div>
+
</div>
+
</div>
+
+
<div class="info" id="machineInfo">Machine 1 / ${machines.length}</div>
+
+
<div class="machine-display">
+
<h2 id="displayTitle" style="text-align: center; color: #89b4fa; font-size: 18px; margin-bottom: 20px;">Indicator Lights</h2>
+
<div class="lights" id="lights"></div>
+
+
<h2 style="text-align: center; color: #89b4fa; font-size: 18px; margin: 30px 0 20px 0;">Buttons</h2>
+
<div class="buttons-grid" id="buttons"></div>
+
</div>
+
+
<div class="stats">
+
<div id="statsInfo">Buttons Pressed: 0 | Target: ? | Accumulated Total: 0</div>
+
<div style="margin-top: 5px; font-size: 11px;"><a href="../index.html">[Return to Index]</a></div>
+
</div>
+
+
<script type="module">
+
const machines = ${machinesData};
+
+
let currentMode = 1; // 1 or 2
+
let currentMachineIndex = 0;
+
let currentState = [];
+
let buttonStates = []; // Track which buttons are "on" (pressed odd number of times)
+
let isPlaying = false;
+
let showingSolution = false;
+
let solutionSteps = [];
+
let currentStep = 0;
+
let solvedMachines = new Set(); // Track which machines have been solved
+
let animationSpeed = 200; // ms between button presses (default 5x)
+
+
+
function renderMachine() {
+
const machine = machines[currentMachineIndex];
+
+
// Update title based on mode
+
const titleEl = document.getElementById('displayTitle');
+
if (currentMode === 1) {
+
titleEl.textContent = 'Indicator Lights';
+
titleEl.style.color = '#89b4fa';
+
} else {
+
titleEl.textContent = 'Joltage Counters';
+
titleEl.style.color = '#f9e2af';
+
}
+
+
// Render lights or counters
+
const lightsDiv = document.getElementById('lights');
+
lightsDiv.innerHTML = '';
+
+
if (currentMode === 1) {
+
// Part 1: Indicator lights
+
machine.target.forEach((target, i) => {
+
const light = document.createElement('div');
+
light.className = \`light \${currentState[i] ? 'on' : 'off'} \${target ? 'target' : ''}\`;
+
light.textContent = i;
+
lightsDiv.appendChild(light);
+
});
+
} else {
+
// Part 2: Joltage counters
+
machine.joltages.forEach((target, i) => {
+
const counter = document.createElement('div');
+
const current = currentState[i] || 0;
+
const isTarget = current === target;
+
counter.className = \`light \${isTarget ? 'on' : 'off'} \${true ? 'target' : ''}\`;
+
counter.innerHTML = \`<div style="font-size: 7px; opacity: 0.7;">[\${i}]</div><div style="font-size: 10px; font-weight: bold;">\${current}/<span style="color: #f9e2af;">\${target}</span></div>\`;
+
lightsDiv.appendChild(counter);
+
});
+
}
+
+
// Render buttons
+
const buttonsDiv = document.getElementById('buttons');
+
buttonsDiv.innerHTML = '';
+
machine.buttons.forEach((toggles, i) => {
+
const btn = document.createElement('div');
+
const pressCount = buttonStates[i] || 0;
+
const isPressed = currentMode === 1 ? (pressCount % 2 === 1) : (pressCount > 0);
+
btn.className = \`button-display \${isPressed ? 'pressed' : ''}\`;
+
btn.innerHTML = \`
+
<div class="button-label">Button \${i}\${currentMode === 2 ? \` (\${pressCount})\` : ''}</div>
+
<div class="button-toggles">Affects: \${toggles.join(', ')}</div>
+
\`;
+
btn.addEventListener('click', () => toggleButton(i));
+
buttonsDiv.appendChild(btn);
+
});
+
}
+
+
function toggleButton(buttonIndex) {
+
const machine = machines[currentMachineIndex];
+
+
if (currentMode === 1) {
+
// Part 1: Toggle lights (XOR)
+
buttonStates[buttonIndex] = buttonStates[buttonIndex] ? 0 : 1;
+
machine.buttons[buttonIndex].forEach(lightIndex => {
+
currentState[lightIndex] = !currentState[lightIndex];
+
});
+
} else {
+
// Part 2: Increment counters
+
buttonStates[buttonIndex] = (buttonStates[buttonIndex] || 0) + 1;
+
machine.buttons[buttonIndex].forEach(counterIndex => {
+
currentState[counterIndex] = (currentState[counterIndex] || 0) + 1;
+
});
+
}
+
+
renderMachine();
+
updateStats();
+
}
+
+
function solveMachine(machine) {
+
const n = machine.target.length;
+
const m = machine.buttons.length;
+
+
const matrix = [];
+
for (let i = 0; i < n; i++) {
+
const row = [];
+
for (let j = 0; j < m; j++) {
+
row.push(machine.buttons[j].includes(i) ? 1 : 0);
+
}
+
row.push(machine.target[i] ? 1 : 0);
+
matrix.push(row);
+
}
+
+
const pivotCols = [];
+
for (let col = 0; col < m; col++) {
+
let pivotRow = -1;
+
for (let row = pivotCols.length; row < n; row++) {
+
if (matrix[row][col] === 1) {
+
pivotRow = row;
+
break;
+
}
+
}
+
+
if (pivotRow === -1) continue;
+
+
const targetRow = pivotCols.length;
+
if (pivotRow !== targetRow) {
+
[matrix[pivotRow], matrix[targetRow]] = [matrix[targetRow], matrix[pivotRow]];
+
}
+
+
pivotCols.push(col);
+
+
for (let row = 0; row < n; row++) {
+
if (row !== targetRow && matrix[row][col] === 1) {
+
for (let c = 0; c <= m; c++) {
+
matrix[row][c] ^= matrix[targetRow][c];
+
}
+
}
+
}
+
}
+
+
const solution = new Array(m).fill(0);
+
for (let i = pivotCols.length - 1; i >= 0; i--) {
+
const col = pivotCols[i];
+
solution[col] = matrix[i][m];
+
for (let j = col + 1; j < m; j++) {
+
if (matrix[i][j] === 1) {
+
solution[col] ^= solution[j];
+
}
+
}
+
}
+
+
return solution;
+
}
+
+
// Part 2 solver (copy of server-side logic)
+
function solveMachinePart2(machine) {
+
const n = machine.joltages.length;
+
const m = machine.buttons.length;
+
const target = machine.joltages;
+
+
const A = [];
+
for (let i = 0; i < n; i++) {
+
const row = [];
+
for (let j = 0; j < m; j++) {
+
row.push(machine.buttons[j].includes(i) ? 1 : 0);
+
}
+
A.push(row);
+
}
+
+
const matrix = [];
+
for (let i = 0; i < n; i++) {
+
matrix.push([...A[i], target[i]]);
+
}
+
+
const pivotCols = [];
+
for (let col = 0; col < m; col++) {
+
let pivotRow = -1;
+
for (let row = pivotCols.length; row < n; row++) {
+
if (matrix[row][col] !== 0) {
+
pivotRow = row;
+
break;
+
}
+
}
+
+
if (pivotRow === -1) continue;
+
+
const targetRow = pivotCols.length;
+
if (pivotRow !== targetRow) {
+
[matrix[pivotRow], matrix[targetRow]] = [matrix[targetRow], matrix[pivotRow]];
+
}
+
+
pivotCols.push(col);
+
+
const pivot = matrix[targetRow][col];
+
for (let c = 0; c <= m; c++) {
+
matrix[targetRow][c] /= pivot;
+
}
+
+
for (let row = 0; row < n; row++) {
+
if (row !== targetRow && matrix[row][col] !== 0) {
+
const factor = matrix[row][col];
+
for (let c = 0; c <= m; c++) {
+
matrix[row][c] -= factor * matrix[targetRow][c];
+
}
+
}
+
}
+
}
+
+
const isPivot = new Array(m).fill(false);
+
pivotCols.forEach(col => isPivot[col] = true);
+
const freeVars = [];
+
for (let j = 0; j < m; j++) {
+
if (!isPivot[j]) freeVars.push(j);
+
}
+
+
if (freeVars.length > 8) { // Reduced limit for browser
+
return new Array(m).fill(0);
+
}
+
+
let minPresses = Infinity;
+
let bestSolution = [];
+
+
const maxTarget = Math.max(...target);
+
const maxFreeValue = Math.min(maxTarget * 2, 100);
+
+
function searchFreeVars(idx, currentSol) {
+
if (idx === freeVars.length) {
+
const sol = [...currentSol];
+
let valid = true;
+
for (let i = pivotCols.length - 1; i >= 0; i--) {
+
const col = pivotCols[i];
+
let val = matrix[i][m];
+
for (let j = col + 1; j < m; j++) {
+
val -= matrix[i][j] * sol[j];
+
}
+
sol[col] = val;
+
+
if (val < -1e-9 || Math.abs(val - Math.round(val)) > 1e-9) {
+
valid = false;
+
break;
+
}
+
}
+
+
if (valid) {
+
const intSol = sol.map(x => Math.round(Math.max(0, x)));
+
const presses = intSol.reduce((sum, x) => sum + x, 0);
+
if (presses < minPresses) {
+
minPresses = presses;
+
bestSolution = intSol;
+
}
+
}
+
return;
+
}
+
+
for (let val = 0; val <= maxFreeValue; val++) {
+
currentSol[freeVars[idx]] = val;
+
searchFreeVars(idx + 1, currentSol);
+
}
+
}
+
+
searchFreeVars(0, new Array(m).fill(0));
+
return bestSolution;
+
}
+
+
function getCurrentSolution() {
+
const machine = machines[currentMachineIndex];
+
return currentMode === 1 ? solveMachine(machine) : solveMachinePart2(machine);
+
}
+
+
function showSolution() {
+
const machine = machines[currentMachineIndex];
+
const solution = getCurrentSolution();
+
+
if (currentMode === 1) {
+
currentState = new Array(machine.target.length).fill(false);
+
buttonStates = [...solution].map(v => v === 1);
+
+
solution.forEach((shouldPress, buttonIndex) => {
+
if (shouldPress === 1) {
+
machine.buttons[buttonIndex].forEach(lightIndex => {
+
currentState[lightIndex] = !currentState[lightIndex];
+
});
+
}
+
});
+
} else {
+
currentState = new Array(machine.joltages.length).fill(0);
+
buttonStates = [...solution];
+
+
solution.forEach((pressCount, buttonIndex) => {
+
for (let p = 0; p < pressCount; p++) {
+
machine.buttons[buttonIndex].forEach(counterIndex => {
+
currentState[counterIndex]++;
+
});
+
}
+
});
+
}
+
+
showingSolution = true;
+
renderMachine();
+
updateStats();
+
}
+
+
function updateStats() {
+
const machine = machines[currentMachineIndex];
+
const solution = getCurrentSolution();
+
const minPresses = solution.reduce((a, b) => a + b, 0);
+
+
let totalPressed;
+
if (currentMode === 1) {
+
totalPressed = buttonStates.filter(b => b).length;
+
} else {
+
totalPressed = buttonStates.reduce((sum, count) => sum + (count || 0), 0);
+
}
+
+
// Calculate accumulated total for solved machines
+
let accumulatedTotal = 0;
+
solvedMachines.forEach(idx => {
+
const m = machines[idx];
+
const sol = currentMode === 1 ? solveMachine(m) : solveMachinePart2(m);
+
accumulatedTotal += sol.reduce((a, b) => a + b, 0);
+
});
+
+
document.getElementById('statsInfo').textContent = \`Buttons Pressed: \${totalPressed} | Target: \${minPresses} | Accumulated Total: \${accumulatedTotal}\`;
+
document.getElementById('machineInfo').textContent = \`Machine \${currentMachineIndex + 1} / \${machines.length}\`;
+
}
+
+
document.getElementById('prev').addEventListener('click', () => {
+
if (currentMachineIndex > 0) {
+
isPlaying = false;
+
document.getElementById('play').textContent = '▶ Play';
+
currentMachineIndex--;
+
initMachine();
+
}
+
});
+
+
document.getElementById('next').addEventListener('click', () => {
+
if (currentMachineIndex < machines.length - 1) {
+
isPlaying = false;
+
document.getElementById('play').textContent = '▶ Play';
+
currentMachineIndex++;
+
initMachine();
+
}
+
});
+
+
document.getElementById('reset').addEventListener('click', initMachine);
+
+
document.getElementById('togglePart').addEventListener('click', () => {
+
currentMode = currentMode === 1 ? 2 : 1;
+
document.getElementById('togglePart').textContent = \`Part \${currentMode}\`;
+
solvedMachines.clear();
+
initMachine();
+
});
+
+
document.getElementById('play').addEventListener('click', () => {
+
isPlaying = !isPlaying;
+
document.getElementById('play').textContent = isPlaying ? '⏸ Pause' : '▶ Play';
+
if (isPlaying) {
+
animateSolution();
+
}
+
});
+
+
// Speed control
+
const speedSlider = document.getElementById('speed');
+
const speedValue = document.getElementById('speedValue');
+
speedSlider.addEventListener('input', (e) => {
+
const speed = parseInt(e.target.value);
+
speedValue.textContent = \`\${speed}x\`;
+
// Faster speed = shorter delay (inverse relationship)
+
animationSpeed = 1000 / speed;
+
});
+
+
function animateSolution() {
+
if (!isPlaying) return;
+
+
if (currentStep < solutionSteps.length) {
+
// Toggle the next button in the solution
+
const buttonIndex = solutionSteps[currentStep];
+
toggleButton(buttonIndex);
+
currentStep++;
+
+
// Use 10x faster speed for Part 2 (more button presses)
+
const delay = currentMode === 2 ? animationSpeed / 10 : animationSpeed;
+
setTimeout(animateSolution, delay);
+
} else {
+
// Mark this machine as solved
+
const machine = machines[currentMachineIndex];
+
let isCorrect;
+
if (currentMode === 1) {
+
isCorrect = currentState.every((state, i) => state === machine.target[i]);
+
} else {
+
isCorrect = currentState.every((state, i) => state === machine.joltages[i]);
+
}
+
+
if (isCorrect) {
+
solvedMachines.add(currentMachineIndex);
+
updateStats();
+
}
+
+
// Current machine done, move to next immediately
+
if (currentMachineIndex < machines.length - 1) {
+
if (isPlaying) {
+
currentMachineIndex++;
+
initMachine();
+
setTimeout(animateSolution, animationSpeed);
+
}
+
} else {
+
// All done
+
isPlaying = false;
+
document.getElementById('play').textContent = '▶ Play';
+
setTimeout(() => {
+
currentMachineIndex = 0;
+
initMachine();
+
}, animationSpeed * 4);
+
}
+
}
+
}
+
+
function initMachine() {
+
const machine = machines[currentMachineIndex];
+
showingSolution = false;
+
currentStep = 0;
+
+
if (currentMode === 1) {
+
// Part 1
+
currentState = new Array(machine.target.length).fill(false);
+
buttonStates = new Array(machine.buttons.length).fill(0);
+
+
const solution = solveMachine(machine);
+
solutionSteps = [];
+
solution.forEach((shouldPress, idx) => {
+
if (shouldPress === 1) {
+
solutionSteps.push(idx);
+
}
+
});
+
} else {
+
// Part 2
+
currentState = new Array(machine.joltages.length).fill(0);
+
buttonStates = new Array(machine.buttons.length).fill(0);
+
+
const solution = solveMachinePart2(machine);
+
solutionSteps = [];
+
solution.forEach((pressCount, idx) => {
+
for (let i = 0; i < pressCount; i++) {
+
solutionSteps.push(idx);
+
}
+
});
+
}
+
+
renderMachine();
+
updateStats();
+
}
+
+
// Initialize
+
initMachine();
+
</script>
+
</body>
+
</html>`;
+
+
await Bun.write(`${scriptDir}/index.html`, html);
+687
vis/10/index.html
···
···
+
<!DOCTYPE html>
+
<html lang="en">
+
<head>
+
<meta charset="UTF-8">
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
+
<title>AoC 2025 Day 10 - Factory</title>
+
<style>
+
* {
+
box-sizing: border-box;
+
}
+
body {
+
background: #1e1e2e;
+
color: #cdd6f4;
+
font-family: "Source Code Pro", monospace;
+
font-size: 14pt;
+
font-weight: 300;
+
padding: 20px;
+
display: flex;
+
flex-direction: column;
+
align-items: center;
+
min-height: 100vh;
+
margin: 0;
+
}
+
h1 {
+
color: #a6e3a1;
+
text-shadow: 0 0 2px #a6e3a1, 0 0 5px #a6e3a1;
+
margin-bottom: 10px;
+
font-size: 1em;
+
font-weight: normal;
+
}
+
.controls {
+
background: #11111b;
+
border: 1px solid #313244;
+
padding: 15px;
+
margin: 15px 0;
+
max-width: 1200px;
+
border-radius: 4px;
+
width: 100%;
+
}
+
.control-row {
+
display: flex;
+
gap: 15px;
+
align-items: center;
+
margin-bottom: 15px;
+
flex-wrap: wrap;
+
justify-content: center;
+
}
+
.control-row:last-child {
+
margin-bottom: 0;
+
}
+
button {
+
background: #11111b;
+
color: #a6e3a1;
+
border: 1px solid #313244;
+
padding: 8px 16px;
+
cursor: pointer;
+
font-family: inherit;
+
font-size: 14px;
+
border-radius: 3px;
+
}
+
button:hover {
+
background: #181825;
+
}
+
button:disabled {
+
opacity: 0.5;
+
cursor: not-allowed;
+
}
+
.speed-control {
+
display: flex;
+
align-items: center;
+
gap: 8px;
+
font-size: 13px;
+
color: #a6adc8;
+
}
+
.speed-control input[type="range"] {
+
width: 120px;
+
height: 6px;
+
background: #313244;
+
outline: none;
+
-webkit-appearance: none;
+
border-radius: 3px;
+
}
+
.speed-control input[type="range"]::-webkit-slider-thumb {
+
-webkit-appearance: none;
+
appearance: none;
+
width: 14px;
+
height: 14px;
+
background: #a6e3a1;
+
cursor: pointer;
+
border-radius: 50%;
+
border: 1px solid #313244;
+
}
+
.speed-control input[type="range"]::-moz-range-thumb {
+
width: 14px;
+
height: 14px;
+
background: #a6e3a1;
+
cursor: pointer;
+
border-radius: 50%;
+
border: 1px solid #313244;
+
}
+
.machine-display {
+
background: #11111b;
+
border: 1px solid #313244;
+
padding: 20px;
+
margin: 20px 0;
+
max-width: 1200px;
+
border-radius: 4px;
+
width: 100%;
+
}
+
.lights {
+
display: flex;
+
gap: 10px;
+
justify-content: center;
+
margin: 20px 0;
+
flex-wrap: wrap;
+
}
+
.light {
+
width: 50px;
+
height: 50px;
+
border-radius: 50%;
+
border: 2px solid #313244;
+
display: flex;
+
flex-direction: column;
+
align-items: center;
+
justify-content: center;
+
font-size: 9px;
+
transition: all 0.3s ease;
+
overflow: hidden;
+
text-align: center;
+
padding: 3px;
+
line-height: 1.1;
+
}
+
.light.off {
+
background: #1e1e2e;
+
color: #6c7086;
+
}
+
.light.on {
+
background: #a6e3a1;
+
color: #1e1e2e;
+
box-shadow: 0 0 10px #a6e3a1;
+
}
+
.light.target {
+
border-color: #f9e2af;
+
border-width: 3px;
+
}
+
.buttons-grid {
+
display: grid;
+
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
+
gap: 10px;
+
margin: 20px 0;
+
}
+
.button-display {
+
background: #181825;
+
border: 1px solid #313244;
+
padding: 10px;
+
border-radius: 4px;
+
text-align: center;
+
cursor: pointer;
+
transition: all 0.2s ease;
+
}
+
.button-display:hover {
+
background: #313244;
+
}
+
.button-display.pressed {
+
background: #a6e3a1;
+
color: #1e1e2e;
+
border-color: #a6e3a1;
+
}
+
.button-label {
+
font-size: 12px;
+
margin-bottom: 5px;
+
color: #a6adc8;
+
}
+
.button-toggles {
+
font-size: 11px;
+
color: #6c7086;
+
}
+
.stats {
+
background: #11111b;
+
border: 1px solid #313244;
+
padding: 10px 15px;
+
margin: 10px 0;
+
max-width: 1200px;
+
border-radius: 4px;
+
text-align: center;
+
font-size: 13px;
+
color: #a6adc8;
+
width: 100%;
+
margin-top: auto;
+
}
+
.info {
+
margin: 10px 0;
+
text-align: center;
+
color: #f9e2af;
+
}
+
a {
+
text-decoration: none;
+
color: #a6e3a1;
+
outline: 0;
+
}
+
a:hover, a:focus {
+
text-decoration: underline;
+
}
+
</style>
+
</head>
+
<body>
+
<h1>AoC 2025 Day 10 - Factory Machines</h1>
+
+
<div class="controls">
+
<div class="control-row">
+
<button id="togglePart" style="color: #f9e2af; font-weight: bold;">Part 1</button>
+
<button id="prev">← Previous Machine</button>
+
<button id="play">▶ Play</button>
+
<button id="next">Next Machine →</button>
+
<button id="reset">↺ Reset</button>
+
<div class="speed-control">
+
<label for="speed">Speed:</label>
+
<input type="range" id="speed" min="1" max="25" value="5" step="1">
+
<span id="speedValue">5x</span>
+
</div>
+
</div>
+
</div>
+
+
<div class="info" id="machineInfo">Machine 1 / 197</div>
+
+
<div class="machine-display">
+
<h2 id="displayTitle" style="text-align: center; color: #89b4fa; font-size: 18px; margin-bottom: 20px;">Indicator Lights</h2>
+
<div class="lights" id="lights"></div>
+
+
<h2 style="text-align: center; color: #89b4fa; font-size: 18px; margin: 30px 0 20px 0;">Buttons</h2>
+
<div class="buttons-grid" id="buttons"></div>
+
</div>
+
+
<div class="stats">
+
<div id="statsInfo">Buttons Pressed: 0 | Target: ? | Accumulated Total: 0</div>
+
<div style="margin-top: 5px; font-size: 11px;"><a href="../index.html">[Return to Index]</a></div>
+
</div>
+
+
<script type="module">
+
const machines = [{"target":[false,false,false,true,true,true,false,true,false,true],"buttons":[[1,8],[0,4,5,6],[2,3,4,5,6,7,8],[5],[0,3,5],[0,1,5,6,7,9],[0,7,9],[0,1,2,3,5,6,8,9],[0,1,2,3,4,5,7,8,9],[0,2,4,6,7,8,9],[1,2,3,4,6,7,8,9],[0,9]],"joltages":[65,41,48,35,50,67,76,68,55,61]},{"target":[true,true,false,true,false,false],"buttons":[[0,2,3,5],[0,2,3,4],[0,1,2,4],[1,4],[2,3,4,5],[1,4,5],[0,3,4],[3]],"joltages":[56,191,62,82,236,212]},{"target":[false,false,false,true,false],"buttons":[[2,3,4],[1,2],[1,2,3,4],[0,2,3],[3],[0,3,4]],"joltages":[194,25,212,218,39]},{"target":[true,true,true,false,false],"buttons":[[1,2],[1,2,3],[3,4],[0,1,2],[1,3,4]],"joltages":[12,52,35,43,28]},{"target":[true,false,false,true,true,true,true],"buttons":[[0,3,4,5,6],[0,1,3,5,6],[0,1,2,6],[0,3],[0,1,2,3],[4,5],[3,4]],"joltages":[47,46,31,136,104,19,27]},{"target":[true,false,true,false,true],"buttons":[[0,1,2],[1,2,3],[0,2,3],[1,2],[0,4],[1,3]],"joltages":[35,44,50,27,10]},{"target":[false,true,false,false,false,true,true,true,false],"buttons":[[4,5,6],[3,5,6],[0,2,4,6],[0,2,6,8],[0,1,8],[1,3],[0,1,2,4,5,7,8],[2,5,7]],"joltages":[39,33,32,11,41,35,37,15,29]},{"target":[false,true,false,true,true,true,true],"buttons":[[0,1],[0,4,5,6],[1,3,4,5],[1,5],[1,2,3],[1,2,3,6],[0,1,3,4,6]],"joltages":[43,87,30,61,37,26,44]},{"target":[false,true,true,true,true,true,true,false],"buttons":[[0,3,4,5,7],[1,2,4,5,6,7],[1,2,3,4,6,7],[0,1,2],[5,7],[0,1,2,3,4,6],[0,4,5],[2,3],[0,2,3,4,5,7],[0,1,5,7]],"joltages":[34,43,49,20,33,47,21,47]},{"target":[false,true,true,true,true,true],"buttons":[[0,3],[0,1,3,5],[1,2,3,4,5],[2],[0,1,2]],"joltages":[34,170,162,185,153,168]},{"target":[false,true,false,true],"buttons":[[1,3],[0,2,3]],"joltages":[154,10,154,164]},{"target":[false,false,true,false,true,true],"buttons":[[0,3,4],[2,4,5],[0,1,3,4,5],[0,1,3,5]],"joltages":[28,12,2,28,23,14]},{"target":[false,false,false,true,false],"buttons":[[1,2,3,4],[3],[1,2,4],[0,3],[1,4]],"joltages":[168,22,12,188,22]},{"target":[true,true,false,false,false],"buttons":[[1,2,4],[2,3],[2,3,4],[1,2],[1,2,3],[0,2],[4]],"joltages":[3,30,36,15,11]},{"target":[false,false,true,true],"buttons":[[1],[1,2],[2,3],[2],[0,1,3],[0,3]],"joltages":[11,11,143,25]},{"target":[false,true,true,true,false,false,true,false,false],"buttons":[[1,2,4,5,7,8],[0,3,4,5,7,8],[1,3,7,8],[5,7],[6],[0,1,3,4,6],[0,1,2,4,5,6,7,8],[1,3,4,6,7],[0,2,3,4,7,8],[1,5,6],[3,4,5,6,7,8]],"joltages":[49,151,36,57,71,160,141,79,63]},{"target":[false,true,false,true],"buttons":[[1,3],[2,3],[1,2],[0,1],[0,1,3]],"joltages":[23,48,18,47]},{"target":[false,true,false,false,false,false,false,false,true],"buttons":[[0,2,4,6],[1,4,5],[0,2,3],[0,2,4,7,8],[1,3,5,6,7,8],[3,7],[2,3,4,7,8],[1,8],[0,2]],"joltages":[42,20,228,213,224,19,14,205,201]},{"target":[true,false,false,true,false],"buttons":[[4],[0,1,3],[2,3,4],[1],[0,3],[3,4],[1,2,4]],"joltages":[14,29,10,18,29]},{"target":[false,true,true,true,true,true,false,true],"buttons":[[0,1,5,7],[0,4,5,6,7],[2,6],[2,3,5],[1,4,5],[3,5,7],[1,2,3,4,5,6,7]],"joltages":[13,42,24,35,37,68,25,45]},{"target":[true,true,true,false,true,true,true,false,true],"buttons":[[4,6,7],[2,4,6,7],[0,1,4,5],[2,3,4,5,6,7,8],[1,8],[1,2,3,4,6,8],[2,5,6],[0,2,3,5,6,8],[0,5,6,7,8],[1,2,4,6,8]],"joltages":[27,15,61,25,57,58,94,57,47]},{"target":[true,true,false,true,true,false,false,false,false],"buttons":[[0,1,2,5,6,7,8],[0,1,2,3,6,7],[0,1,2,6,7],[2,3,6],[0,3,4,7,8],[0,1,2,4,6],[5,7,8],[4,6,7]],"joltages":[47,45,61,37,32,209,77,249,211]},{"target":[false,true,true,false,true,true,false,true,false,true],"buttons":[[2,4,7,9],[1,4,5,8],[0,1,3,5],[1,4,5],[7],[1,2,8,9],[2,3,7,8],[0,1,2,3,4,7,8],[0,5],[0,2,3],[1,2,5,6,7,8,9],[0,1,2,3,5,9],[4,6,7,9]],"joltages":[69,76,81,72,49,58,6,51,46,40]},{"target":[true,true,false,false],"buttons":[[0,2],[0,1,3],[0,1]],"joltages":[26,6,20,2]},{"target":[false,true,false,true,false,true,false],"buttons":[[0,1,6],[0,3,4],[1,2,3,6],[1,2,3,4,5],[1,2,3,5,6],[0,1,2,3]],"joltages":[21,33,28,34,7,7,22]},{"target":[true,false,false,true,true,false,true,true,true,true],"buttons":[[8],[3,5],[1,3,4,6],[4,5,7,8],[2,3,4,6,9],[0,1,4,6,7,9],[1,2,3,4,5,6],[1,4,5,6,7],[1,5,6,7],[6,9],[3,6],[0,1,2,3,4,5,8,9]],"joltages":[25,161,35,166,175,74,190,42,29,50]},{"target":[true,false,false,true,false],"buttons":[[0,2,4],[1,4],[0,3]],"joltages":[22,5,20,2,25]},{"target":[false,false,false,false,false,false,false,true,false,false],"buttons":[[0,3,4,5],[2,3,5,6,8,9],[1,2,3,5,7,8],[0,1,3,4,7],[0,2,3,4,5,6,7],[1,2,5,6,7],[0,1,3,6,8,9],[0,2,6],[0,2],[0,1,3,4,5,7,8]],"joltages":[79,31,88,74,43,75,58,49,44,20]},{"target":[false,true,true,false,false,true,true,true,false],"buttons":[[0,2],[1,6],[7,8],[1,3,7],[2,3],[3,4,7,8],[0,2,3,4,5,7],[4,7],[1,2,5,6,7],[0,2,3,4,5,8]],"joltages":[19,38,37,33,26,30,21,65,31]},{"target":[true,true,true,false,false,true,false,false],"buttons":[[5,6],[0,4],[0,1,2,4,5,7],[0,3,5],[1,2,3,5,6],[0,2],[0,1,2,4,7],[0,3,6]],"joltages":[55,49,51,38,32,53,23,32]},{"target":[false,false,true,true,false,true],"buttons":[[1,5],[0,1,2,3,4],[0,1,3],[2,4],[0,3,4],[0,2,4,5]],"joltages":[122,133,27,118,28,20]},{"target":[true,false,false,false,true,false,true],"buttons":[[0,1,2,6],[1,3,6],[0,3,4,5,6],[1],[0,1,4,5,6],[0,4,5],[2,3,4,5,6],[2,3,4]],"joltages":[47,37,38,37,55,37,47]},{"target":[true,true,false,true,true,true],"buttons":[[0,1,3,4,5],[1,4],[0,5],[1,3,4,5],[1,2,3,5],[0,2,3,4,5]],"joltages":[36,43,22,54,47,57]},{"target":[false,true,true,false,false,false,true,false,false],"buttons":[[0,1,3,4,5,7],[0,1,2,3,4,6,8],[0,4,8],[1,5,6,7],[0,1,5,6,7,8],[0,2,4,5,7,8],[0,1,3,5,6]],"joltages":[78,68,23,32,40,77,62,58,53]},{"target":[false,false,true,true,false,false,false,false,false],"buttons":[[0,4,6,7,8],[1,2,3,5,7],[3,6],[1,3,4],[0,1,2,4,5,6,7,8],[0,1,2,3,4,5],[0,5,6],[2,5,6]],"joltages":[34,44,55,49,35,59,55,33,18]},{"target":[false,true,true,false,true,false,true,false,false,true],"buttons":[[1,2,3,6,8,9],[1,2,5,7,8],[3,7,9],[1,2,4,6,9],[1,2,4,6,8,9],[1,2,5,6,7,8,9],[0,2,5,6,7,8],[0,3,4,6,7,9],[0,2,5,6,7,8,9]],"joltages":[20,44,61,26,25,34,59,55,44,62]},{"target":[true,false,true,false],"buttons":[[0,1,3],[0,2]],"joltages":[213,18,195,18]},{"target":[true,false,false,true,true,false],"buttons":[[3,4],[0,1,2,5],[2,5],[0,2,3,4],[0,1,3,4,5],[0,5]],"joltages":[27,12,27,15,15,41]},{"target":[false,true,true,false,false],"buttons":[[0],[1,2,3],[0,4],[1,2],[0,1,2,3],[3,4],[1,3]],"joltages":[42,207,201,207,36]},{"target":[false,true,true,false,true,false,false],"buttons":[[1,2,3,4,5],[0,3],[2,3,4],[1,3,6],[1,2,4,5,6],[0,1,3,4],[0]],"joltages":[34,123,34,153,35,14,114]},{"target":[true,false,true,false,true,false,true],"buttons":[[1,3,5,6],[0,5],[3,6],[1,2,3,4],[0,2]],"joltages":[33,22,29,26,16,26,10]},{"target":[true,false,false,false,true,true,false,false,false],"buttons":[[0,1,2,4,5,6,7],[0,1,2,8],[0,2,3,4,6,7,8],[0,2,3],[1,2,3,4,6,7,8],[0,1,2,3,5,6,8],[1,3,5,6],[1,2,4,5,6],[0,5,6,8]],"joltages":[53,48,74,47,55,29,61,48,42]},{"target":[true,true,false,true,false],"buttons":[[1,3,4],[0,4],[1,4],[0,1,2,3],[1,2,4]],"joltages":[177,213,173,193,44]},{"target":[false,true,false,true,false,true,true,false,true],"buttons":[[1,3,7],[8],[0,1],[4,5],[4,5,8],[0,3,4,5,6,7,8],[2,7],[2,4,6],[0,2,3]],"joltages":[22,15,30,9,21,9,15,17,24]},{"target":[true,false,false,false,false,false,false,true,false,true],"buttons":[[0,1,2,4,6,7,8],[1,3,7,9],[5,7],[0,2,4,6],[2,4,5,7,9],[3,5,7],[0,1,2,5,6,9],[0,7,8]],"joltages":[54,27,50,24,36,58,34,77,28,35]},{"target":[true,false,true,false,false,true,true],"buttons":[[0,1,3],[0,2],[1,2,4,6],[3,5],[5,6],[0,4,6],[0,1,3,5,6],[2,6]],"joltages":[33,28,31,20,26,14,44]},{"target":[true,false,false,true,true],"buttons":[[0,1],[2,3],[1,3,4],[0,1,4]],"joltages":[175,177,0,2,168]},{"target":[false,true,true,true,false,false,false,true,true,false],"buttons":[[8],[0,3,4,5,6,7,8,9],[0,4,5,9],[0,1,2,3,5,7,8],[2,3,4,5,6,7,9],[1,2,3,6,7,9],[0,1,2,3,4,5,7,8],[2,3,5,8,9],[6,8,9],[1,2,3,4,5,6,7,9],[1,4,6,8,9],[0,3,6,9],[0,2,3,7]],"joltages":[65,50,69,97,72,86,95,82,68,117]},{"target":[true,false,false,true,false,true,false,false,false,false],"buttons":[[0,2,4,7],[1,8,9],[0,1,3,4,6,7,8,9],[8],[0,1,3,4,5,6,9],[1,3,5,6,7],[0,3,5,6,7],[1,3],[0,3,5],[0,1,4,8],[0,1,2,4,5,7,8,9]],"joltages":[80,81,27,53,70,31,38,56,62,53]},{"target":[true,false,false,false],"buttons":[[0,1,2],[1,3],[1,2],[0,2],[2,3]],"joltages":[19,41,38,23]},{"target":[false,true,true,false,false],"buttons":[[1,2],[1,3,4],[0,3]],"joltages":[20,29,9,40,20]},{"target":[false,false,true,false,true,false],"buttons":[[3,4,5],[2,3,5],[0,1,2,5],[3,5],[0,1,2],[2,3,4,5],[2,3]],"joltages":[27,27,76,67,25,72]},{"target":[true,true,false,true,true,false,false,false,true],"buttons":[[7,8],[0,2,4,5,7,8],[1,4,6,7],[2,4,5,6],[2,3,4,5,6],[0,1,3,5,6,8],[1,5,7,8],[0,2,5,8],[0,1,3,6],[2,3,4,5,6,7,8],[0,2,3]],"joltages":[56,44,44,48,44,68,60,44,61]},{"target":[true,false,false,true,false],"buttons":[[0,2,3,4],[0,1,2,3],[1,2,3],[2,4]],"joltages":[12,13,132,25,119]},{"target":[false,false,true,false,false,false,true],"buttons":[[1,2,4],[2,3,4],[2],[0,1,4,5,6],[2,4],[0,1,2,4],[0,2,3,4,5],[0,2,4,5,6],[0,1,2,3,6]],"joltages":[58,42,71,22,64,34,49]},{"target":[false,false,true,true,false],"buttons":[[0,2,4],[0,1,2,3],[0,1,4],[1,4],[2,3,4],[1,2,4]],"joltages":[22,44,18,11,41]},{"target":[true,false,true,false],"buttons":[[0,1,3],[0,2]],"joltages":[21,1,20,1]},{"target":[true,false,false,false],"buttons":[[0,3],[0,1,3],[0,2,3],[1],[1,2,3],[2,3]],"joltages":[120,35,134,153]},{"target":[false,true,false,true,true,false,true],"buttons":[[1,3,4,6],[0,1,2,4,5,6],[0,1,2,4,5],[0,2,6],[2,3,5],[4]],"joltages":[54,48,67,27,55,47,50]},{"target":[true,true,false,true],"buttons":[[0,2,3],[0,1,3]],"joltages":[18,17,1,18]},{"target":[true,false,true,true,false,false,false,false,false,true],"buttons":[[0,2,3,9],[6,8],[1,6,7],[4,5,6],[0,1,3,4,8,9],[3,4,5,6,8],[0,3,7,8],[0,2,3]],"joltages":[22,19,19,28,16,15,36,20,12,1]},{"target":[true,true,false,true,false],"buttons":[[0,2,3],[0,1,4],[1,3,4],[1,4],[0,1,3],[1,3]],"joltages":[19,62,1,36,42]},{"target":[true,false,true,true,true],"buttons":[[1,3,4],[0,2,3,4],[2,3]],"joltages":[12,19,30,49,31]},{"target":[false,false,false,true,true],"buttons":[[0,1,4],[1,2,3,4],[0,2],[0,3],[3,4],[1,2],[0]],"joltages":[18,19,18,18,18]},{"target":[true,false,false,true,false,false,true,false,true],"buttons":[[0,1,4],[5,7,8],[2,5,6,7,8],[0,4,5,6],[0,2,3,4,6,8],[1,3,4,5,6,7],[0,2,3,5,6,7,8],[0,1,2,3,4,6,7],[1,2,3,6,7,8],[2,4,5,7]],"joltages":[209,187,45,48,215,71,78,64,43]},{"target":[true,true,false,false,false,false,true,false],"buttons":[[2,3,4,7],[1,4,5],[0,3,4,5],[0,1,2,5,7],[1,4],[0,1,4,6],[0,3,4],[0,6,7]],"joltages":[30,38,108,107,138,10,17,108]},{"target":[false,false,true,true,true,false,true,true,true,false],"buttons":[[0,9],[1,7],[0,1,2,3,5,6],[2,5,7,8],[0,2,3,4,5,7,9],[1,2,3,4,5,7,8,9],[1,2,3,4,5,6],[0,1,2,5,6,8],[0,1,2,4,5,6,7,8],[0,1,2,5],[0,1,2,4,6,7,8,9]],"joltages":[82,105,103,33,55,85,74,77,79,37]},{"target":[true,false,true,false,true,false,true,true,false],"buttons":[[1,2,3,4,5,6,7],[1,6,8],[2,3,5],[5,6],[1,2,4,6,7],[0,1,2,7,8],[0,2,3,4,5,7,8],[0,1,3,4,5,6,8]],"joltages":[37,45,79,49,42,52,30,59,40]},{"target":[true,false,false,false,true,true,false],"buttons":[[0,2,3,4,5],[0,3,6],[0,4,5],[1,3,5,6],[1,2,4,5],[4,6],[0,2,3,4,5,6]],"joltages":[27,18,22,34,33,29,45]},{"target":[true,false,false,true,true,false,true,false],"buttons":[[0,1,4],[0,5,7],[1,2,4,5,6],[2],[0,5],[3,4,6,7],[0,2,3,4,6]],"joltages":[24,171,185,10,181,178,176,7]},{"target":[true,false,false,true,false,true,true,false],"buttons":[[0,3,4,6],[4,6],[0,4,5],[1,2,3,4,5,7],[0,1,2,3,6],[0,1,2,4,6,7],[1,2,3],[1,2,3,4]],"joltages":[62,61,61,57,84,21,65,22]},{"target":[true,false,true,false,true,true,false],"buttons":[[0,1,2,4,5],[3,6],[1,2,4,5,6],[1,3,5,6],[0,1,6],[1,2]],"joltages":[16,149,136,27,17,25,38]},{"target":[true,false,true,false,true,false,false,true,false,true],"buttons":[[0,3,6,7,9],[0,2,3,5,6,7,8,9],[3,6,8],[0,2,5,6,9],[2,3,4,7],[0,1,2,4,5,6,7,8],[0,1,3,4,5,6,7,9],[0,1,2,3,7,9],[5,8,9],[2,5,8,9],[3]],"joltages":[54,41,64,92,37,43,52,67,47,59]},{"target":[true,true,false,false,true,false],"buttons":[[3,4,5],[1,5],[1,2,4],[1,4],[1,2],[0,3,5],[0]],"joltages":[23,47,31,10,33,12]},{"target":[true,false,false,true,true,false,true],"buttons":[[2,4],[1,3,4,5],[0,1,5,6],[0,2,4,5,6],[0,1,4,5,6]],"joltages":[47,41,24,12,55,59,47]},{"target":[true,false,true,false,true,true,false,true],"buttons":[[0,1,2,4,5,7],[0,2,3,6,7],[0,3,4,5],[3,4,5,6],[0,1,3,5,6,7],[1,2,4,5,6,7],[0,2,3],[2,4,5,6,7],[1,7]],"joltages":[32,34,35,34,44,47,32,42]},{"target":[false,false,true,false,true,false,false,false,false,true],"buttons":[[0,2,3,5,6,7,8,9],[1,3,4,5,6,7,8,9],[0,2,7,8,9],[5,6,9],[3],[0,1,4,5,9],[1,5,9],[0,1,2,3,4,5,8],[2,5],[4,8]],"joltages":[26,38,191,38,31,233,23,8,24,46]},{"target":[false,true,false,false,false,false,true,false,true,false],"buttons":[[2,3,4,8],[0,1,2,5,6,7,9],[0,2,3,4,7,8,9],[0,2,3,5,6,7,8,9],[1,3],[4,5,6,9],[0,3,4,5,6,7,8],[0,8,9],[3,4,5,7,8,9],[0,1,2,3,4,6,8,9],[1,2,5,6,7,8,9],[3,4,5]],"joltages":[70,55,62,73,59,77,79,59,69,100]},{"target":[true,false,false,false,true,true,true,false,false,false],"buttons":[[0,3,6,9],[5,8,9],[1,2,3,4,6,8,9],[1,2,5,7],[0,1,2,3,4,6,7,8],[1,2,3,4,6,7,8,9],[3,5],[1,5,6,7,8,9],[4,5,6],[1,2,3,4,5,6,7,9]],"joltages":[33,65,60,67,57,30,75,48,63,62]},{"target":[true,false,true,true],"buttons":[[1,2],[0,1],[0,2,3]],"joltages":[8,22,16,1]},{"target":[true,true,false,false,true,true],"buttons":[[1,2,5],[0,1,2,3,5],[0,3,4],[0,2,4]],"joltages":[20,11,21,10,17,11]},{"target":[false,true,false,true],"buttons":[[1,3],[0,2],[0,3]],"joltages":[21,10,9,22]},{"target":[true,false,false,true,true,false,true,true],"buttons":[[0,1,2,3,4,6,7],[3,4,7],[2,3,7],[2,3,4,5,7],[2,3,5,6],[2,3,6,7],[3,4],[1,3,7],[0,4,5,6],[2,3]],"joltages":[3,14,61,108,49,34,27,62]},{"target":[true,true,true,true,true,true,true,true,false,false],"buttons":[[0,2,3,4,9],[0,3,6,7,8,9],[0,1,2,3,4,5,6,7],[4,5,7,9],[0,1,2,3,4,7,8,9],[0,2,3,4,6,7,8,9],[1,3,5,6,8,9],[0,1,4,5,8,9],[0,2,3],[1,8],[0,5,8]],"joltages":[58,39,41,60,41,33,38,48,46,47]},{"target":[true,false,false,true,false,true,false,false,true],"buttons":[[0,3,6,7],[3,4,6,7],[0,2,5],[0,5,8],[0,6],[0,1,2,3,4,5,7,8],[1,3,4,6,7,8],[0,3,5,8],[4,7],[0,1,3,4,7,8]],"joltages":[49,22,13,36,43,26,47,47,35]},{"target":[false,true,false,false,false,false,false],"buttons":[[1,2,3,4,5],[1,2,3,4],[1,2,3,4,6],[0,2,4,6],[0,1,2,4,5]],"joltages":[6,29,33,27,33,18,8]},{"target":[true,true,false,true,true,true,false,true,false,true],"buttons":[[0,2,5,6,8],[1,2,3,4,5],[0,2,3,5,7,8,9],[0,1,2,4,5,6,9],[2,3,6,7,9],[0,1,2,3,4,5,7,9],[0,2,9],[2,3,4,7,9]],"joltages":[38,39,69,47,42,56,30,28,17,39]},{"target":[false,false,true,true,false,true,false],"buttons":[[0,1,3,4,5],[2,5],[0,1,4,5],[1,4,6],[0,3,4]],"joltages":[128,128,12,21,142,126,14]},{"target":[true,true,true,false],"buttons":[[1,3],[0,2,3],[3],[0,1],[2],[1]],"joltages":[24,41,14,44]},{"target":[true,true,false,true,true,false,false,false],"buttons":[[0,1,4,6,7],[0,1,3,4],[4,6],[0,2,3,4],[6,7],[3,5,6],[0,2,3,5,7]],"joltages":[38,20,18,31,42,23,54,42]},{"target":[true,false,true,false,false],"buttons":[[0,2,3],[3,4],[0,3],[4],[1,2],[0,1]],"joltages":[42,175,174,42,14]},{"target":[false,true,true,true,true,true,true,true],"buttons":[[0,2,6],[0,1,2,3,5,6],[1,7],[2,4,5,6,7],[1,2,4,5],[2,3,4,5,6]],"joltages":[2,8,22,7,20,20,22,21]},{"target":[false,true,false,true,true,true,false,true,true,true],"buttons":[[3,7,8],[0,8,9],[1,2,3,4,5,7,8,9],[0,1,2,3,5,6,9],[0,1,2,3,4,6,7],[0,1,2,3,5,6,8,9],[0,4,6,8],[0,1,2,4,8,9],[0,1,5,8]],"joltages":[191,63,54,46,150,41,166,15,177,48]},{"target":[true,false,true,false],"buttons":[[1,2,3],[0,2]],"joltages":[11,14,25,14]},{"target":[true,false,false,false],"buttons":[[0,3],[1,2,3],[3],[0,1,2],[2],[0,2]],"joltages":[7,7,14,22]},{"target":[false,false,false,false,true,true,false,false],"buttons":[[5,7],[0,6],[2,7],[1,2,3,5,6,7],[0,3,4,5,6,7],[0,1,3,5,7],[1,4],[0,1,2,3,5,7],[0,1,2,3,4,5,7]],"joltages":[37,30,22,26,13,31,14,31]},{"target":[true,false,false,false,true,true,false,false,false,false],"buttons":[[0,2,7],[2,5],[0,1,4,5,6,9],[0,1,6,7,8,9],[0,2,3,4,5,7,8],[0,2,3,4,5],[1,2,3,5,6,7,8],[0,1,2,6],[1,2,4,6],[3,8,9]],"joltages":[76,83,91,53,48,56,83,51,57,48]},{"target":[true,false,true,true,false,true,true,true,true],"buttons":[[0,1,3,4,6,7,8],[0,2,3,5,6,7,8],[2,4],[2,3,4,5,6,7,8],[0,1,3,4,5,7,8],[5,6],[2,3,6,7,8]],"joltages":[31,27,50,68,55,45,60,68,68]},{"target":[false,false,true,false,false,false,false,true,true],"buttons":[[0,1,4,5,6,7,8],[0,4,6,7,8],[1,3,4,5,7,8],[1,2,6,7,8],[0,2,3,4,8],[1,2,4,5],[0,4,5,6,7],[0,1,3,4,6,7,8]],"joltages":[52,52,40,41,71,35,43,53,68]},{"target":[false,true,false,true],"buttons":[[1,3],[0,2]],"joltages":[19,106,19,106]},{"target":[false,true,false,true],"buttons":[[0,3],[1,2,3],[1,2],[2],[0,1,3]],"joltages":[20,44,28,31]},{"target":[true,true,true,true,false],"buttons":[[0,2,4],[1,2],[0,1,2,3],[0,2,3,4],[1]],"joltages":[134,128,137,125,10]},{"target":[true,true,true,false,false,false,true,true],"buttons":[[0,4,5,6,7],[0,1,2,5],[1,4,5,7],[0,1,5],[2,3,4,7],[0,2,5,6,7],[0,2,3,6],[1,3,5],[0,1,2,3,6,7],[1,2,4,5,6]],"joltages":[201,193,197,35,42,211,32,55]},{"target":[false,false,true,false,true,true],"buttons":[[2,3,4,5],[0,1,2,3,5],[1,4],[0,1],[0,3,4],[0,3,5]],"joltages":[29,31,12,23,24,17]},{"target":[true,false,false,true],"buttons":[[2],[0,1],[0,1,2],[1,2],[3],[0,1,3]],"joltages":[23,25,25,20]},{"target":[false,true,true,false,true,true,false,false,true,false],"buttons":[[2,4,9],[0,1,3,4,5,6,8,9],[2,4,5,6,7],[1,2,3,4,6,7,8,9],[0,4,5,7,8],[0,3,4,6,7,8,9],[1,2,4,5,6,7,9],[0,3,4,5,6,7,8]],"joltages":[17,16,30,28,47,16,41,41,28,36]},{"target":[true,false,false,true,false,true],"buttons":[[0,3,5],[1,3,4],[1,3,5],[0,2,3,5],[4,5]],"joltages":[24,173,9,197,12,209]},{"target":[false,false,true,false,true],"buttons":[[0,1,3,4],[1,2,3],[0,1,2,4],[0,2,3]],"joltages":[160,25,158,146,22]},{"target":[true,true,true,false,false,true,true,true],"buttons":[[1,2,4,5,7],[0,2,3,5,7],[0,3,4,5,6,7],[1,2,6,7],[0,1],[1,2,4,7],[3,4,5,7],[0,2,3,5,6,7]],"joltages":[46,41,57,45,49,65,42,79]},{"target":[true,false,true,true],"buttons":[[1,2,3],[2,3],[0,2,3]],"joltages":[14,1,18,18]},{"target":[false,true,true,false,true,true,true,true,true,true],"buttons":[[1,2,3,4,5],[0,2,7],[0,2,4,5,6,7,8,9],[6,8,9],[0,1,3,4,6,8,9],[5],[5,6,9],[0,1,4,5,7,8,9],[0,2,3],[0,1,2,6,7,8,9],[1,2,5,6,7,8,9]],"joltages":[58,38,41,16,30,38,65,43,58,72]},{"target":[false,true,false,false,false,true,true,false,true],"buttons":[[0,1,2,3,4,6,7,8],[0,2,3,4,5,7],[0,1,5,6],[0,2,3,4,5,6,7],[0,1,2,6,7,8],[2,3,4,5,7],[0,2,4,7],[3,5,8]],"joltages":[220,14,230,224,217,223,32,230,32]},{"target":[true,true,true,true,false,false,true,false,false],"buttons":[[0,2,5],[3,4],[0,2,4,5],[0,4,5,7],[0,2,4,5,6,8],[0,1,5,8],[0,1,2,6,7],[0,1,3,4,5,7,8],[0,1,4,5,6],[0,2,3,4,5,6,8],[0,4,5,7,8]],"joltages":[302,229,63,40,99,283,47,64,243]},{"target":[false,false,false,true,false,true,false],"buttons":[[0,2,3,4,5],[3,4,5,6],[0,1,3,4,6],[3,4,5],[1,2,3,4,6],[0,3,6],[0,2,5],[0,1,5],[0,2,4,5,6]],"joltages":[87,25,61,70,76,80,58]},{"target":[true,true,true,false,false,false,false,false,false],"buttons":[[0,1,3,6,7,8],[3,6],[2,3,4,5,6,7],[0,4,8],[1,5,6,8],[0,1,3,4,6,7],[0,1,2,4,6,7,8],[1,2],[1,2,6]],"joltages":[145,188,47,160,29,35,188,157,156]},{"target":[false,false,false,true,true,false,true],"buttons":[[3,4,6],[0,1,3,4,6],[0,2,3,6],[3],[0,6],[4,5,6],[0,1,2,4,5],[0,3,5],[1,4,5,6]],"joltages":[38,26,19,40,39,21,35]},{"target":[true,true,true,true,false,false,true,true],"buttons":[[0,1,2,4,7],[1,6],[0,1,3,6],[0,7],[2,6],[0,1,3],[1,2,4,7],[3,5,6,7]],"joltages":[28,38,208,23,24,12,210,43]},{"target":[false,true,false,false,false,false,false],"buttons":[[0,1],[0,3,4,6],[2,3,4,6],[4,5,6],[1,2,4,5,6],[0,1,3,4,5],[3,4,6]],"joltages":[44,44,23,55,83,47,64]},{"target":[true,false,true,false,true,true,false,false,false,false],"buttons":[[0,1,2,3,7,8],[2,4,5,7,8],[0,1,3,4,8,9],[0,5,7,9],[3,4],[0,1,2,3,4,5,8,9],[0,1,2,3,4,5,6,7,9],[0,2,3,4,6,8,9]],"joltages":[48,26,154,61,184,135,23,130,167,47]},{"target":[true,true,false,true,true,true,true,true,true,true],"buttons":[[2,3,5,6,8,9],[0,5,9],[1,2,9],[0,2,3,4,5,6,7,8],[2,6,8],[0,3,5,6],[0,1,2,3,4,5,7,9],[3,4,9],[0,2,5,6,8],[3,7]],"joltages":[35,17,158,154,7,167,147,13,141,171]},{"target":[true,false,true,true,false,true,false,false],"buttons":[[0,3],[0,2,4],[1,2,3,5,6],[0,1,2,3,6],[1,2,3,4,5,7],[2,3],[3,4],[2,3,4,7],[0,1,2,7],[0,1,6,7]],"joltages":[72,60,68,67,41,16,39,45]},{"target":[true,true,true,false,false],"buttons":[[3],[1,2,3],[0,1,2,3],[3,4],[0,1,4],[0,3,4],[0,2]],"joltages":[37,26,24,34,18]},{"target":[false,false,false,true,false,false,false,true,true,true],"buttons":[[2,3,5],[0,3,4,5,6,9],[3,6],[2,8],[0,1,4,5,6,7,9],[1,3],[0,1,3,4,5,6,7,8,9],[5,7,9],[0,2,4,8]],"joltages":[50,36,32,66,50,63,46,33,22,48]},{"target":[true,false,false,true],"buttons":[[0,1,3],[0,2,3],[1],[1,2]],"joltages":[16,181,165,16]},{"target":[true,false,true,false],"buttons":[[0,2],[0,1,3]],"joltages":[19,15,4,15]},{"target":[true,true,false,true,true,true,true],"buttons":[[0,1,3],[0,4,5,6],[0,1,3,4,5,6],[0,2,4,5,6],[0,1,2,4,5,6],[2,3,4]],"joltages":[28,18,38,24,43,24,24]},{"target":[true,false,false,true,false,false],"buttons":[[0,3],[1,2,3,4],[1,2,4,5],[0,1,2,3,4,5]],"joltages":[19,227,227,33,227,213]},{"target":[true,false,true,true],"buttons":[[1,2,3],[0,1],[1,2],[2,3]],"joltages":[17,49,32,12]},{"target":[false,true,false,true,true],"buttons":[[0,1,3],[3,4],[2],[0,2,4]],"joltages":[16,13,20,28,18]},{"target":[true,true,false,false],"buttons":[[2],[0],[3],[0,2],[1,3],[0,2,3]],"joltages":[15,15,33,31]},{"target":[false,true,true,false,true,false,true,true,true,false],"buttons":[[1,6,8],[6,7],[0,1,2],[1,5,6,7,9],[2,3,4,5,6,8,9],[7,8],[2,4,5,6,7,8],[3,6,7,9],[0,1,3,5,6,7,8,9],[1,2,3,5,6,7],[0,2,5,6,8,9],[0,2,3,4,5,8,9]],"joltages":[19,59,26,37,9,46,82,69,41,50]},{"target":[true,false,true,false,false,false,true],"buttons":[[0,1,4,6],[0,3],[3,6],[1,2,4,5,6],[0,1,5],[1,4,5,6],[0,1,2,3,5],[0,1,4,5,6],[1,3,4,6]],"joltages":[51,67,24,33,42,59,42]},{"target":[true,true,true,true],"buttons":[[1,3],[0,1,2,3]],"joltages":[12,16,12,16]},{"target":[false,true,false,true,false],"buttons":[[0,2,3],[0,3,4],[0,1],[0,2],[0,3],[3],[0,1,2]],"joltages":[58,8,27,181,16]},{"target":[false,false,true,false,false,false,false],"buttons":[[2,3],[2,6],[2,3,5],[0,1,3,4,5],[4,6],[0,3,5,6],[0,6],[1,2,4,5,6]],"joltages":[19,26,59,29,26,44,49]},{"target":[true,true,false,false],"buttons":[[0,1,3],[3],[0],[0,1,2]],"joltages":[35,28,10,25]},{"target":[true,false,false,true,true,false,true],"buttons":[[0,2,3],[1,4],[1,2,3,5,6],[0,4],[2,3],[0,3,4],[4,6],[0,2,4,5,6],[0,3,4,6]],"joltages":[62,8,36,54,72,20,49]},{"target":[true,true,false,false,true,true,false,false,false],"buttons":[[0,2,3,4,8],[0,1,8],[0,1,3,4,5,6,7,8],[0,3,4,5,6,7,8],[2,5,7,8],[0,1,2,3,6,8],[0,6,7],[3,5,8],[2,7]],"joltages":[57,32,170,62,35,43,37,178,72]},{"target":[false,true,true,false,false,false,true],"buttons":[[0,2,3,5],[1,2,3,4,5],[0,1,2,5],[0,1,4,6],[0,5,6]],"joltages":[52,33,32,15,16,38,21]},{"target":[false,false,false,false,true,false],"buttons":[[0,2,3],[0,2],[3,5],[0,1,2,3,5],[1],[3,4]],"joltages":[12,17,12,24,5,17]},{"target":[false,false,false,false,true,false,false,true,false,false],"buttons":[[2,6],[0,2,3,4,5,6,7,8],[0,1,3,7,8,9],[3,4,9],[0,1,2,3,4,5,6,9],[1,3,5,7,8,9],[0,2,3,4,6,7,9],[0,1,8],[1,3,4,8],[0,1,3,4,6,7,8,9]],"joltages":[41,47,28,70,62,27,43,32,44,52]},{"target":[true,false,true,true,false,true,false],"buttons":[[1,2,4,6],[1,2,3,4],[0,2,3,5,6],[0,2],[0,1,3,4,6]],"joltages":[28,18,46,29,18,20,29]},{"target":[true,true,false,false,true,false],"buttons":[[1,2,4,5],[5],[0,2],[0,1,2,4],[0],[4,5],[1,3,4,5],[3,4,5]],"joltages":[33,34,37,192,225,221]},{"target":[true,true,false,false,false,true,true,false],"buttons":[[0,3,4],[2,5],[1,4],[2,4,6],[0,1,3,7],[0,2,4,6,7]],"joltages":[164,10,193,10,185,20,173,158]},{"target":[false,false,false,false,false,false,false,true],"buttons":[[4,5],[1,2,4,7],[0,5,7],[1,4],[1,2,3,4,5,6,7],[1,2,3,4,5,7],[0,3,5,6,7],[0,1,2,5,6,7]],"joltages":[44,63,52,44,62,80,38,85]},{"target":[true,true,true,true,false,false,true,false,true,true],"buttons":[[0,3,5,8,9],[0,2,9],[1,3,5,6,7,8,9],[7,8],[0,2,3,4,5,8,9],[4,8,9],[0,1,3,4,5,6,7,9],[0,1],[0,1,2,3,4,5,7,9],[0,2,4,5,6,7],[1,3,6,8],[0,1,4,9],[4,6]],"joltages":[178,69,47,175,63,177,53,67,149,185]},{"target":[false,true,true,false,false,true,true,true,true],"buttons":[[3,4,6],[0,3,4,5,6,7,8],[4,5,8],[0,1,2,3,5,6,7,8],[4,5],[1,2,4,7],[6],[1,3,7,8]],"joltages":[29,40,24,62,75,62,54,55,61]},{"target":[true,true,false,true,true,true,false],"buttons":[[0,1,2,3,4],[0,3,6],[0,3,5,6],[3,5],[0,4],[0,1,3,4,5]],"joltages":[249,205,200,242,214,25,35]},{"target":[true,true,false,false,false,false,true,true],"buttons":[[1,3,4,6],[1,2,4,5,6,7],[0,1,3,4,5,7],[0,1,2,3,5,6],[2,3,4,5,6,7],[0,3,4,6,7],[0,4,5]],"joltages":[43,37,32,45,52,55,46,22]},{"target":[true,true,false,false,false,false,true,true,true,false],"buttons":[[2,6,8,9],[3,9],[2,4,6],[5,6,7],[4,7],[0,1,2,3,7],[2],[1,5,6,9],[0,1,3,6,8,9],[3,4,5,6],[1,2,3,4,5,6,8],[0,1,3,4,6,8],[9]],"joltages":[37,51,76,53,52,23,82,42,55,55]},{"target":[false,false,true,true,false],"buttons":[[2,3],[0,2,3,4],[1,3,4],[1,2,3,4]],"joltages":[8,18,34,37,26]},{"target":[true,true,false,true,false,false,false,false,true],"buttons":[[2,5],[0,1,2,5,8],[3,4,5,6,8],[1,2,3,4,6,7,8],[0,1,3,4,5,6,8],[1,4,7],[2,3,5,7,8],[1,2,3,5,7]],"joltages":[29,65,46,36,47,40,32,38,54]},{"target":[true,true,true,false,true,false,true],"buttons":[[2,5],[0,4],[2,3],[1,2],[2],[0,3,6],[0,2,6],[0,3],[0,1,4,5,6]],"joltages":[88,25,56,42,38,32,51]},{"target":[true,false,false,true,true,true,false,true,true],"buttons":[[0,1,4,5,6],[0,1,3,4,5,6,7,8],[0,1,2,7,8],[1,2,3,4,5],[0,3,8],[1,3,4,5,6,7],[4,6],[0,1,3,5,6,7],[8],[0,2,3,4,5,6,7],[1,7]],"joltages":[175,196,12,182,43,176,171,187,52]},{"target":[false,true,false,true,true,true,false,false],"buttons":[[2,4,5],[2,6,7],[2,4,5,6,7],[3,4],[0,3,4,5,7],[1,2,3,4,5,7],[5],[2,5,6],[1,3,4,5,6,7],[0,2,4,6,7]],"joltages":[14,25,37,189,194,64,34,47]},{"target":[false,true,true,false],"buttons":[[0,1],[0,2,3],[0,1,2],[1,2]],"joltages":[35,31,38,20]},{"target":[true,false,true,false,false,false,true],"buttons":[[0,1,4,5],[1,2,4],[0,1,4,6],[1,2,4,5,6],[0,2,6],[1,2,3],[3,4]],"joltages":[42,60,34,19,63,35,39]},{"target":[false,true,true,true,false,false,false],"buttons":[[4],[0,2,3,4,6],[0,1,2,3,4,5],[0,2,4,5,6],[0,1,3,4,5],[1,2,3]],"joltages":[37,35,20,36,44,36,3]},{"target":[true,false,true,false,false],"buttons":[[0,3],[2,3],[3,4],[0,3,4],[2,4],[0,1,3]],"joltages":[200,3,39,227,212]},{"target":[true,false,true,false,true,false,false,false],"buttons":[[2],[1,7],[0,3,4,6],[3],[1,4,5,6,7],[0,2,3,5,6]],"joltages":[33,211,25,52,29,30,46,211]},{"target":[false,false,false,false,true,true],"buttons":[[0,1,4,5],[0,1,5],[2,3,4],[1,3],[0,1,3],[1,2,5],[0],[1,2,3,4]],"joltages":[36,41,20,34,21,16]},{"target":[false,true,true,false,true,true,true,false,true,false],"buttons":[[0,2,3,4,9],[1,7],[1,2,3,5,6,7,8,9],[0,1,2,4,5,7,9],[3,4,5,6,7],[4,6],[2],[0,1,2,3,6,7,9],[0,6,7,8,9]],"joltages":[138,163,164,156,25,29,162,172,22,157]},{"target":[false,false,true,false,true,false],"buttons":[[0,1,2,4,5],[0,2,3],[0,2,5],[0,4,5]],"joltages":[53,2,34,19,21,34]},{"target":[true,false,false,false,true,true],"buttons":[[1,2,3,4],[0,3,5],[1,5],[0,1,4,5],[0,2,3,4,5],[0,2,3],[0,1,2,3]],"joltages":[32,41,28,39,15,30]},{"target":[true,true,false,true,true,true,false,false],"buttons":[[0,2,5,6],[0,5,6,7],[4,5,7],[1,3,6,7],[0,2,5,7],[1],[3,4,6,7],[0,6],[1,2,3,5]],"joltages":[30,45,38,45,35,55,43,64]},{"target":[false,true,false,true,false,false,true,false,false,false],"buttons":[[3,7],[0,4,5,9],[3,4,6,8],[0,1,2,3,5,6,8,9],[2,3,4,5,6,7,8,9],[8,9],[0,1,2,3,4,6,8],[0,1,2],[0,1,2,4,5,7,8,9],[0,1,3,4,6],[0,1,3,7,9],[0,1,6,7,8,9]],"joltages":[263,243,67,237,236,61,224,76,91,99]},{"target":[false,true,true,false,true,true],"buttons":[[0,2,3,5],[1],[0,1,2,4,5],[4,5],[1,3],[0],[0,2,3]],"joltages":[44,31,42,42,15,35]},{"target":[true,true,true,false],"buttons":[[1,3],[1,2],[0,2],[2],[2,3]],"joltages":[9,155,45,146]},{"target":[true,false,true,false,false,false,true,false,true,false],"buttons":[[0,1,2,5,6],[0,1,2,5,7],[1,2,4,5,6],[0,1,3,5,7,8,9],[2,3,4,5,6,8],[4,6],[0,1,2,3,4,5,6,8],[0,3,4,5,9],[5,6,7,8],[1,4,6,7,8],[2,3,8,9],[2,3,4,9],[0,1,2,4,5,7,8]],"joltages":[76,79,96,73,82,86,58,63,80,61]},{"target":[false,false,false,true,true,true],"buttons":[[0,3,4],[3,4,5],[0,1,4,5],[0,2,3,4]],"joltages":[34,10,10,32,42,18]},{"target":[false,false,true,true,false],"buttons":[[1,2,4],[0,2,3],[2,3]],"joltages":[17,7,28,21,7]},{"target":[false,true,true,true],"buttons":[[1,2,3],[0,2]],"joltages":[4,19,23,19]},{"target":[true,true,true,false],"buttons":[[2,3],[0,1,3],[0,1],[1,2]],"joltages":[15,32,30,26]},{"target":[false,false,true,false,true,false],"buttons":[[0,2,4],[3,4],[0,1,2,4,5],[0,1,3],[1,2,3,5]],"joltages":[37,29,33,31,48,21]},{"target":[true,true,true,false,false,true,true,true],"buttons":[[1,3,6],[0,1,2,3,4,5,7],[0,2,4,5,6,7],[1,2,6],[0,3,6],[1,5,7]],"joltages":[27,26,20,16,20,37,36,37]},{"target":[false,true,true,false],"buttons":[[2,3],[1,2],[0,3]],"joltages":[14,1,1,14]},{"target":[false,true,false,true,true,false,false,false,true],"buttons":[[3,4,5,6,8],[1,2,3,6,7,8],[1,2,3,5,6,7],[3,7],[2,3,4,5,6,7,8],[0,1,2,8],[0,3,4,5,7,8]],"joltages":[153,46,47,212,158,173,51,196,189]},{"target":[true,false,true,true,true,false],"buttons":[[0,1,4,5],[0,1,2,5],[1,2,3],[1,2,3,4,5],[0,2,3,5],[0,3,4],[1,2],[2,3,4,5]],"joltages":[220,54,54,223,212,30]},{"target":[true,false,true,true,true,true],"buttons":[[1,2,3,5],[0,1,5],[1,2,3,4],[0,2,3,4],[2,3]],"joltages":[21,25,36,36,20,14]},{"target":[false,false,false,true,false,false,false,false,true,true],"buttons":[[0,9],[4,5,6],[0,2,4,6,7,9],[0,2,3,4,7,8,9],[0,1,4,7],[0,3,7,8],[8,9],[0,7,8],[0,1,2,5,6,7]],"joltages":[65,26,36,8,49,35,47,46,18,49]},{"target":[false,true,true,true,true,false,true,true],"buttons":[[1,2,3,5,6,7],[0,1,3,4,6,7],[1,2,3,4,5,6],[0,2,4,7],[1,3,5],[3,4,5,6,7],[4,7],[0,1,4,6,7],[0,7]],"joltages":[19,35,12,42,55,27,40,46]},{"target":[false,true,false,true,true,true],"buttons":[[0,2,3,5],[1,3,4,5],[0,1,2,4],[1,5],[1,2,3,5]],"joltages":[29,50,39,38,35,43]},{"target":[false,false,true,false,false,true,true,false,true],"buttons":[[2,3,8],[1,5],[1,4,5,6,7,8],[1,3,4,5,7,8],[2,3,4,5,7],[0,1,3,4],[0,1,3,4,6],[0,2,3,4,5,7,8]],"joltages":[28,173,36,70,64,171,30,46,60]},{"target":[false,true,true,false],"buttons":[[1],[0,2,3],[1,2]],"joltages":[3,11,10,3]},{"target":[true,false,true,false,false,false,false,true,true],"buttons":[[1,2,3,8],[1,2,3,4,5],[0,1,3,7],[0,1,2,3,6,7],[0,1,2,3,7,8],[4],[1,2,3,4,5,7,8]],"joltages":[27,49,45,49,31,19,6,42,35]},{"target":[true,true,false,false],"buttons":[[1],[0,1,2],[2,3],[0]],"joltages":[22,19,28,9]},{"target":[true,true,false,false,true,true,true],"buttons":[[1,2,3,4,5],[2,3,4,5],[0,2,4,5],[1,4],[0,2,4],[3],[0,1,3,6],[1,3,6]],"joltages":[37,171,27,179,33,24,158]},{"target":[false,true,true,true,true,false],"buttons":[[1,2,3,4],[0,4],[0,1,3],[1,2,3],[2,3,4,5],[1,2,3,4,5],[0,2]],"joltages":[44,38,47,45,44,21]},{"target":[false,true,true,false,true,false,false,false,true],"buttons":[[1,6,8],[2,3,4,5,8],[0,1,2,3,6,8],[0,2,3,4,7,8],[5,7],[0,1,2,3,4,5,8],[1,3,4,5],[0,1,4],[1,2,3,6,7,8],[4,5,6,7],[0,1,2,4,5,6,8]],"joltages":[59,172,61,70,85,56,141,54,164]},{"target":[false,true,true,false,false,false,false,false,false],"buttons":[[7,8],[3,5],[1,2],[1,3,5,6,8],[2,3,4,5,6],[0,4,7,8],[2,4],[1,2,3,4,5,6,7]],"joltages":[4,35,43,56,44,56,47,41,33]},{"target":[true,false,false,false,false,true,false,false,false,false],"buttons":[[0,1,2,3,4,5,7,8,9],[2,4,5,9],[3,5,6],[3,9],[0,3,5,9],[0,1,4],[0,1,3,5,6,8],[0,1,2,4,5,6,7,8],[0,2,5,6,7,8,9],[0,1,3,6,8,9],[4,6,8]],"joltages":[217,50,191,56,54,220,203,176,191,209]},{"target":[false,true,false,false,true,false],"buttons":[[0,2,4],[1,3],[1,3,5],[1,2,3,5],[0,1,2,3],[3],[0,3,4,5]],"joltages":[145,21,28,151,139,132]},{"target":[true,false,false,true,true,true],"buttons":[[3,4],[2],[1,3,5],[1,2,3,5],[0,1,2],[0,2,4,5],[0,2,3,4],[0,2,3]],"joltages":[42,19,63,44,38,13]},{"target":[true,false,true,false,false,false,false,false,false],"buttons":[[0,2,4,6,7],[0,3,4,6,8],[0,3,4,5,8],[0,1,4,6],[2,4,5],[2,3,5],[1,3,5,7],[3,8]],"joltages":[32,17,39,53,46,56,18,25,25]},{"target":[true,true,true,false,false,false,false,false,false,true],"buttons":[[0,1,2,5],[5,6,9],[0,2,8,9],[0,2,3,5],[2],[0,1,2,3,4,5,6,7],[0,1,2,3,5,6,7,9],[7],[0,3,4]],"joltages":[73,56,84,44,19,78,52,49,9,44]},{"target":[true,false,true,true],"buttons":[[1,2],[2],[0,1,3],[0,1,2]],"joltages":[21,27,190,4]},{"target":[false,false,false,true,false,false,true,false,true,true],"buttons":[[0,2,3,4,6,7,8,9],[0,2,3,4,8,9],[0,1,2,5,6,8,9],[2,3],[0,1,2,5,6,7,8],[1,2,5,8],[0,1,2,3,5,7,8,9],[2,7],[0,3,8,9],[2,4,9]],"joltages":[36,32,70,37,11,32,14,33,37,42]}];
+
+
let currentMode = 1; // 1 or 2
+
let currentMachineIndex = 0;
+
let currentState = [];
+
let buttonStates = []; // Track which buttons are "on" (pressed odd number of times)
+
let isPlaying = false;
+
let showingSolution = false;
+
let solutionSteps = [];
+
let currentStep = 0;
+
let solvedMachines = new Set(); // Track which machines have been solved
+
let animationSpeed = 200; // ms between button presses (default 5x)
+
+
+
function renderMachine() {
+
const machine = machines[currentMachineIndex];
+
+
// Update title based on mode
+
const titleEl = document.getElementById('displayTitle');
+
if (currentMode === 1) {
+
titleEl.textContent = 'Indicator Lights';
+
titleEl.style.color = '#89b4fa';
+
} else {
+
titleEl.textContent = 'Joltage Counters';
+
titleEl.style.color = '#f9e2af';
+
}
+
+
// Render lights or counters
+
const lightsDiv = document.getElementById('lights');
+
lightsDiv.innerHTML = '';
+
+
if (currentMode === 1) {
+
// Part 1: Indicator lights
+
machine.target.forEach((target, i) => {
+
const light = document.createElement('div');
+
light.className = `light ${currentState[i] ? 'on' : 'off'} ${target ? 'target' : ''}`;
+
light.textContent = i;
+
lightsDiv.appendChild(light);
+
});
+
} else {
+
// Part 2: Joltage counters
+
machine.joltages.forEach((target, i) => {
+
const counter = document.createElement('div');
+
const current = currentState[i] || 0;
+
const isTarget = current === target;
+
counter.className = `light ${isTarget ? 'on' : 'off'} ${true ? 'target' : ''}`;
+
counter.innerHTML = `<div style="font-size: 7px; opacity: 0.7;">[${i}]</div><div style="font-size: 10px; font-weight: bold;">${current}/<span style="color: #f9e2af;">${target}</span></div>`;
+
lightsDiv.appendChild(counter);
+
});
+
}
+
+
// Render buttons
+
const buttonsDiv = document.getElementById('buttons');
+
buttonsDiv.innerHTML = '';
+
machine.buttons.forEach((toggles, i) => {
+
const btn = document.createElement('div');
+
const pressCount = buttonStates[i] || 0;
+
const isPressed = currentMode === 1 ? (pressCount % 2 === 1) : (pressCount > 0);
+
btn.className = `button-display ${isPressed ? 'pressed' : ''}`;
+
btn.innerHTML = `
+
<div class="button-label">Button ${i}${currentMode === 2 ? ` (${pressCount})` : ''}</div>
+
<div class="button-toggles">Affects: ${toggles.join(', ')}</div>
+
`;
+
btn.addEventListener('click', () => toggleButton(i));
+
buttonsDiv.appendChild(btn);
+
});
+
}
+
+
function toggleButton(buttonIndex) {
+
const machine = machines[currentMachineIndex];
+
+
if (currentMode === 1) {
+
// Part 1: Toggle lights (XOR)
+
buttonStates[buttonIndex] = buttonStates[buttonIndex] ? 0 : 1;
+
machine.buttons[buttonIndex].forEach(lightIndex => {
+
currentState[lightIndex] = !currentState[lightIndex];
+
});
+
} else {
+
// Part 2: Increment counters
+
buttonStates[buttonIndex] = (buttonStates[buttonIndex] || 0) + 1;
+
machine.buttons[buttonIndex].forEach(counterIndex => {
+
currentState[counterIndex] = (currentState[counterIndex] || 0) + 1;
+
});
+
}
+
+
renderMachine();
+
updateStats();
+
}
+
+
function solveMachine(machine) {
+
const n = machine.target.length;
+
const m = machine.buttons.length;
+
+
const matrix = [];
+
for (let i = 0; i < n; i++) {
+
const row = [];
+
for (let j = 0; j < m; j++) {
+
row.push(machine.buttons[j].includes(i) ? 1 : 0);
+
}
+
row.push(machine.target[i] ? 1 : 0);
+
matrix.push(row);
+
}
+
+
const pivotCols = [];
+
for (let col = 0; col < m; col++) {
+
let pivotRow = -1;
+
for (let row = pivotCols.length; row < n; row++) {
+
if (matrix[row][col] === 1) {
+
pivotRow = row;
+
break;
+
}
+
}
+
+
if (pivotRow === -1) continue;
+
+
const targetRow = pivotCols.length;
+
if (pivotRow !== targetRow) {
+
[matrix[pivotRow], matrix[targetRow]] = [matrix[targetRow], matrix[pivotRow]];
+
}
+
+
pivotCols.push(col);
+
+
for (let row = 0; row < n; row++) {
+
if (row !== targetRow && matrix[row][col] === 1) {
+
for (let c = 0; c <= m; c++) {
+
matrix[row][c] ^= matrix[targetRow][c];
+
}
+
}
+
}
+
}
+
+
const solution = new Array(m).fill(0);
+
for (let i = pivotCols.length - 1; i >= 0; i--) {
+
const col = pivotCols[i];
+
solution[col] = matrix[i][m];
+
for (let j = col + 1; j < m; j++) {
+
if (matrix[i][j] === 1) {
+
solution[col] ^= solution[j];
+
}
+
}
+
}
+
+
return solution;
+
}
+
+
// Part 2 solver (copy of server-side logic)
+
function solveMachinePart2(machine) {
+
const n = machine.joltages.length;
+
const m = machine.buttons.length;
+
const target = machine.joltages;
+
+
const A = [];
+
for (let i = 0; i < n; i++) {
+
const row = [];
+
for (let j = 0; j < m; j++) {
+
row.push(machine.buttons[j].includes(i) ? 1 : 0);
+
}
+
A.push(row);
+
}
+
+
const matrix = [];
+
for (let i = 0; i < n; i++) {
+
matrix.push([...A[i], target[i]]);
+
}
+
+
const pivotCols = [];
+
for (let col = 0; col < m; col++) {
+
let pivotRow = -1;
+
for (let row = pivotCols.length; row < n; row++) {
+
if (matrix[row][col] !== 0) {
+
pivotRow = row;
+
break;
+
}
+
}
+
+
if (pivotRow === -1) continue;
+
+
const targetRow = pivotCols.length;
+
if (pivotRow !== targetRow) {
+
[matrix[pivotRow], matrix[targetRow]] = [matrix[targetRow], matrix[pivotRow]];
+
}
+
+
pivotCols.push(col);
+
+
const pivot = matrix[targetRow][col];
+
for (let c = 0; c <= m; c++) {
+
matrix[targetRow][c] /= pivot;
+
}
+
+
for (let row = 0; row < n; row++) {
+
if (row !== targetRow && matrix[row][col] !== 0) {
+
const factor = matrix[row][col];
+
for (let c = 0; c <= m; c++) {
+
matrix[row][c] -= factor * matrix[targetRow][c];
+
}
+
}
+
}
+
}
+
+
const isPivot = new Array(m).fill(false);
+
pivotCols.forEach(col => isPivot[col] = true);
+
const freeVars = [];
+
for (let j = 0; j < m; j++) {
+
if (!isPivot[j]) freeVars.push(j);
+
}
+
+
if (freeVars.length > 8) { // Reduced limit for browser
+
return new Array(m).fill(0);
+
}
+
+
let minPresses = Infinity;
+
let bestSolution = [];
+
+
const maxTarget = Math.max(...target);
+
const maxFreeValue = Math.min(maxTarget * 2, 100);
+
+
function searchFreeVars(idx, currentSol) {
+
if (idx === freeVars.length) {
+
const sol = [...currentSol];
+
let valid = true;
+
for (let i = pivotCols.length - 1; i >= 0; i--) {
+
const col = pivotCols[i];
+
let val = matrix[i][m];
+
for (let j = col + 1; j < m; j++) {
+
val -= matrix[i][j] * sol[j];
+
}
+
sol[col] = val;
+
+
if (val < -1e-9 || Math.abs(val - Math.round(val)) > 1e-9) {
+
valid = false;
+
break;
+
}
+
}
+
+
if (valid) {
+
const intSol = sol.map(x => Math.round(Math.max(0, x)));
+
const presses = intSol.reduce((sum, x) => sum + x, 0);
+
if (presses < minPresses) {
+
minPresses = presses;
+
bestSolution = intSol;
+
}
+
}
+
return;
+
}
+
+
for (let val = 0; val <= maxFreeValue; val++) {
+
currentSol[freeVars[idx]] = val;
+
searchFreeVars(idx + 1, currentSol);
+
}
+
}
+
+
searchFreeVars(0, new Array(m).fill(0));
+
return bestSolution;
+
}
+
+
function getCurrentSolution() {
+
const machine = machines[currentMachineIndex];
+
return currentMode === 1 ? solveMachine(machine) : solveMachinePart2(machine);
+
}
+
+
function showSolution() {
+
const machine = machines[currentMachineIndex];
+
const solution = getCurrentSolution();
+
+
if (currentMode === 1) {
+
currentState = new Array(machine.target.length).fill(false);
+
buttonStates = [...solution].map(v => v === 1);
+
+
solution.forEach((shouldPress, buttonIndex) => {
+
if (shouldPress === 1) {
+
machine.buttons[buttonIndex].forEach(lightIndex => {
+
currentState[lightIndex] = !currentState[lightIndex];
+
});
+
}
+
});
+
} else {
+
currentState = new Array(machine.joltages.length).fill(0);
+
buttonStates = [...solution];
+
+
solution.forEach((pressCount, buttonIndex) => {
+
for (let p = 0; p < pressCount; p++) {
+
machine.buttons[buttonIndex].forEach(counterIndex => {
+
currentState[counterIndex]++;
+
});
+
}
+
});
+
}
+
+
showingSolution = true;
+
renderMachine();
+
updateStats();
+
}
+
+
function updateStats() {
+
const machine = machines[currentMachineIndex];
+
const solution = getCurrentSolution();
+
const minPresses = solution.reduce((a, b) => a + b, 0);
+
+
let totalPressed;
+
if (currentMode === 1) {
+
totalPressed = buttonStates.filter(b => b).length;
+
} else {
+
totalPressed = buttonStates.reduce((sum, count) => sum + (count || 0), 0);
+
}
+
+
// Calculate accumulated total for solved machines
+
let accumulatedTotal = 0;
+
solvedMachines.forEach(idx => {
+
const m = machines[idx];
+
const sol = currentMode === 1 ? solveMachine(m) : solveMachinePart2(m);
+
accumulatedTotal += sol.reduce((a, b) => a + b, 0);
+
});
+
+
document.getElementById('statsInfo').textContent = `Buttons Pressed: ${totalPressed} | Target: ${minPresses} | Accumulated Total: ${accumulatedTotal}`;
+
document.getElementById('machineInfo').textContent = `Machine ${currentMachineIndex + 1} / ${machines.length}`;
+
}
+
+
document.getElementById('prev').addEventListener('click', () => {
+
if (currentMachineIndex > 0) {
+
isPlaying = false;
+
document.getElementById('play').textContent = '▶ Play';
+
currentMachineIndex--;
+
initMachine();
+
}
+
});
+
+
document.getElementById('next').addEventListener('click', () => {
+
if (currentMachineIndex < machines.length - 1) {
+
isPlaying = false;
+
document.getElementById('play').textContent = '▶ Play';
+
currentMachineIndex++;
+
initMachine();
+
}
+
});
+
+
document.getElementById('reset').addEventListener('click', initMachine);
+
+
document.getElementById('togglePart').addEventListener('click', () => {
+
currentMode = currentMode === 1 ? 2 : 1;
+
document.getElementById('togglePart').textContent = `Part ${currentMode}`;
+
solvedMachines.clear();
+
initMachine();
+
});
+
+
document.getElementById('play').addEventListener('click', () => {
+
isPlaying = !isPlaying;
+
document.getElementById('play').textContent = isPlaying ? '⏸ Pause' : '▶ Play';
+
if (isPlaying) {
+
animateSolution();
+
}
+
});
+
+
// Speed control
+
const speedSlider = document.getElementById('speed');
+
const speedValue = document.getElementById('speedValue');
+
speedSlider.addEventListener('input', (e) => {
+
const speed = parseInt(e.target.value);
+
speedValue.textContent = `${speed}x`;
+
// Faster speed = shorter delay (inverse relationship)
+
animationSpeed = 1000 / speed;
+
});
+
+
function animateSolution() {
+
if (!isPlaying) return;
+
+
if (currentStep < solutionSteps.length) {
+
// Toggle the next button in the solution
+
const buttonIndex = solutionSteps[currentStep];
+
toggleButton(buttonIndex);
+
currentStep++;
+
+
// Use 10x faster speed for Part 2 (more button presses)
+
const delay = currentMode === 2 ? animationSpeed / 10 : animationSpeed;
+
setTimeout(animateSolution, delay);
+
} else {
+
// Mark this machine as solved
+
const machine = machines[currentMachineIndex];
+
let isCorrect;
+
if (currentMode === 1) {
+
isCorrect = currentState.every((state, i) => state === machine.target[i]);
+
} else {
+
isCorrect = currentState.every((state, i) => state === machine.joltages[i]);
+
}
+
+
if (isCorrect) {
+
solvedMachines.add(currentMachineIndex);
+
updateStats();
+
}
+
+
// Current machine done, move to next immediately
+
if (currentMachineIndex < machines.length - 1) {
+
if (isPlaying) {
+
currentMachineIndex++;
+
initMachine();
+
setTimeout(animateSolution, animationSpeed);
+
}
+
} else {
+
// All done
+
isPlaying = false;
+
document.getElementById('play').textContent = '▶ Play';
+
setTimeout(() => {
+
currentMachineIndex = 0;
+
initMachine();
+
}, animationSpeed * 4);
+
}
+
}
+
}
+
+
function initMachine() {
+
const machine = machines[currentMachineIndex];
+
showingSolution = false;
+
currentStep = 0;
+
+
if (currentMode === 1) {
+
// Part 1
+
currentState = new Array(machine.target.length).fill(false);
+
buttonStates = new Array(machine.buttons.length).fill(0);
+
+
const solution = solveMachine(machine);
+
solutionSteps = [];
+
solution.forEach((shouldPress, idx) => {
+
if (shouldPress === 1) {
+
solutionSteps.push(idx);
+
}
+
});
+
} else {
+
// Part 2
+
currentState = new Array(machine.joltages.length).fill(0);
+
buttonStates = new Array(machine.buttons.length).fill(0);
+
+
const solution = solveMachinePart2(machine);
+
solutionSteps = [];
+
solution.forEach((pressCount, idx) => {
+
for (let i = 0; i < pressCount; i++) {
+
solutionSteps.push(idx);
+
}
+
});
+
}
+
+
renderMachine();
+
updateStats();
+
}
+
+
// Initialize
+
initMachine();
+
</script>
+
</body>
+
</html>