Skip to content

Commit 522ed3b

Browse files
Update docs on Fri Dec 20 09:34:36 UTC 2024
1 parent 195f806 commit 522ed3b

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

2024/20/index.html

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,19 @@ <h2 id="problem-name">Race Condition</h2>
279279
</div>
280280

281281
<div class="content">
282-
<div id="notes"><p>The Historians are quite pixelated again. This time, a massive, black building looms over you - you&#39;re <a href="/2017/day/24">right outside</a> the CPU!</p>
282+
<div id="notes"><p>The Historians are quite pixelated again. This time, a massive, black building looms over you - you&#39;re <em>right outside</em> the CPU!</p>
283283
<p>While The Historians get to work, a nearby program sees that you&#39;re idle and challenges you to a <em>race</em>. Apparently, you&#39;ve arrived just in time for the frequently-held <em>race condition</em> festival!</p>
284284
<p><em>Visit the website for the full story and <a href="https://adventofcode.com/2024/day/20">full puzzle</a> description.</em></p>
285+
<p>Here is your corrected text with improved grammar and flow: </p>
286+
<p>The problem included a small but crucial hint: <em>there is only a single path from the start to the end</em>. Moreover, there are no dead ends in the input; it&#39;s just a single, continuous trace. </p>
287+
<p>I created a function that returns the points of the track in from finish to start. This way, the index of an item in the array corresponds to its distance to the finish line. Then, I go over the path. For each position, the number of possible cheats is calculated by checking what happens if we are trying to make a shortcut to any other positions that is closer to the finish line. </p>
288+
<p>There are a number of cases to consider:</p>
289+
<ul>
290+
<li>the target position is too far away. This happens when its Manhattan distance is greater than the allowed <em>cheat</em> limit</li>
291+
<li>the target is within range, but the saving is less than 100</li>
292+
<li>the target is within range, and the saving is at least 100</li>
293+
</ul>
294+
<p>We need to determine the number of good cheats for each position add them up. I used Parallel LINQ here, as the regular sequential one took significantly more time.</p>
285295
</div>
286296
<div id="code-container"><pre class="hljs language-csharp"><code>namespace AdventOfCode.Y2024.Day20;
287297

@@ -298,29 +308,26 @@ <h2 id="problem-name">Race Condition</h2>
298308

299309
int Solve(string input, int cheat) {
300310
var path = GetPath(input);
301-
302-
// this nested loop is 6x times faster then the same thing with LINQ ¯\_(ツ)_/¯
303-
var res = 0;
304-
for (var i = 0; i &lt; path.Length; i++) {
305-
for (var j = i + 1; j &lt; path.Length; j++) {
306-
var dist = Manhattan(path[i], path[j]);
307-
308-
// the index of an element in the path equals to its distance
309-
// from the finish line
310-
311-
var saving = j - (i + dist);
312-
if (dist &lt;= cheat &amp;&amp; saving &gt;= 100) {
313-
res++;
314-
}
315-
}
316-
}
317-
return res;
311+
var indices = Enumerable.Range(0, path.Length).ToArray();
312+
313+
// sum up the worthy cheats for each index along the path
314+
var cheatsFromI = (int i) =&gt; (
315+
from j in indices[0..i]
316+
let dist = Manhattan(path[i], path[j])
317+
let saving = i - (j + dist)
318+
where dist &lt;= cheat &amp;&amp; saving &gt;= 100
319+
select 1
320+
).Sum();
321+
322+
// parallel is gold today, it gives us an 3-4x boost
323+
return indices.AsParallel().Select(cheatsFromI).Sum();
318324
}
319325

320326
int Manhattan(Complex a, Complex b) =&gt;
321327
(int)(Math.Abs(a.Imaginary - b.Imaginary) + Math.Abs(a.Real - b.Real));
322328

323-
// follow the path from start to finish, supposed that there is a single track in the input
329+
// follow the path from finish to start, supposed that there is a single track in the input
330+
// the index of a position in the returned array equals to its distance from the finish
324331
Complex[] GetPath(string input) {
325332
var lines = input.Split(&quot;\n&quot;);
326333
var map = (
@@ -329,19 +336,18 @@ <h2 id="problem-name">Race Condition</h2>
329336
select new KeyValuePair&lt;Complex, char&gt;(x + y * Complex.ImaginaryOne, lines[y][x])
330337
).ToDictionary();
331338

339+
Complex[] dirs = [-1, 1, Complex.ImaginaryOne, -Complex.ImaginaryOne];
340+
332341
var start = map.Keys.Single(k =&gt; map[k] == &#039;S&#039;);
333342
var goal = map.Keys.Single(k =&gt; map[k] == &#039;E&#039;);
334343

335-
var (prev, cur, dir) = ((Complex?)null, start, Complex.ImaginaryOne);
344+
var (prev, cur) = ((Complex?)null, goal);
345+
var res = new List&lt;Complex&gt; { cur };
336346

337-
var res = new List&lt;Complex&gt; { start };
338-
while (cur != goal) {
339-
if (map[cur + dir] == &#039;#&#039; || cur + dir == prev) {
340-
dir *= Complex.ImaginaryOne;
341-
} else {
342-
(prev, cur) = (cur, cur + dir);
343-
res.Add(cur);
344-
}
347+
while (cur != start) {
348+
var dir = dirs.Single(dir =&gt; map[cur + dir] != &#039;#&#039; &amp;&amp; cur + dir != prev);
349+
(prev, cur) = (cur, cur + dir);
350+
res.Add(cur);
345351
}
346352
return res.ToArray();
347353
}

0 commit comments

Comments
 (0)