advent of code 2025 in ts and nix
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>AoC 2025 Day 8 - Playground Junction Boxes</title>
7 <style>
8 * {
9 box-sizing: border-box;
10 margin: 0;
11 padding: 0;
12 }
13 body {
14 background: #1e1e2e;
15 color: #cdd6f4;
16 font-family: "Source Code Pro", monospace;
17 font-size: 14pt;
18 font-weight: 300;
19 overflow: hidden;
20 margin: 0;
21 padding: 0;
22 }
23 #container {
24 width: 100vw;
25 height: 100vh;
26 position: relative;
27 }
28 #canvas {
29 width: 100%;
30 height: 100%;
31 display: block;
32 position: absolute;
33 top: 0;
34 left: 0;
35 z-index: 0;
36 }
37 .ui {
38 position: absolute;
39 top: 0;
40 left: 0;
41 right: 0;
42 padding: 20px;
43 pointer-events: none;
44 z-index: 1;
45 }
46 .ui > * {
47 pointer-events: auto;
48 }
49 h1 {
50 color: #a6e3a1;
51 text-shadow: 0 0 2px #a6e3a1, 0 0 5px #a6e3a1;
52 margin-bottom: 10px;
53 font-size: 1em;
54 font-weight: normal;
55 text-align: center;
56 }
57 .controls {
58 background: rgba(17, 17, 27, 0.9);
59 border: 1px solid #313244;
60 padding: 15px;
61 margin: 15px auto;
62 max-width: 800px;
63 border-radius: 4px;
64 }
65 .timeline-container {
66 background: rgba(17, 17, 27, 0.9);
67 border: 1px solid #313244;
68 padding: 20px;
69 margin: 10px auto;
70 max-width: 800px;
71 border-radius: 4px;
72 }
73 .timeline-label {
74 color: #a6adc8;
75 font-size: 12px;
76 margin-bottom: 10px;
77 display: flex;
78 justify-content: space-between;
79 align-items: center;
80 }
81 .timeline-markers {
82 position: relative;
83 margin-top: 8px;
84 font-size: 11px;
85 color: #6c7086;
86 height: 30px;
87 }
88 .timeline-marker {
89 position: absolute;
90 text-align: center;
91 transform: translateX(-50%);
92 white-space: nowrap;
93 }
94 .timeline-marker.start {
95 left: 0%;
96 transform: translateX(0);
97 }
98 .timeline-marker.end {
99 right: 0%;
100 transform: translateX(0);
101 text-align: right;
102 }
103 .timeline-marker.highlight {
104 color: #a6e3a1;
105 font-weight: bold;
106 }
107 .timeline-slider {
108 width: 100% !important;
109 -webkit-appearance: none;
110 appearance: none;
111 height: 12px;
112 background: linear-gradient(to right, #313244 0%, #313244 100%);
113 outline: none;
114 border-radius: 6px;
115 cursor: pointer;
116 position: relative;
117 }
118 .timeline-slider::-webkit-slider-thumb {
119 -webkit-appearance: none;
120 appearance: none;
121 width: 24px;
122 height: 24px;
123 background: #a6e3a1;
124 cursor: grab;
125 border-radius: 50%;
126 border: 3px solid #11111b;
127 box-shadow: 0 2px 8px rgba(166, 227, 161, 0.4);
128 transition: all 0.2s ease;
129 }
130 .timeline-slider::-moz-range-thumb {
131 width: 24px;
132 height: 24px;
133 background: #a6e3a1;
134 cursor: grab;
135 border-radius: 50%;
136 border: 3px solid #11111b;
137 box-shadow: 0 2px 8px rgba(166, 227, 161, 0.4);
138 transition: all 0.2s ease;
139 }
140 .timeline-slider::-webkit-slider-thumb:hover {
141 background: #b4e7b9;
142 transform: scale(1.1);
143 box-shadow: 0 4px 12px rgba(166, 227, 161, 0.6);
144 }
145 .timeline-slider::-moz-range-thumb:hover {
146 background: #b4e7b9;
147 transform: scale(1.1);
148 box-shadow: 0 4px 12px rgba(166, 227, 161, 0.6);
149 }
150 .timeline-slider:active::-webkit-slider-thumb {
151 cursor: grabbing;
152 transform: scale(0.95);
153 }
154 .timeline-slider:active::-moz-range-thumb {
155 cursor: grabbing;
156 transform: scale(0.95);
157 }
158 .control-row {
159 display: flex;
160 gap: 15px;
161 align-items: center;
162 margin-bottom: -1rem;
163 flex-wrap: wrap;
164 justify-content: center;
165 }
166 .control-row:last-child {
167 margin-bottom: 0;
168 }
169 button {
170 background: #11111b;
171 color: #a6e3a1;
172 border: 1px solid #313244;
173 padding: 8px 16px;
174 cursor: pointer;
175 font-family: inherit;
176 font-size: 14px;
177 border-radius: 3px;
178 }
179 button:hover {
180 background: #181825;
181 }
182 button:disabled {
183 opacity: 0.5;
184 cursor: not-allowed;
185 }
186 .info {
187 color: #f9e2af;
188 font-size: 14px;
189 }
190 .stats {
191 background: rgba(17, 17, 27, 0.9);
192 border: 1px solid #313244;
193 padding: 10px 15px;
194 margin: 0 auto;
195 max-width: 800px;
196 border-radius: 4px;
197 text-align: center;
198 font-size: 13px;
199 color: #a6adc8;
200 position: fixed;
201 bottom: 20px;
202 left: 50%;
203 transform: translateX(-50%);
204 z-index: 1;
205 }
206 .legend {
207 display: flex;
208 gap: 15px;
209 margin-top: 10px;
210 flex-wrap: wrap;
211 justify-content: center;
212 }
213 .legend-item {
214 display: flex;
215 align-items: center;
216 gap: 6px;
217 font-size: 12px;
218 color: #a6adc8;
219 }
220 .legend-box {
221 width: 12px;
222 height: 12px;
223 border-radius: 50%;
224 }
225 .legend-box.junction { background: #89b4fa; }
226 .legend-box.connection { background: #a6e3a1; }
227 .legend-box.circuit { background: #f9e2af; }
228 input[type="range"] {
229 -webkit-appearance: none;
230 appearance: none;
231 width: 120px;
232 height: 6px;
233 background: #313244;
234 outline: none;
235 border: 1px solid #313244;
236 }
237 input[type="range"]::-webkit-slider-thumb {
238 -webkit-appearance: none;
239 appearance: none;
240 width: 16px;
241 height: 16px;
242 background: #a6e3a1;
243 cursor: pointer;
244 border: 1px solid #313244;
245 border-radius: 50%;
246 }
247 input[type="range"]::-moz-range-thumb {
248 width: 16px;
249 height: 16px;
250 background: #a6e3a1;
251 cursor: pointer;
252 border: 1px solid #313244;
253 border-radius: 50%;
254 }
255 label {
256 color: #a6adc8;
257 font-size: 13px;
258 }
259 a {
260 text-decoration: none;
261 color: #a6e3a1;
262 outline: 0;
263 }
264 a:hover, a:focus {
265 text-decoration: underline;
266 }
267 </style>
268</head>
269<body>
270 <div id="container">
271 <canvas id="canvas"></canvas>
272 <div class="ui">
273 <h1>AoC 2025 Day 8 - Playground Junction Boxes</h1>
274
275 <div class="controls">
276 <div class="control-row">
277 <button id="prev">← Previous</button>
278 <button id="play">▶ Play</button>
279 <button id="next">Next →</button>
280 <button id="reset">↺ Reset</button>
281 </div>
282 <div class="timeline-label">
283 <span>Timeline</span>
284 <span id="timelineStep">Step 0 of 7845</span>
285 </div>
286 <input type="range" id="timeline" class="timeline-slider" min="0" max="7845" value="0" step="1">
287 <div class="timeline-markers">
288 <div class="timeline-marker start">Start<br>0</div>
289 <div class="timeline-marker highlight" style="left: 12.746972594008923%;">Part 1<br>1000</div>
290 <div class="timeline-marker highlight end">Part 2<br>7845</div>
291 </div>
292 <div class="legend">
293 <div class="legend-item"><div class="legend-box junction"></div> Isolated Junction (small)</div>
294 <div class="legend-item"><div class="legend-box connection"></div> Connected Junction (large)</div>
295 <div class="legend-item"><div class="legend-box circuit"></div> Circuit (color-coded)</div>
296 </div>
297 </div>
298
299 <div class="stats">
300 <div id="statsInfo">Circuits: 1000 | Largest: 0 | Part 1: 0 | Part 2: 0</div>
301 <div style="margin-top: 5px; font-size: 11px;"><a href="../index.html">[Return to Index]</a></div>
302 </div>
303 </div>
304 </div>
305
306 <script type="importmap">
307 {
308 "imports": {
309 "three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
310 "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
311 }
312 }
313 </script>
314
315 <script type="module">
316 import * as THREE from 'three';
317 import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
318
319 // Input data embedded
320 const junctions = [{"x":5161,"y":22203,"z":73169},{"x":66101,"y":34794,"z":41187},{"x":19740,"y":85581,"z":70637},{"x":64804,"y":51256,"z":2927},{"x":68224,"y":49993,"z":7867},{"x":9878,"y":97392,"z":46130},{"x":40001,"y":51521,"z":79544},{"x":45624,"y":73253,"z":74846},{"x":30230,"y":58923,"z":59531},{"x":84723,"y":58102,"z":86638},{"x":14537,"y":44841,"z":84567},{"x":41558,"y":92494,"z":89096},{"x":75012,"y":1225,"z":75685},{"x":77420,"y":67581,"z":11653},{"x":2365,"y":26154,"z":61974},{"x":80460,"y":35718,"z":17495},{"x":84603,"y":85352,"z":97745},{"x":85312,"y":81113,"z":25465},{"x":84808,"y":39686,"z":39315},{"x":78930,"y":20627,"z":23019},{"x":9138,"y":22120,"z":32917},{"x":43534,"y":38414,"z":62909},{"x":1852,"y":53657,"z":68936},{"x":42113,"y":82762,"z":91457},{"x":54027,"y":40542,"z":58053},{"x":82202,"y":42280,"z":72268},{"x":202,"y":67735,"z":80514},{"x":52305,"y":854,"z":45988},{"x":88343,"y":55523,"z":31987},{"x":28291,"y":46179,"z":65951},{"x":91364,"y":63556,"z":74551},{"x":86323,"y":53379,"z":5679},{"x":4978,"y":97691,"z":830},{"x":72221,"y":98591,"z":40848},{"x":76259,"y":31452,"z":38504},{"x":24278,"y":31745,"z":72816},{"x":43435,"y":38188,"z":12128},{"x":38931,"y":44301,"z":87982},{"x":12819,"y":90012,"z":60798},{"x":22440,"y":63786,"z":13427},{"x":72991,"y":66943,"z":5903},{"x":99694,"y":22765,"z":27658},{"x":14531,"y":64099,"z":3781},{"x":81830,"y":53305,"z":71039},{"x":16083,"y":37712,"z":94291},{"x":1861,"y":15536,"z":36482},{"x":49895,"y":20278,"z":79203},{"x":81296,"y":28469,"z":21142},{"x":18962,"y":44916,"z":45948},{"x":75556,"y":98208,"z":8719},{"x":17073,"y":99830,"z":64332},{"x":80061,"y":73938,"z":7885},{"x":84505,"y":81534,"z":49321},{"x":51314,"y":28742,"z":90563},{"x":45266,"y":91838,"z":54563},{"x":68720,"y":31965,"z":85325},{"x":17087,"y":71197,"z":81398},{"x":21515,"y":19915,"z":83771},{"x":98426,"y":60158,"z":81708},{"x":39695,"y":27980,"z":22169},{"x":74294,"y":16001,"z":70164},{"x":37834,"y":77125,"z":68205},{"x":50158,"y":66031,"z":33997},{"x":6228,"y":61768,"z":85916},{"x":18288,"y":41150,"z":22719},{"x":22002,"y":47425,"z":92208},{"x":56877,"y":4935,"z":3480},{"x":62885,"y":9582,"z":43220},{"x":40257,"y":2330,"z":33318},{"x":98759,"y":96290,"z":18372},{"x":73781,"y":23958,"z":3804},{"x":7471,"y":82734,"z":46760},{"x":35024,"y":97965,"z":71262},{"x":37867,"y":65856,"z":50384},{"x":52511,"y":81222,"z":52412},{"x":33482,"y":59673,"z":3263},{"x":5675,"y":59568,"z":35932},{"x":21251,"y":43750,"z":56819},{"x":96765,"y":7988,"z":87769},{"x":20307,"y":50290,"z":65243},{"x":17293,"y":84764,"z":12114},{"x":66302,"y":92742,"z":19412},{"x":72049,"y":98072,"z":97246},{"x":53960,"y":10572,"z":73353},{"x":17692,"y":2175,"z":43186},{"x":26181,"y":26692,"z":78570},{"x":6206,"y":68914,"z":3522},{"x":80114,"y":23493,"z":14095},{"x":35469,"y":79858,"z":91410},{"x":21464,"y":22046,"z":6372},{"x":39867,"y":59222,"z":96369},{"x":41647,"y":17493,"z":96062},{"x":21818,"y":91894,"z":75532},{"x":8309,"y":91873,"z":78553},{"x":211,"y":75084,"z":88402},{"x":70079,"y":49640,"z":88549},{"x":53250,"y":64935,"z":66594},{"x":59536,"y":22170,"z":30100},{"x":60861,"y":99105,"z":14003},{"x":61621,"y":27840,"z":90515},{"x":74639,"y":29893,"z":7322},{"x":84678,"y":40440,"z":94821},{"x":97113,"y":95314,"z":13072},{"x":68608,"y":49658,"z":91760},{"x":63585,"y":86976,"z":70868},{"x":80713,"y":2187,"z":45320},{"x":53966,"y":90337,"z":38684},{"x":12879,"y":57544,"z":67234},{"x":1808,"y":55865,"z":37081},{"x":29062,"y":1242,"z":56047},{"x":68536,"y":82413,"z":79663},{"x":82931,"y":37875,"z":80295},{"x":71837,"y":70100,"z":82856},{"x":8604,"y":29732,"z":15837},{"x":55168,"y":22932,"z":85866},{"x":7831,"y":59139,"z":11394},{"x":68246,"y":95928,"z":25366},{"x":5516,"y":88931,"z":66654},{"x":96479,"y":58400,"z":51809},{"x":21133,"y":61075,"z":29966},{"x":43770,"y":13343,"z":39028},{"x":75024,"y":25103,"z":58888},{"x":35728,"y":97042,"z":40407},{"x":93159,"y":78375,"z":73702},{"x":59258,"y":10570,"z":78625},{"x":58756,"y":87652,"z":98984},{"x":32438,"y":36234,"z":86197},{"x":42461,"y":39846,"z":29989},{"x":91102,"y":74517,"z":69917},{"x":24981,"y":69124,"z":48442},{"x":95106,"y":21901,"z":90494},{"x":52329,"y":5337,"z":48036},{"x":74828,"y":37780,"z":86916},{"x":73037,"y":37561,"z":82293},{"x":11261,"y":5900,"z":29591},{"x":47758,"y":40284,"z":70586},{"x":44437,"y":88862,"z":81499},{"x":2771,"y":47188,"z":65346},{"x":48737,"y":73833,"z":22256},{"x":6681,"y":31926,"z":14269},{"x":14890,"y":4721,"z":99568},{"x":74643,"y":59728,"z":83172},{"x":44018,"y":65177,"z":11311},{"x":28163,"y":95996,"z":55663},{"x":62284,"y":4057,"z":40282},{"x":85786,"y":8606,"z":16706},{"x":38301,"y":35943,"z":83825},{"x":93121,"y":30446,"z":83456},{"x":80709,"y":93878,"z":46043},{"x":25806,"y":35135,"z":61144},{"x":82648,"y":87205,"z":99228},{"x":81004,"y":39106,"z":48053},{"x":45717,"y":30505,"z":54773},{"x":97465,"y":49038,"z":15700},{"x":46560,"y":20959,"z":89092},{"x":41799,"y":67704,"z":577},{"x":36770,"y":96608,"z":79263},{"x":40028,"y":55549,"z":56718},{"x":14448,"y":88161,"z":97119},{"x":26854,"y":84620,"z":40111},{"x":70853,"y":7432,"z":76917},{"x":55200,"y":24264,"z":16287},{"x":59,"y":67218,"z":14635},{"x":6942,"y":65638,"z":37471},{"x":68640,"y":68354,"z":35571},{"x":40272,"y":87947,"z":27089},{"x":6692,"y":88929,"z":43004},{"x":21229,"y":45052,"z":37013},{"x":15926,"y":71370,"z":74945},{"x":92692,"y":75869,"z":34838},{"x":91181,"y":95437,"z":48530},{"x":18204,"y":12940,"z":45467},{"x":35323,"y":15520,"z":69239},{"x":82373,"y":40019,"z":86985},{"x":80756,"y":54592,"z":21710},{"x":48243,"y":31541,"z":44180},{"x":46122,"y":84026,"z":53779},{"x":39293,"y":93745,"z":62710},{"x":46031,"y":21084,"z":76780},{"x":18406,"y":22463,"z":33328},{"x":49421,"y":94086,"z":30128},{"x":76265,"y":81888,"z":38769},{"x":51061,"y":44872,"z":30360},{"x":11748,"y":24035,"z":63578},{"x":27664,"y":31317,"z":20723},{"x":41342,"y":56333,"z":80116},{"x":6524,"y":33672,"z":42019},{"x":36451,"y":16429,"z":91763},{"x":25211,"y":84537,"z":10563},{"x":57256,"y":68807,"z":87002},{"x":16992,"y":17366,"z":32886},{"x":2095,"y":66214,"z":26424},{"x":72798,"y":44489,"z":12613},{"x":72302,"y":77566,"z":22389},{"x":83839,"y":80165,"z":79968},{"x":11488,"y":5510,"z":666},{"x":13321,"y":26484,"z":91940},{"x":88598,"y":20942,"z":28033},{"x":45663,"y":93458,"z":8868},{"x":13632,"y":60855,"z":21950},{"x":69401,"y":17820,"z":15957},{"x":99693,"y":49351,"z":24797},{"x":76038,"y":24933,"z":31774},{"x":36063,"y":8828,"z":29548},{"x":91198,"y":49648,"z":72812},{"x":14950,"y":49734,"z":84990},{"x":29974,"y":24256,"z":43142},{"x":19381,"y":8237,"z":23391},{"x":22823,"y":5267,"z":23772},{"x":57408,"y":109,"z":81592},{"x":25135,"y":3341,"z":44930},{"x":22021,"y":39757,"z":75364},{"x":921,"y":25399,"z":58355},{"x":34100,"y":75425,"z":22714},{"x":49845,"y":80698,"z":15599},{"x":75078,"y":43967,"z":63211},{"x":33418,"y":70727,"z":81931},{"x":11894,"y":93560,"z":98772},{"x":18360,"y":40040,"z":11898},{"x":13341,"y":57104,"z":74958},{"x":20124,"y":85072,"z":36147},{"x":11466,"y":57461,"z":25681},{"x":4890,"y":38197,"z":35448},{"x":24857,"y":93228,"z":69880},{"x":50868,"y":43259,"z":83785},{"x":10058,"y":67418,"z":98282},{"x":14583,"y":66434,"z":53841},{"x":74869,"y":52825,"z":81807},{"x":17976,"y":7604,"z":55075},{"x":28345,"y":58341,"z":54910},{"x":23937,"y":31696,"z":20983},{"x":15299,"y":65989,"z":48101},{"x":85948,"y":89595,"z":74642},{"x":55386,"y":58983,"z":43994},{"x":99999,"y":44512,"z":37075},{"x":75074,"y":15909,"z":8571},{"x":86057,"y":69748,"z":62953},{"x":30817,"y":82342,"z":17104},{"x":90956,"y":22036,"z":54469},{"x":93486,"y":72096,"z":63425},{"x":21847,"y":61753,"z":27413},{"x":76878,"y":83913,"z":6736},{"x":47263,"y":86404,"z":11866},{"x":54473,"y":77380,"z":8133},{"x":43916,"y":77261,"z":44094},{"x":31411,"y":73190,"z":80946},{"x":57844,"y":38767,"z":42289},{"x":67832,"y":36459,"z":80545},{"x":50394,"y":7272,"z":47306},{"x":32819,"y":25545,"z":67025},{"x":69061,"y":50499,"z":87171},{"x":29321,"y":3573,"z":96393},{"x":790,"y":54881,"z":30567},{"x":10323,"y":19294,"z":61513},{"x":42390,"y":48286,"z":82826},{"x":48131,"y":42651,"z":2327},{"x":63796,"y":43817,"z":56908},{"x":28226,"y":55100,"z":69879},{"x":20961,"y":95836,"z":666},{"x":22399,"y":63924,"z":10001},{"x":8586,"y":66790,"z":40318},{"x":66927,"y":1619,"z":64174},{"x":34447,"y":39223,"z":88816},{"x":53211,"y":28305,"z":63761},{"x":59463,"y":98390,"z":3323},{"x":21005,"y":38029,"z":96138},{"x":18979,"y":86778,"z":11125},{"x":39421,"y":55489,"z":41546},{"x":66733,"y":67487,"z":21536},{"x":85741,"y":27543,"z":34114},{"x":54905,"y":19440,"z":27003},{"x":80920,"y":97553,"z":51524},{"x":64486,"y":94319,"z":16244},{"x":47427,"y":88423,"z":99263},{"x":94831,"y":59526,"z":29750},{"x":20612,"y":19198,"z":3428},{"x":36838,"y":45561,"z":55848},{"x":3739,"y":24234,"z":96805},{"x":30520,"y":80842,"z":25923},{"x":75905,"y":4527,"z":45717},{"x":57097,"y":36462,"z":29937},{"x":12449,"y":12092,"z":75382},{"x":16241,"y":91132,"z":18465},{"x":92421,"y":32601,"z":39642},{"x":94358,"y":19855,"z":92919},{"x":98029,"y":17123,"z":98277},{"x":62997,"y":9369,"z":62516},{"x":5743,"y":97599,"z":15596},{"x":55128,"y":96754,"z":63021},{"x":64749,"y":29348,"z":87579},{"x":50931,"y":49963,"z":16511},{"x":24104,"y":10431,"z":32239},{"x":85592,"y":78853,"z":55919},{"x":54462,"y":92986,"z":61923},{"x":82923,"y":98099,"z":69987},{"x":65451,"y":96563,"z":45754},{"x":56042,"y":38226,"z":27831},{"x":10024,"y":90940,"z":53047},{"x":51092,"y":54380,"z":11833},{"x":58088,"y":87728,"z":35943},{"x":71276,"y":19838,"z":71114},{"x":28525,"y":42958,"z":70906},{"x":88225,"y":61386,"z":12953},{"x":74256,"y":4303,"z":23200},{"x":49526,"y":36042,"z":15796},{"x":9153,"y":94788,"z":23665},{"x":80101,"y":23495,"z":50819},{"x":31569,"y":685,"z":20686},{"x":22964,"y":44468,"z":35471},{"x":70246,"y":98432,"z":61863},{"x":72794,"y":47183,"z":51421},{"x":6710,"y":30845,"z":79164},{"x":81930,"y":58931,"z":76876},{"x":60308,"y":77291,"z":46931},{"x":95213,"y":70380,"z":78860},{"x":39666,"y":17476,"z":7322},{"x":95063,"y":1905,"z":43670},{"x":54354,"y":12416,"z":76624},{"x":53740,"y":3491,"z":62481},{"x":12864,"y":30769,"z":52235},{"x":32045,"y":63460,"z":79567},{"x":75862,"y":90991,"z":84898},{"x":38669,"y":63989,"z":25022},{"x":7799,"y":5513,"z":46763},{"x":24068,"y":39447,"z":50344},{"x":36023,"y":279,"z":64133},{"x":5465,"y":72858,"z":7840},{"x":29160,"y":24991,"z":21515},{"x":59713,"y":27231,"z":3281},{"x":36164,"y":90203,"z":93847},{"x":75331,"y":71291,"z":86760},{"x":42565,"y":52454,"z":17080},{"x":6955,"y":23878,"z":44603},{"x":40854,"y":37169,"z":54460},{"x":5285,"y":66356,"z":26455},{"x":63058,"y":94851,"z":50037},{"x":12741,"y":4910,"z":77151},{"x":32824,"y":27982,"z":26924},{"x":47478,"y":85766,"z":35219},{"x":16457,"y":86168,"z":96792},{"x":83127,"y":34305,"z":62074},{"x":95548,"y":14535,"z":41035},{"x":88855,"y":5223,"z":94494},{"x":50146,"y":163,"z":79528},{"x":23338,"y":33348,"z":38377},{"x":4070,"y":21412,"z":15793},{"x":96775,"y":52388,"z":47999},{"x":12154,"y":63542,"z":15677},{"x":88504,"y":99262,"z":54679},{"x":12808,"y":85236,"z":5704},{"x":3906,"y":14610,"z":29712},{"x":32559,"y":83568,"z":27884},{"x":93026,"y":38658,"z":39179},{"x":14070,"y":67679,"z":15610},{"x":29713,"y":12625,"z":84667},{"x":6921,"y":19610,"z":86805},{"x":66462,"y":57191,"z":80287},{"x":60537,"y":75661,"z":4167},{"x":38067,"y":9388,"z":24090},{"x":92022,"y":81040,"z":60306},{"x":54484,"y":9192,"z":84268},{"x":36791,"y":90762,"z":60181},{"x":75947,"y":15733,"z":50393},{"x":16807,"y":86935,"z":85406},{"x":8328,"y":60108,"z":63149},{"x":71295,"y":14068,"z":96601},{"x":80613,"y":26940,"z":67177},{"x":89681,"y":62762,"z":34136},{"x":10217,"y":93743,"z":30456},{"x":73059,"y":67804,"z":71175},{"x":9005,"y":74733,"z":45169},{"x":43845,"y":10522,"z":61274},{"x":56005,"y":15428,"z":11649},{"x":83175,"y":17043,"z":59977},{"x":58911,"y":36157,"z":73078},{"x":18088,"y":79910,"z":55693},{"x":81267,"y":64100,"z":26580},{"x":56896,"y":25358,"z":96591},{"x":65687,"y":86996,"z":70012},{"x":77409,"y":95703,"z":52067},{"x":31023,"y":70310,"z":62432},{"x":47952,"y":90510,"z":54558},{"x":68213,"y":85589,"z":46380},{"x":58332,"y":90985,"z":35281},{"x":54333,"y":45220,"z":15414},{"x":94029,"y":8669,"z":19406},{"x":14313,"y":90201,"z":57318},{"x":93133,"y":35598,"z":4739},{"x":57923,"y":86809,"z":49393},{"x":96319,"y":38176,"z":37542},{"x":88108,"y":46715,"z":16554},{"x":57259,"y":86355,"z":83582},{"x":92724,"y":64865,"z":59543},{"x":21703,"y":12027,"z":77429},{"x":82537,"y":84727,"z":10231},{"x":69466,"y":70604,"z":11687},{"x":25405,"y":34281,"z":72216},{"x":13429,"y":28547,"z":21532},{"x":50561,"y":60774,"z":36501},{"x":96078,"y":21610,"z":59197},{"x":75502,"y":7393,"z":90387},{"x":84406,"y":14971,"z":69869},{"x":63056,"y":23127,"z":75447},{"x":2987,"y":35313,"z":26884},{"x":75976,"y":38124,"z":62378},{"x":50678,"y":51910,"z":64734},{"x":92897,"y":9414,"z":78851},{"x":12385,"y":9019,"z":52962},{"x":49969,"y":73736,"z":13654},{"x":85171,"y":97718,"z":94935},{"x":69860,"y":46369,"z":35285},{"x":48996,"y":47871,"z":45331},{"x":34138,"y":70912,"z":14473},{"x":81860,"y":631,"z":53276},{"x":94452,"y":580,"z":73549},{"x":62698,"y":2127,"z":79924},{"x":25326,"y":51241,"z":35453},{"x":96322,"y":9704,"z":66070},{"x":18980,"y":34897,"z":88148},{"x":43690,"y":93420,"z":6598},{"x":74205,"y":53286,"z":67674},{"x":3254,"y":30109,"z":93966},{"x":57779,"y":91666,"z":11952},{"x":72134,"y":40940,"z":44488},{"x":99873,"y":83052,"z":1126},{"x":97309,"y":37450,"z":91956},{"x":55829,"y":40306,"z":91718},{"x":78390,"y":46731,"z":20057},{"x":91883,"y":47744,"z":85866},{"x":78125,"y":3512,"z":78114},{"x":54410,"y":61872,"z":96284},{"x":11630,"y":4634,"z":48245},{"x":583,"y":97186,"z":63568},{"x":50298,"y":62275,"z":77450},{"x":46247,"y":70570,"z":70214},{"x":94826,"y":69412,"z":5578},{"x":78568,"y":78523,"z":95664},{"x":36379,"y":91084,"z":3661},{"x":11137,"y":95017,"z":38825},{"x":71379,"y":44935,"z":23389},{"x":22116,"y":10182,"z":19393},{"x":26631,"y":14386,"z":8913},{"x":90244,"y":18267,"z":36040},{"x":53393,"y":4365,"z":99048},{"x":4079,"y":95272,"z":99036},{"x":59709,"y":84380,"z":53915},{"x":65569,"y":42790,"z":12489},{"x":61765,"y":46485,"z":97361},{"x":82601,"y":59377,"z":69738},{"x":59108,"y":17968,"z":28167},{"x":6237,"y":47107,"z":46872},{"x":93572,"y":74166,"z":87007},{"x":92142,"y":17034,"z":81637},{"x":11605,"y":97185,"z":26640},{"x":69469,"y":6432,"z":23789},{"x":69985,"y":80520,"z":26503},{"x":65480,"y":41448,"z":77875},{"x":16205,"y":81692,"z":74363},{"x":69176,"y":87344,"z":11992},{"x":57385,"y":71058,"z":8987},{"x":23453,"y":46306,"z":89249},{"x":9957,"y":58219,"z":86932},{"x":64935,"y":2339,"z":20205},{"x":31980,"y":85097,"z":77988},{"x":90690,"y":42666,"z":7944},{"x":74914,"y":20830,"z":82559},{"x":68530,"y":35265,"z":76156},{"x":82762,"y":4040,"z":99880},{"x":23472,"y":30526,"z":42857},{"x":87759,"y":55861,"z":81598},{"x":1957,"y":63841,"z":57021},{"x":44944,"y":18845,"z":90230},{"x":54251,"y":38708,"z":38260},{"x":8870,"y":753,"z":71611},{"x":81423,"y":5959,"z":45753},{"x":94142,"y":43274,"z":37696},{"x":86379,"y":70304,"z":7891},{"x":44515,"y":72191,"z":1194},{"x":6205,"y":77653,"z":33542},{"x":92967,"y":18453,"z":48577},{"x":7678,"y":67117,"z":32246},{"x":32575,"y":51952,"z":80296},{"x":22384,"y":73600,"z":14490},{"x":52711,"y":30082,"z":25106},{"x":57480,"y":42599,"z":8822},{"x":43114,"y":59009,"z":65318},{"x":15762,"y":17130,"z":11220},{"x":70564,"y":47248,"z":83517},{"x":2121,"y":75358,"z":38760},{"x":35749,"y":33046,"z":52462},{"x":75238,"y":37380,"z":60124},{"x":96192,"y":97611,"z":49292},{"x":97758,"y":97953,"z":72104},{"x":58423,"y":34477,"z":87667},{"x":38902,"y":67350,"z":99834},{"x":42943,"y":30562,"z":94103},{"x":87924,"y":51390,"z":54745},{"x":81506,"y":4822,"z":81958},{"x":53178,"y":12282,"z":19647},{"x":85139,"y":63746,"z":27671},{"x":81487,"y":89072,"z":36336},{"x":6253,"y":25748,"z":86215},{"x":48027,"y":49098,"z":56556},{"x":43576,"y":68684,"z":55894},{"x":18254,"y":6493,"z":84642},{"x":52909,"y":84771,"z":72402},{"x":65560,"y":53513,"z":82375},{"x":81009,"y":57728,"z":62936},{"x":3688,"y":11379,"z":22586},{"x":26035,"y":72184,"z":18309},{"x":35242,"y":7329,"z":55693},{"x":71894,"y":92384,"z":38569},{"x":14615,"y":55929,"z":26218},{"x":26019,"y":15150,"z":17171},{"x":66669,"y":33277,"z":40758},{"x":24931,"y":4862,"z":27660},{"x":75483,"y":86544,"z":67579},{"x":5083,"y":12873,"z":65276},{"x":1313,"y":87524,"z":29121},{"x":286,"y":17310,"z":28052},{"x":31431,"y":78066,"z":80220},{"x":97016,"y":30080,"z":85033},{"x":55036,"y":47034,"z":83591},{"x":29322,"y":15017,"z":27875},{"x":74140,"y":43294,"z":70313},{"x":11167,"y":98589,"z":17524},{"x":98795,"y":81059,"z":18560},{"x":12125,"y":50747,"z":94693},{"x":29937,"y":96225,"z":94110},{"x":35740,"y":63048,"z":74201},{"x":60963,"y":97471,"z":54331},{"x":25085,"y":26113,"z":87315},{"x":79011,"y":55630,"z":79771},{"x":42718,"y":62834,"z":7988},{"x":66051,"y":65078,"z":5058},{"x":69214,"y":22915,"z":92689},{"x":49908,"y":23340,"z":39297},{"x":69887,"y":84399,"z":92649},{"x":78657,"y":85796,"z":70300},{"x":93483,"y":74898,"z":95070},{"x":46907,"y":50571,"z":41782},{"x":70877,"y":41047,"z":48729},{"x":41524,"y":75771,"z":99337},{"x":53466,"y":47701,"z":38633},{"x":12762,"y":44499,"z":22350},{"x":44688,"y":9488,"z":25293},{"x":71430,"y":21562,"z":52514},{"x":66810,"y":36914,"z":96406},{"x":99100,"y":39368,"z":50027},{"x":3160,"y":44565,"z":15249},{"x":63424,"y":89275,"z":68274},{"x":97623,"y":53617,"z":59825},{"x":2322,"y":2086,"z":37512},{"x":40230,"y":51063,"z":69967},{"x":13255,"y":99386,"z":61085},{"x":76434,"y":51331,"z":71427},{"x":20341,"y":71310,"z":18982},{"x":43964,"y":43210,"z":37969},{"x":36453,"y":34957,"z":99037},{"x":33461,"y":99489,"z":89885},{"x":47027,"y":40641,"z":91396},{"x":90242,"y":14775,"z":6617},{"x":77782,"y":57333,"z":73540},{"x":98828,"y":75818,"z":59586},{"x":25833,"y":94734,"z":11049},{"x":23932,"y":92894,"z":49069},{"x":82190,"y":13166,"z":17162},{"x":96342,"y":7060,"z":51505},{"x":31207,"y":39374,"z":141},{"x":63816,"y":76588,"z":17759},{"x":59091,"y":83198,"z":27627},{"x":15102,"y":8698,"z":84051},{"x":13417,"y":49225,"z":56704},{"x":9458,"y":71311,"z":45454},{"x":46120,"y":10697,"z":75585},{"x":78524,"y":87896,"z":27662},{"x":99544,"y":44501,"z":37210},{"x":77089,"y":31087,"z":11164},{"x":19136,"y":55656,"z":28658},{"x":96836,"y":89792,"z":77233},{"x":1573,"y":69768,"z":70774},{"x":34548,"y":4159,"z":64615},{"x":97621,"y":88974,"z":97672},{"x":16412,"y":95340,"z":19485},{"x":6842,"y":70744,"z":21696},{"x":27216,"y":62222,"z":95880},{"x":54156,"y":26578,"z":79466},{"x":40425,"y":6222,"z":41375},{"x":96958,"y":27155,"z":62281},{"x":69478,"y":3232,"z":61554},{"x":12529,"y":31863,"z":2982},{"x":31439,"y":47831,"z":1305},{"x":27766,"y":33929,"z":62205},{"x":28107,"y":15467,"z":47852},{"x":82990,"y":80468,"z":96872},{"x":66036,"y":57413,"z":76555},{"x":12420,"y":63388,"z":22307},{"x":55157,"y":75636,"z":36508},{"x":51115,"y":58706,"z":29691},{"x":49857,"y":40192,"z":53190},{"x":51028,"y":36248,"z":72849},{"x":96395,"y":20052,"z":57260},{"x":94013,"y":71425,"z":47753},{"x":46776,"y":76728,"z":4429},{"x":52826,"y":60416,"z":51781},{"x":82089,"y":73840,"z":90552},{"x":67515,"y":19072,"z":62369},{"x":93647,"y":14133,"z":12132},{"x":86372,"y":9775,"z":77886},{"x":65032,"y":18651,"z":36941},{"x":29189,"y":6126,"z":46728},{"x":91647,"y":15409,"z":23234},{"x":11242,"y":36242,"z":45807},{"x":53248,"y":16864,"z":60107},{"x":71327,"y":27046,"z":9222},{"x":50402,"y":75876,"z":44510},{"x":33404,"y":96699,"z":84855},{"x":45579,"y":83811,"z":17786},{"x":39497,"y":27697,"z":84681},{"x":36596,"y":86508,"z":9225},{"x":58008,"y":26663,"z":48254},{"x":44342,"y":7399,"z":9660},{"x":1899,"y":94854,"z":78032},{"x":55241,"y":41264,"z":65612},{"x":14171,"y":61023,"z":83439},{"x":15896,"y":85118,"z":19571},{"x":26262,"y":92097,"z":60999},{"x":90827,"y":51591,"z":55977},{"x":2986,"y":30523,"z":93726},{"x":46290,"y":64597,"z":98545},{"x":69550,"y":43907,"z":46248},{"x":14666,"y":65895,"z":65914},{"x":83466,"y":3766,"z":45688},{"x":92475,"y":98128,"z":98120},{"x":14468,"y":1300,"z":83791},{"x":42359,"y":56603,"z":13864},{"x":1998,"y":87292,"z":30935},{"x":30636,"y":21447,"z":4608},{"x":10281,"y":80457,"z":60591},{"x":5927,"y":61652,"z":33198},{"x":84792,"y":90194,"z":23668},{"x":21375,"y":39200,"z":63981},{"x":26148,"y":2563,"z":59453},{"x":3878,"y":71863,"z":32303},{"x":24688,"y":40615,"z":21628},{"x":39305,"y":95887,"z":5211},{"x":77164,"y":28994,"z":894},{"x":60900,"y":79225,"z":35865},{"x":83313,"y":55862,"z":45365},{"x":93289,"y":62769,"z":33883},{"x":78270,"y":54992,"z":59444},{"x":78875,"y":24007,"z":44581},{"x":6586,"y":98225,"z":43721},{"x":7609,"y":14475,"z":55643},{"x":52655,"y":19354,"z":1554},{"x":90896,"y":48830,"z":55935},{"x":79908,"y":38414,"z":98854},{"x":56763,"y":69447,"z":14243},{"x":20261,"y":3353,"z":28051},{"x":48847,"y":25039,"z":69183},{"x":73095,"y":27262,"z":96065},{"x":83789,"y":46377,"z":66387},{"x":28015,"y":18283,"z":30259},{"x":92510,"y":84207,"z":68258},{"x":68858,"y":44507,"z":25847},{"x":51411,"y":84735,"z":80122},{"x":24991,"y":5280,"z":32444},{"x":47479,"y":24448,"z":5575},{"x":9688,"y":93891,"z":63995},{"x":93516,"y":32229,"z":95595},{"x":49792,"y":8956,"z":75349},{"x":82466,"y":2659,"z":42943},{"x":84831,"y":76883,"z":60572},{"x":17885,"y":26212,"z":32434},{"x":72426,"y":43039,"z":45242},{"x":38540,"y":73027,"z":74988},{"x":75250,"y":83395,"z":25528},{"x":60282,"y":63543,"z":61072},{"x":16881,"y":25850,"z":35010},{"x":4519,"y":87097,"z":63686},{"x":47418,"y":98765,"z":14632},{"x":82891,"y":70986,"z":16303},{"x":1366,"y":54258,"z":91108},{"x":46829,"y":42539,"z":81531},{"x":54600,"y":7812,"z":3535},{"x":7137,"y":68680,"z":1136},{"x":88358,"y":8124,"z":599},{"x":69247,"y":88524,"z":96202},{"x":92311,"y":35169,"z":68307},{"x":91805,"y":96856,"z":32492},{"x":27952,"y":60153,"z":4739},{"x":30620,"y":3652,"z":43088},{"x":73324,"y":88130,"z":7501},{"x":86253,"y":9120,"z":62975},{"x":85991,"y":90883,"z":11260},{"x":26466,"y":18263,"z":33451},{"x":39237,"y":61569,"z":79497},{"x":37689,"y":90031,"z":38342},{"x":34696,"y":18264,"z":9226},{"x":45350,"y":47447,"z":78459},{"x":62677,"y":45853,"z":74744},{"x":57411,"y":67900,"z":45868},{"x":7048,"y":66892,"z":23560},{"x":87734,"y":35737,"z":27665},{"x":61109,"y":48318,"z":39804},{"x":36411,"y":27,"z":28578},{"x":6227,"y":24921,"z":9488},{"x":53477,"y":26195,"z":86182},{"x":77449,"y":71240,"z":84188},{"x":38630,"y":98127,"z":69702},{"x":99055,"y":60171,"z":99999},{"x":83349,"y":97372,"z":85844},{"x":39341,"y":86407,"z":75472},{"x":47680,"y":96358,"z":89076},{"x":2527,"y":71367,"z":872},{"x":30127,"y":11915,"z":92875},{"x":27824,"y":89266,"z":39931},{"x":38712,"y":86498,"z":96990},{"x":81776,"y":27828,"z":54759},{"x":63372,"y":15940,"z":11399},{"x":6071,"y":66057,"z":84756},{"x":11294,"y":44057,"z":62574},{"x":35475,"y":49648,"z":234},{"x":24252,"y":10872,"z":63749},{"x":63614,"y":91455,"z":75505},{"x":98426,"y":38129,"z":43879},{"x":31629,"y":13292,"z":31049},{"x":17440,"y":64268,"z":44872},{"x":55257,"y":18709,"z":72695},{"x":96667,"y":64655,"z":65603},{"x":16652,"y":52245,"z":63140},{"x":54593,"y":16042,"z":75859},{"x":62373,"y":68010,"z":91287},{"x":14761,"y":50102,"z":47525},{"x":48995,"y":93258,"z":52452},{"x":35039,"y":36326,"z":85135},{"x":53151,"y":19858,"z":18208},{"x":66066,"y":14395,"z":2972},{"x":69065,"y":88336,"z":55024},{"x":94201,"y":5660,"z":82690},{"x":16758,"y":45854,"z":30312},{"x":86733,"y":56045,"z":24153},{"x":60422,"y":75296,"z":63216},{"x":55152,"y":16869,"z":38967},{"x":40203,"y":10071,"z":52315},{"x":24979,"y":79489,"z":22106},{"x":62418,"y":36395,"z":28813},{"x":36002,"y":25787,"z":36541},{"x":5398,"y":67134,"z":19608},{"x":45567,"y":29666,"z":99903},{"x":10198,"y":53619,"z":78720},{"x":48266,"y":94275,"z":32975},{"x":44723,"y":73473,"z":86109},{"x":71654,"y":10515,"z":46265},{"x":96533,"y":99156,"z":95256},{"x":20173,"y":16315,"z":46171},{"x":55137,"y":67991,"z":2808},{"x":3277,"y":59718,"z":20458},{"x":24998,"y":86919,"z":72481},{"x":31496,"y":67973,"z":16417},{"x":96712,"y":1737,"z":48781},{"x":74575,"y":64801,"z":96462},{"x":87339,"y":2057,"z":43083},{"x":47263,"y":89361,"z":36045},{"x":45953,"y":81799,"z":84544},{"x":85626,"y":35456,"z":62954},{"x":69021,"y":66867,"z":67040},{"x":68578,"y":93277,"z":41488},{"x":2494,"y":14008,"z":27502},{"x":94737,"y":79155,"z":20947},{"x":8300,"y":95363,"z":14661},{"x":4261,"y":1566,"z":36906},{"x":61289,"y":70259,"z":4340},{"x":12951,"y":58498,"z":60371},{"x":97025,"y":16001,"z":79457},{"x":98406,"y":60266,"z":21369},{"x":23175,"y":202,"z":97114},{"x":63765,"y":71722,"z":25127},{"x":80262,"y":89066,"z":48532},{"x":10178,"y":50750,"z":60284},{"x":73012,"y":51122,"z":73821},{"x":71962,"y":85888,"z":29954},{"x":49604,"y":27436,"z":3498},{"x":33824,"y":41959,"z":18841},{"x":65525,"y":44351,"z":33838},{"x":19647,"y":44807,"z":75944},{"x":18365,"y":17396,"z":48109},{"x":12342,"y":62941,"z":32471},{"x":19433,"y":88248,"z":31068},{"x":53830,"y":61194,"z":20751},{"x":50327,"y":80044,"z":70438},{"x":47479,"y":82735,"z":53545},{"x":86533,"y":36374,"z":88149},{"x":76215,"y":10963,"z":7959},{"x":95856,"y":68203,"z":69083},{"x":44406,"y":82301,"z":90909},{"x":75945,"y":41115,"z":32836},{"x":75323,"y":64386,"z":3301},{"x":76595,"y":43267,"z":62186},{"x":71018,"y":80419,"z":60598},{"x":36152,"y":87027,"z":46004},{"x":82895,"y":60201,"z":73317},{"x":21221,"y":20024,"z":32799},{"x":30839,"y":36544,"z":19137},{"x":50665,"y":7076,"z":16737},{"x":85144,"y":25721,"z":53984},{"x":77746,"y":44861,"z":87239},{"x":29612,"y":18252,"z":73085},{"x":63340,"y":8179,"z":74011},{"x":94270,"y":58535,"z":51866},{"x":63687,"y":25565,"z":45329},{"x":42012,"y":17325,"z":65275},{"x":79074,"y":21032,"z":39506},{"x":97103,"y":92135,"z":77620},{"x":42475,"y":76269,"z":40353},{"x":79254,"y":74928,"z":93712},{"x":24498,"y":82815,"z":95878},{"x":24267,"y":44573,"z":4849},{"x":80452,"y":22788,"z":84351},{"x":86115,"y":97837,"z":17072},{"x":6138,"y":63056,"z":38463},{"x":21903,"y":56589,"z":68556},{"x":14741,"y":63246,"z":33703},{"x":22351,"y":52367,"z":5528},{"x":53539,"y":47613,"z":94853},{"x":44785,"y":38786,"z":14171},{"x":88087,"y":94500,"z":56183},{"x":73700,"y":2726,"z":3842},{"x":16250,"y":73010,"z":1209},{"x":55705,"y":14057,"z":73268},{"x":59932,"y":40685,"z":24530},{"x":92494,"y":20475,"z":37609},{"x":91863,"y":64924,"z":42834},{"x":46489,"y":61374,"z":49425},{"x":94363,"y":39872,"z":55202},{"x":13410,"y":98087,"z":45172},{"x":22051,"y":11324,"z":45962},{"x":44849,"y":25662,"z":88491},{"x":75769,"y":63796,"z":1104},{"x":65563,"y":73886,"z":19426},{"x":71046,"y":47690,"z":95322},{"x":74551,"y":83083,"z":69651},{"x":8615,"y":4078,"z":32306},{"x":77226,"y":21601,"z":16840},{"x":92787,"y":80265,"z":48396},{"x":65273,"y":45058,"z":4977},{"x":42226,"y":7234,"z":80530},{"x":32766,"y":81532,"z":34163},{"x":83798,"y":3241,"z":84369},{"x":38469,"y":67001,"z":76815},{"x":1894,"y":88267,"z":7920},{"x":45806,"y":45132,"z":89732},{"x":30945,"y":91180,"z":87272},{"x":1006,"y":55022,"z":65523},{"x":46291,"y":77146,"z":7658},{"x":60054,"y":55561,"z":86698},{"x":19915,"y":80670,"z":65432},{"x":56270,"y":14003,"z":18444},{"x":30490,"y":99328,"z":26538},{"x":37477,"y":78725,"z":5663},{"x":85532,"y":9745,"z":63388},{"x":57982,"y":50202,"z":93462},{"x":15320,"y":29847,"z":5357},{"x":49269,"y":86040,"z":48487},{"x":57114,"y":68294,"z":82371},{"x":95011,"y":61493,"z":60676},{"x":32850,"y":78313,"z":74952},{"x":12425,"y":24856,"z":59986},{"x":61739,"y":94986,"z":51353},{"x":25916,"y":38678,"z":93921},{"x":14719,"y":91750,"z":8822},{"x":70751,"y":25157,"z":31902},{"x":17034,"y":9440,"z":41006},{"x":18664,"y":82908,"z":58921},{"x":36354,"y":22416,"z":73832},{"x":64615,"y":82081,"z":20657},{"x":2180,"y":53837,"z":43929},{"x":71746,"y":26827,"z":47862},{"x":35313,"y":46818,"z":29867},{"x":63995,"y":83312,"z":62542},{"x":26389,"y":18027,"z":38909},{"x":89290,"y":58554,"z":65877},{"x":72755,"y":9306,"z":67463},{"x":34796,"y":76540,"z":91702},{"x":28031,"y":92356,"z":38544},{"x":24223,"y":56569,"z":15528},{"x":76978,"y":72802,"z":49103},{"x":33532,"y":12892,"z":20891},{"x":4541,"y":85088,"z":8174},{"x":1527,"y":12502,"z":12337},{"x":15927,"y":71127,"z":5248},{"x":96299,"y":18029,"z":68425},{"x":52808,"y":90723,"z":37783},{"x":92606,"y":60196,"z":77969},{"x":55899,"y":73686,"z":52560},{"x":23919,"y":13265,"z":86545},{"x":58996,"y":69280,"z":19651},{"x":51013,"y":16113,"z":1727},{"x":71789,"y":30209,"z":56287},{"x":71296,"y":92980,"z":91882},{"x":33408,"y":92160,"z":76319},{"x":42048,"y":10919,"z":83857},{"x":28792,"y":74297,"z":86478},{"x":5389,"y":75937,"z":81049},{"x":79159,"y":44718,"z":95910},{"x":77812,"y":6109,"z":6903},{"x":11429,"y":2081,"z":46678},{"x":28728,"y":57702,"z":40446},{"x":85490,"y":69973,"z":11074},{"x":18985,"y":5870,"z":9670},{"x":41900,"y":64465,"z":86223},{"x":64031,"y":20749,"z":69030},{"x":19968,"y":63958,"z":89442},{"x":7769,"y":52832,"z":45916},{"x":95865,"y":7808,"z":98612},{"x":39867,"y":62263,"z":12449},{"x":83497,"y":47866,"z":75410},{"x":82557,"y":53917,"z":16242},{"x":9807,"y":26078,"z":60255},{"x":15042,"y":22029,"z":69166},{"x":30024,"y":51812,"z":46565},{"x":92338,"y":60566,"z":9364},{"x":57715,"y":22310,"z":11197},{"x":97140,"y":46213,"z":37849},{"x":74647,"y":55761,"z":78801},{"x":6299,"y":96259,"z":38989},{"x":40357,"y":37111,"z":41316},{"x":30968,"y":92364,"z":46696},{"x":76414,"y":51273,"z":99009},{"x":7118,"y":39225,"z":38640},{"x":17737,"y":14009,"z":58457},{"x":39944,"y":3341,"z":30639},{"x":84410,"y":19567,"z":41648},{"x":15931,"y":44298,"z":65121},{"x":79307,"y":94793,"z":80987},{"x":952,"y":58766,"z":5923},{"x":69268,"y":84830,"z":19869},{"x":51994,"y":80483,"z":45526},{"x":32711,"y":76202,"z":36436},{"x":71893,"y":59114,"z":79883},{"x":99066,"y":65336,"z":68361},{"x":41506,"y":31715,"z":45108},{"x":82661,"y":73919,"z":50362},{"x":86802,"y":61113,"z":87896},{"x":80840,"y":25948,"z":71017},{"x":37009,"y":56980,"z":26364},{"x":75120,"y":7694,"z":92969},{"x":64429,"y":15686,"z":26000},{"x":46498,"y":72376,"z":35606},{"x":86689,"y":27004,"z":55646},{"x":4210,"y":73749,"z":54409},{"x":98698,"y":23473,"z":57220},{"x":10744,"y":80544,"z":68264},{"x":87968,"y":61897,"z":73680},{"x":52729,"y":8385,"z":35266},{"x":18864,"y":31204,"z":87105},{"x":86199,"y":81893,"z":5053},{"x":24062,"y":50963,"z":68619},{"x":61890,"y":58242,"z":84398},{"x":20147,"y":67830,"z":14430},{"x":98776,"y":33533,"z":40129},{"x":12323,"y":27694,"z":64221},{"x":72068,"y":17313,"z":20441},{"x":7514,"y":65746,"z":67963},{"x":52487,"y":28248,"z":54826},{"x":71958,"y":4904,"z":93581},{"x":98092,"y":16710,"z":97076},{"x":54744,"y":77145,"z":9758},{"x":44623,"y":43540,"z":95666},{"x":9774,"y":88326,"z":80075},{"x":12941,"y":63893,"z":95040},{"x":94286,"y":36626,"z":59162},{"x":51358,"y":17484,"z":86901},{"x":40056,"y":64515,"z":77119},{"x":87783,"y":80188,"z":43564},{"x":98201,"y":84610,"z":75208},{"x":61098,"y":97658,"z":6479},{"x":86959,"y":5239,"z":38368},{"x":73286,"y":38785,"z":89091},{"x":23913,"y":59499,"z":26416},{"x":25602,"y":57654,"z":72854},{"x":63260,"y":85932,"z":86084},{"x":13537,"y":48315,"z":73193},{"x":19335,"y":11368,"z":43913},{"x":83423,"y":60937,"z":37261},{"x":9313,"y":47305,"z":36979},{"x":723,"y":518,"z":67639},{"x":46040,"y":85305,"z":22039},{"x":31475,"y":33436,"z":47686},{"x":31640,"y":79385,"z":76978},{"x":27354,"y":39004,"z":31931},{"x":62329,"y":20080,"z":37076},{"x":81285,"y":85346,"z":48141},{"x":12914,"y":98357,"z":15867},{"x":97984,"y":34251,"z":11049},{"x":12225,"y":26767,"z":39580},{"x":88412,"y":31758,"z":79197},{"x":14614,"y":36309,"z":35051},{"x":84857,"y":60361,"z":669},{"x":51578,"y":50383,"z":82234}];
321
322 // Normalize coordinates to fit in view
323 const maxCoord = Math.max(...junctions.flatMap(j => [j.x, j.y, j.z]));
324 const scale = 20 / maxCoord;
325
326 // Calculate all pairwise distances
327 function distance(a, b) {
328 return Math.sqrt(
329 (a.x - b.x) ** 2 +
330 (a.y - b.y) ** 2 +
331 (a.z - b.z) ** 2
332 );
333 }
334
335 const pairs = [];
336 for (let i = 0; i < junctions.length; i++) {
337 for (let j = i + 1; j < junctions.length; j++) {
338 pairs.push({
339 i,
340 j,
341 distance: distance(junctions[i], junctions[j])
342 });
343 }
344 }
345
346 // Sort by distance
347 pairs.sort((a, b) => a.distance - b.distance);
348
349 // Union-Find for circuit tracking
350 class UnionFind {
351 constructor(n) {
352 this.parent = Array.from({ length: n }, (_, i) => i);
353 this.size = Array(n).fill(1);
354 }
355
356 find(x) {
357 if (this.parent[x] !== x) {
358 this.parent[x] = this.find(this.parent[x]);
359 }
360 return this.parent[x];
361 }
362
363 union(x, y) {
364 const rootX = this.find(x);
365 const rootY = this.find(y);
366
367 if (rootX === rootY) return false;
368
369 if (this.size[rootX] < this.size[rootY]) {
370 this.parent[rootX] = rootY;
371 this.size[rootY] += this.size[rootX];
372 } else {
373 this.parent[rootY] = rootX;
374 this.size[rootX] += this.size[rootY];
375 }
376
377 return true;
378 }
379
380 getCircuitSizes() {
381 const circuits = new Map();
382 for (let i = 0; i < this.parent.length; i++) {
383 const root = this.find(i);
384 circuits.set(root, this.size[root]);
385 }
386 return Array.from(circuits.values()).sort((a, b) => b - a);
387 }
388
389 getCircuitCount() {
390 const roots = new Set();
391 for (let i = 0; i < this.parent.length; i++) {
392 roots.add(this.find(i));
393 }
394 return roots.size;
395 }
396 }
397
398 // Build animation stages for Part 1 (first 1000 connections) and Part 2 (until single circuit)
399 const stages = [];
400 const uf = new UnionFind(junctions.length);
401 const connections = [];
402 let part2ConnectionIndex = -1;
403 let part2Product = 0;
404
405 let step = 0;
406 while (true) {
407 const circuitSizes = uf.getCircuitSizes();
408 const top3 = circuitSizes.slice(0, 3);
409 const product = top3.length >= 3 ? top3[0] * top3[1] * top3[2] : 0;
410 const circuitCount = uf.getCircuitCount();
411
412 stages.push({
413 connections: [...connections],
414 circuits: circuitCount,
415 largest: circuitSizes[0] || 1,
416 product,
417 circuitSizes: [...circuitSizes],
418 part2Product: part2Product
419 });
420
421 // Check if we've reached a single circuit (Part 2 complete)
422 if (circuitCount === 1 && part2ConnectionIndex === -1) {
423 part2ConnectionIndex = step - 1; // The previous connection completed it
424 if (part2ConnectionIndex >= 0) {
425 const lastPair = pairs[part2ConnectionIndex];
426 part2Product = junctions[lastPair.i].x * junctions[lastPair.j].x;
427 }
428 // Update the current stage with the part2Product
429 stages[stages.length - 1].part2Product = part2Product;
430 }
431
432 // Stop after reaching single circuit, or if we've exhausted pairs
433 if (circuitCount === 1 || step >= pairs.length) {
434 break;
435 }
436
437 const pair = pairs[step];
438 uf.union(pair.i, pair.j);
439 connections.push(pair);
440 step++;
441 }
442
443 console.log('Part 1: After 1000 connections, product =', stages[Math.min(1000, stages.length - 1)].product);
444 console.log('Part 2: Single circuit at connection', part2ConnectionIndex, ', product =', part2Product);
445
446 // Three.js setup
447 const scene = new THREE.Scene();
448 scene.background = new THREE.Color(0x0d0d15);
449
450 const camera = new THREE.PerspectiveCamera(
451 75,
452 window.innerWidth / window.innerHeight,
453 0.1,
454 1000
455 );
456 camera.position.set(15, 15, 15);
457
458 const renderer = new THREE.WebGLRenderer({
459 canvas: document.getElementById('canvas'),
460 antialias: true
461 });
462 renderer.setSize(window.innerWidth, window.innerHeight);
463 renderer.setPixelRatio(window.devicePixelRatio);
464
465 const controls = new OrbitControls(camera, renderer.domElement);
466 controls.enableDamping = true;
467 controls.dampingFactor = 0.05;
468 controls.target.set(0, 3, 0); // Shift the view down by 3 units
469 controls.autoRotate = true;
470 controls.autoRotateSpeed = 0.5; // Slow rotation (0.5 degrees per frame at 60fps = 30 seconds per rotation)
471 controls.update();
472
473 // Lighting
474 const ambientLight = new THREE.AmbientLight(0xffffff, 0.4);
475 scene.add(ambientLight);
476
477 const pointLight1 = new THREE.PointLight(0xffffff, 0.6);
478 pointLight1.position.set(10, 10, 10);
479 scene.add(pointLight1);
480
481 const pointLight2 = new THREE.PointLight(0xffffff, 0.4);
482 pointLight2.position.set(-10, -10, -10);
483 scene.add(pointLight2);
484
485 // Create junction boxes (smaller)
486 const junctionGeometry = new THREE.SphereGeometry(0.1, 12, 12);
487 const junctionMaterial = new THREE.MeshPhongMaterial({
488 color: 0x89b4fa,
489 emissive: 0x89b4fa,
490 emissiveIntensity: 0.2
491 });
492
493 const junctionMeshes = junctions.map((j, idx) => {
494 const mesh = new THREE.Mesh(junctionGeometry, junctionMaterial);
495 mesh.position.set(
496 (j.x * scale) - 10,
497 (j.y * scale) - 10,
498 (j.z * scale) - 10
499 );
500 mesh.userData.index = idx;
501 scene.add(mesh);
502 return mesh;
503 });
504
505 // Connection lines - pre-render all cylinders (enough to reach single circuit)
506 let connectionCylinders = [];
507
508 // Determine how many connections we need (until single circuit)
509 const maxConnections = Math.min(pairs.length, stages[stages.length - 1].connections.length);
510
511 // Pre-create all connection cylinders
512 console.log('Pre-rendering', maxConnections, 'connections...');
513 pairs.slice(0, maxConnections).forEach((pair, idx) => {
514 const j1 = junctions[pair.i];
515 const j2 = junctions[pair.j];
516
517 const p1 = new THREE.Vector3(
518 (j1.x * scale) - 10,
519 (j1.y * scale) - 10,
520 (j1.z * scale) - 10
521 );
522 const p2 = new THREE.Vector3(
523 (j2.x * scale) - 10,
524 (j2.y * scale) - 10,
525 (j2.z * scale) - 10
526 );
527
528 // Create cylinder between points
529 const direction = new THREE.Vector3().subVectors(p2, p1);
530 const length = direction.length();
531 const cylinderGeometry = new THREE.CylinderGeometry(0.015, 0.015, length, 4);
532 const cylinderMaterial = new THREE.MeshBasicMaterial({
533 transparent: true,
534 opacity: 0.8
535 });
536
537 const cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
538
539 // Position at midpoint
540 cylinder.position.copy(p1).add(direction.multiplyScalar(0.5));
541
542 // Orient cylinder to connect the two points
543 cylinder.quaternion.setFromUnitVectors(
544 new THREE.Vector3(0, 1, 0),
545 direction.normalize()
546 );
547
548 // Initially invisible
549 cylinder.visible = false;
550 cylinder.userData.pairIndex = idx;
551 cylinder.userData.i = pair.i;
552 cylinder.userData.j = pair.j;
553
554 scene.add(cylinder);
555 connectionCylinders.push(cylinder);
556 });
557 console.log('Pre-rendering complete!');
558
559 // Pre-generate stable colors for each junction based on their index
560 const junctionColors = [];
561 const hues = [];
562 for (let i = 0; i < junctions.length; i++) {
563 const hue = (i * 137.508) % 360; // Golden angle for good distribution
564 junctionColors.push(new THREE.Color().setHSL(hue / 360, 0.8, 0.55));
565 }
566
567 function updateConnections(stage) {
568 const numConnections = stage.connections.length;
569
570 if (numConnections === 0) {
571 // No connections yet - make all junctions small and hide all cylinders
572 junctionMeshes.forEach(mesh => {
573 mesh.scale.set(0.33, 0.33, 0.33);
574 mesh.material = new THREE.MeshPhongMaterial({
575 color: 0x89b4fa,
576 emissive: 0x89b4fa,
577 emissiveIntensity: 0.2
578 });
579 });
580 connectionCylinders.forEach(cyl => cyl.visible = false);
581 return;
582 }
583
584 // Color junctions by circuit - use lowest junction index as stable color
585 const uf = new UnionFind(junctions.length);
586 stage.connections.forEach(conn => uf.union(conn.i, conn.j));
587
588 // Map each root to the lowest junction index in that circuit for stable colors
589 const circuitColors = new Map();
590 for (let i = 0; i < junctions.length; i++) {
591 const root = uf.find(i);
592 if (!circuitColors.has(root)) {
593 // Find the lowest index in this circuit
594 let lowestInCircuit = i;
595 for (let j = 0; j < i; j++) {
596 if (uf.find(j) === root) {
597 lowestInCircuit = j;
598 break;
599 }
600 }
601 circuitColors.set(root, junctionColors[lowestInCircuit]);
602 }
603 }
604
605 // Track which junctions are connected
606 const connectedJunctions = new Set();
607 stage.connections.forEach(conn => {
608 connectedJunctions.add(conn.i);
609 connectedJunctions.add(conn.j);
610 });
611
612 junctionMeshes.forEach((mesh, idx) => {
613 const root = uf.find(idx);
614 const color = circuitColors.get(root);
615
616 mesh.material = new THREE.MeshPhongMaterial({
617 color: color,
618 emissive: color,
619 emissiveIntensity: 0.4
620 });
621
622 // Make unconnected junctions smaller
623 if (connectedJunctions.has(idx)) {
624 mesh.scale.set(1, 1, 1);
625 } else {
626 mesh.scale.set(0.33, 0.33, 0.33);
627 }
628 });
629
630 // Show/hide cylinders and update their colors based on current stage
631 connectionCylinders.forEach((cylinder, idx) => {
632 if (idx < numConnections) {
633 cylinder.visible = true;
634 // Update color to match circuit
635 const root = uf.find(cylinder.userData.i);
636 const lineColor = circuitColors.get(root);
637 cylinder.material.color = lineColor;
638 } else {
639 cylinder.visible = false;
640 }
641 });
642 }
643
644 // Animation state
645 let currentStage = 0;
646 let isPlaying = false;
647 let lastTime = 0;
648
649 const playBtn = document.getElementById('play');
650 const prevBtn = document.getElementById('prev');
651 const nextBtn = document.getElementById('next');
652 const resetBtn = document.getElementById('reset');
653 const timelineSlider = document.getElementById('timeline');
654 const timelineStep = document.getElementById('timelineStep');
655 const statsInfo = document.getElementById('statsInfo');
656
657 function updateUI() {
658 const stage = stages[currentStage];
659 timelineStep.textContent = `Step ${currentStage} of ${stages.length - 1}`;
660
661 const part1Result = stages[Math.min(1000, stages.length - 1)].product;
662 const part2Result = stage.part2Product || 0;
663
664 statsInfo.textContent = `Circuits: ${stage.circuits} | Largest: ${stage.largest} | Part 1: ${part1Result.toLocaleString()} | Part 2: ${part2Result.toLocaleString()}`;
665
666 prevBtn.disabled = currentStage === 0;
667 nextBtn.disabled = currentStage === stages.length - 1;
668
669 // Update timeline slider and gradient
670 timelineSlider.value = currentStage;
671 const percent = (currentStage / (stages.length - 1)) * 100;
672 timelineSlider.style.background = `linear-gradient(to right, #a6e3a1 0%, #a6e3a1 ${percent}%, #313244 ${percent}%, #313244 100%)`;
673
674 updateConnections(stage);
675 }
676
677 function goToStage(index) {
678 currentStage = Math.max(0, Math.min(stages.length - 1, index));
679 updateUI();
680 }
681
682 prevBtn.addEventListener('click', () => goToStage(currentStage - 1));
683 nextBtn.addEventListener('click', () => goToStage(currentStage + 1));
684 resetBtn.addEventListener('click', () => goToStage(0));
685
686 // Timeline slider scrubbing
687 timelineSlider.addEventListener('input', (e) => {
688 goToStage(parseInt(e.target.value));
689 });
690
691 playBtn.addEventListener('click', () => {
692 isPlaying = !isPlaying;
693 playBtn.textContent = isPlaying ? '⏸ Pause' : '▶ Play';
694 if (isPlaying && currentStage === stages.length - 1) {
695 goToStage(0);
696 }
697 });
698
699 document.addEventListener('keydown', (e) => {
700 if (e.key === 'ArrowLeft') prevBtn.click();
701 if (e.key === 'ArrowRight') nextBtn.click();
702 if (e.key === ' ') {
703 e.preventDefault();
704 playBtn.click();
705 }
706 if (e.key === 'r' || e.key === 'R') resetBtn.click();
707 });
708
709 window.addEventListener('resize', () => {
710 camera.aspect = window.innerWidth / window.innerHeight;
711 camera.updateProjectionMatrix();
712 renderer.setSize(window.innerWidth, window.innerHeight);
713 });
714
715 // Animation loop
716 function animate(time) {
717 requestAnimationFrame(animate);
718
719 // Auto-advance if playing (zero delay - advance every frame)
720 if (isPlaying) {
721 if (currentStage < stages.length - 1) {
722 goToStage(currentStage + 1);
723 } else {
724 isPlaying = false;
725 playBtn.textContent = '▶ Play';
726 }
727 }
728
729 controls.update();
730 renderer.render(scene, camera);
731 }
732
733 // Initialize - start at step 0
734 currentStage = 0;
735 updateUI();
736 animate(0);
737 </script>
738</body>
739</html>