finish footer links
This commit is contained in:
@@ -49,7 +49,7 @@ My word-search grid appears to be 140 characters by 140, so I'm just going to ha
|
||||
|
||||
Not gonna lie here, this part took me _way_ longer than I expected it to. See, the standard way to read a file in Fortran is with the `read()` statement. (It looks like a function call, but it's not.) You use it something like this:
|
||||
|
||||
```fortran
|
||||
```f90
|
||||
read(file_handle, *) somevar, anothervar, anothervar2
|
||||
```
|
||||
|
||||
@@ -57,7 +57,7 @@ Or at least, that's one way of using it. But here's the problem: by default, For
|
||||
|
||||
Initially, I thought I might be able to do this:
|
||||
|
||||
```fortran
|
||||
```f90
|
||||
character, dimension(140, 140) :: grid
|
||||
|
||||
! ...later
|
||||
@@ -70,7 +70,7 @@ But sadly, this kept spitting out errors about how it had encountered the end of
|
||||
|
||||
My next try looked something like this:
|
||||
|
||||
```fortran
|
||||
```f90
|
||||
do row = 1, 100
|
||||
read(file_handle, *) grid(row, :)
|
||||
end do
|
||||
@@ -82,7 +82,7 @@ I'm pretty sure the proper way to do this would be to figure out how to set the
|
||||
|
||||
So instead, I decided to just make it dumber.
|
||||
|
||||
```fortran
|
||||
```f90
|
||||
program advent04
|
||||
implicit none
|
||||
|
||||
@@ -139,7 +139,7 @@ S A M X M A S
|
||||
S . . S . . S
|
||||
```
|
||||
|
||||
Which has all 8 possible orientationS of the word `XMAS` starting from the central X. Then, we can just take a sliding "window" of the same size into our puzzle grid and compare it to the test grid. This is a native operation in Fortran--comparing two arrays of the same size results in a third array whose elements are the result of each individual comparison from the original arrays. Then we can just call `count()` on the resulting array to get the number of true values, and we know how many characters matched up. Subtract 1 for the central X we already knew about, then divide by 3 since there are 3 letters remaining in each occurrence of `XMAS`, and Bob's your uncle, right?
|
||||
Which has all 8 possible orientations of the word `XMAS` starting from the central X. Then, we can just take a sliding "window" of the same size into our puzzle grid and compare it to the test grid. This is a native operation in Fortran--comparing two arrays of the same size results in a third array whose elements are the result of each individual comparison from the original arrays. Then we can just call `count()` on the resulting array to get the number of true values, and we know how many characters matched up. Subtract 1 for the central X we already knew about, then divide by 3 since there are 3 letters remaining in each occurrence of `XMAS`, and Bob's your uncle, right?
|
||||
|
||||
...Wait, no. That won't work because it doesn't account for partial matches. Say we had a "window" that looked like this (I'm only showing the bottom-right quadrant of the window for simplicity):
|
||||
|
||||
@@ -164,7 +164,7 @@ Will this work? Is it even marginally more efficient than the stupidly obvious w
|
||||
|
||||
Ok, first things first. Let's adjust the data-loading code to pad the grid with 3 bogus values on each edge, so that we can still generate our window correctly when we're looking at a point near the edge of the grid.
|
||||
|
||||
```fortran
|
||||
```f90
|
||||
grid = '.' ! probably wouldn't matter if we skipped this, uninitialized memory just makes me nervous
|
||||
|
||||
open(newunit=handle, file="data/04.txt", status="old", action="read")
|
||||
@@ -196,7 +196,7 @@ Oh. Oh, _noooo_.
|
||||
|
||||
It's okay, I mean, uh, it's not _that_ much higher. Only two orders of magnitude, and what are the odds of all eight versions of `XMAS` appearing in the same window, anyway? Something like 1/4<sup>25</sup>? Maybe we can still make this work.
|
||||
|
||||
```fortran
|
||||
```f90
|
||||
integer function count_xmas(row, col) result(count)
|
||||
implicit none
|
||||
|
||||
@@ -277,7 +277,7 @@ Those `&`s are line-continuation characters, by the way. Apparently you can't ha
|
||||
|
||||
Now we just have to put it all together:
|
||||
|
||||
```fortran
|
||||
```f90
|
||||
total = 0
|
||||
do col = 4, 143
|
||||
do row = 4, 143
|
||||
@@ -314,7 +314,7 @@ Hmm, I wonder if there's a way to take a single starting test grid and manipulat
|
||||
|
||||
Turns out, yes! Yes there is. We can use a combination of slicing with a negative step, and transposing, which switches rows with columns, effectively rotating and flipping the array. So setting up our test grids looks like this:
|
||||
|
||||
```fortran
|
||||
```f90
|
||||
character, dimension(3, 3) :: window, t1, t2, t3, t4
|
||||
|
||||
t1 = reshape( &
|
||||
@@ -332,7 +332,7 @@ t4 = t3(:, 3:1:-1) ! flip t3 left-to-right
|
||||
|
||||
Then we can just compare the window to each test grid:
|
||||
|
||||
```fortran
|
||||
```f90
|
||||
window = grid(row - 1:row + 1, col - 1:col + 1)
|
||||
if ( &
|
||||
count_matches(window, t1) == 5 &
|
||||
|
||||
Reference in New Issue
Block a user