{"id":1136,"date":"2024-12-08T19:47:02","date_gmt":"2024-12-08T17:47:02","guid":{"rendered":"https:\/\/www.juustila.com\/antti\/?p=1136"},"modified":"2024-12-08T19:54:52","modified_gmt":"2024-12-08T17:54:52","slug":"advent-of-code-day-8-resonant-collinearity","status":"publish","type":"post","link":"https:\/\/www.juustila.com\/antti\/2024\/12\/08\/advent-of-code-day-8-resonant-collinearity\/","title":{"rendered":"Advent of Code Day 8 &#8211; Resonant Collinearity"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">This was surprisingly easy! The part 1 of <a href=\"https:\/\/adventofcode.com\/2024\/day\/8\">today&#8217;s task<\/a> was correct on the first run, which is the first time this has happened to me! Usually I make stupid mistakes, not reading the puzzle carefully enough, and rushing to coding with too little planning ahead.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The puzzle part 1 was to find out positions on a map to place antinodes to prevent antennas to emit a signal that makes people 0.1% more likely to buy Easter Bunny brand Imitation Mediocre Chocolate as a Christmas gift.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Calculate the impact of the signal. How many unique locations within the bounds of the map contain an antinode?<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">A map looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">............<br>........0...<br>.....0......<br>.......0....<br>....0.......<br>......A.....<br>............<br>............<br>........A...<br>.........A..<br>............<br>............<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Where <code>0<\/code> and <code>A<\/code> are antennas that are sending on a same frequency, <code>A<\/code> antennas on their own and <code>0<\/code> antennas theirs, respectively. To prevent their signals, the antinodes ( <code>#<\/code>)must be placed <em>in line<\/em> of the antennas, after the first and last <em>pair of antennas<\/em>, like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">......#....#<br>...#....0...<br>....#0....#.<br>..#....0....<br>....0....#..<br>.#....A.....<br>...#........<br>#......#....<br>........A...<br>.........A..<br>..........#.<br>..........#.<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To solve the problem, I implented a <code>Dictionary<\/code> with key-value -pairs (the <code>[Character: [Point]]<\/code> below), where the key is an antenna with a specific frequency and value is an array of (x, y) positions on the map where that kind of antennas are placed. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>var antinodes: Set&lt;Point&gt; = &#91;]\nlet matrix: Matrix&lt;Character&gt; = parse(data: data)\nlet antennaMap: &#91;Character: &#91;Point]] = parseAntennaMap(matrix)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After parsing the antennas and their positions into a <code>Matrix<\/code>, and extracting the antennas and their positions into the dictionary, I could print out the dictionary keys (antennas) with the values (a list of positions for the antennas with the same frequency ):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">Antenna A<br>  5:6<br>  8:8<br>  9:9<br>Antenna 0<br>  1:8<br>  2:5<br>  3:7<br>  4:4<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So I could verify that everything is in order for the next step of the puzzle.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I already had a <code>Point<\/code> structure, having the x and y coordinates, as well as operations to calculate the difference of two points in the coordinate (the distance between them) as well as add together two coordinate points to extrapolate the line between two antennas to position the antinodes inline with the antennas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So what to do with these? First I needed to handle all the antennas with the same frequency in pairs, to extrapolate the line between them to both directions to add the antinodes. The <code>permutations(ofCount:)<\/code> algorithm did that. For each pair of antennas, I determined which comes first (point is upper on the map compared to the other) and vice versa. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After that I counted the difference between the first and last point, because the antinode must be place an equal distance away from the antennas. Then I added a point above the first point (<code>first - difference<\/code>) and below the last point (<code>last + difference<\/code>). <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then I just added these two antinodes into a <code>Set<\/code> to get a number of antinodes placed on the map:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>for (_, points) in antennaMap {\n  let permutations = points.permutations(ofCount: 2)\n  for permutation in permutations {\n     let first =\n     permutation.first! &lt; permutation.last! ? permutation.first! : permutation.last!\n    let last = first == permutation.first! ? permutation.last! : permutation.first!\n    let difference = last - first\n    antinodes.insert(first - difference)\n    antinodes.insert(last + difference)\n  }\n}\nantinodes = antinodes.filter({ matrix.contains(y: $0.y, x: $0.x) })\nreturn antinodes.count<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Finally I made sure no antinodes were placed outside the map coordinates (using <code>filter<\/code> to include only those points in the area of the matrix coordinates) and finally returning the count of antinodes placed (the puzzle answer).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Part 2 was just an addition to part 1. Instead of placing one antinode before and after the line of two antennas, place them so that the antinodes are repeated with equal spacing along the line formed by a pair of antennas, until to the edge of the map.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What I first missed in the puzzle instructions was that the positions of the <em>antennas<\/em> also count in the final answer, not just the antinodes. <em>I did get<\/em> that the unique positions only are counted (that is why the <code>Set&lt;Point&gt;<\/code> is used for antinode positions). As I realized this, I just formed a <em>union<\/em> of antinode and antenna positions, and count of those was the correct answer!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In total, this didn&#8217;t take long to solve, thanks to the existing data structures and algorithms, both from Swift, Swift libraries (Swift Algorithms) and my own utilities from previous years. Performance is also OK:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ swift run -c release AdventOfCode 8 --benchmark<br>Building for production...<br>Build of product 'AdventOfCode' complete! (0.28s)<br>Executing Advent of Code challenge 8...<br>Part 1: 259<br>Part 2: 927<br>Part 1 took 0.000727958 seconds, part 2 took 0.000798333 seconds.<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This was surprisingly easy! The part 1 of today&#8217;s task was correct on the first run, which is the first time this has happened to me! Usually I make stupid mistakes, not reading the puzzle carefully enough, and rushing to coding with too little planning ahead. The puzzle part 1 was to find out positions &hellip; <a href=\"https:\/\/www.juustila.com\/antti\/2024\/12\/08\/advent-of-code-day-8-resonant-collinearity\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Advent of Code Day 8 &#8211; Resonant Collinearity&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[2],"tags":[136,48,149,70,46],"class_list":["post-1136","post","type-post","status-publish","format-standard","hentry","category-coding","tag-advent-of-code","tag-algorithms","tag-aoc2024","tag-programming","tag-swift"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts\/1136","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/comments?post=1136"}],"version-history":[{"count":4,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts\/1136\/revisions"}],"predecessor-version":[{"id":1143,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/posts\/1136\/revisions\/1143"}],"wp:attachment":[{"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/media?parent=1136"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/categories?post=1136"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.juustila.com\/antti\/wp-json\/wp\/v2\/tags?post=1136"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}