Advent of Code (in MiniScript), Day 8
Tags: miniscript, adventofcode, programming
Published: 2022-12-08 15:38:02

Last night was [Day 8](https://adventofcode.com/2022/day/8) of the annual [Advent of Code](https://adventofcode.com/) programming contest.  [As usual](https://dev.to/search?q=JoeStrout%20%23adventofcode), I tackled it in [MiniScript](https://miniscript.org/).

In this challenge, we're given a grid of digits (0-9) representing the height of trees in a forest.  The elves first want to figure out which trees are visible from outside the woods — that is, not blocked by some equally tall or taller tree to the north, south, east, or west.

Here's my solution:
```
fname = "input.txt"

grid = file.readLines(fname)
if not grid[-1] then grid.remove -1
width = grid[0].len
height = grid.len
print "width: " + width + ", height: " + height

isVisInDir = function(x,y, dx,dy)
	h = grid[y][x]
	while true
		x = x + dx
		y = y + dy
		if x < 0 or x >= width or y < 0 or y >= height then
			return true
		end if
		if grid[y][x] >= h then return false
	end while
end function

isVisible = function(x,y)
	return isVisInDir(x,y, -1,0) or
		isVisInDir(x,y, 1,0) or
		isVisInDir(x,y, 0,-1) or
		isVisInDir(x,y, 0,1)
end function

count = 0
for x in range(0, width-1)
	for y in range(0, height-1)
		if isVisible(x,y) then count = count + 1
	end for
end for
print "final answer (part A): " + count
```

I scrapped my usual read-each-line loop for a [`file.readLines`](https://miniscript.org/wiki/File.readLines), which reads the whole thing at once, returning a list of strings.  This included an extra blank line at the end, so I checked for and removed that, and then printed the width and height as a sanity check.

The real work here is done by the `isVisInDir` function, which takes the (x,y) coordinates of a spot in the grid, and a (dx,dy) direction to check in.  It uses a loop to repeatedly add those dx,dy values to the x,y values, so as to consider each tree in turn along that line.  If find a tree (digit) equal to or greater than the one at x,y, we return false (our starting tree is not visible from this direction).  If we go out of bounds, then we return true.

With that in hand, the `isVisible` function simply checks all four directions.  Finally, we have a simple counting loop that calls this for each point in the grid.  (Instead of an `if` statement, I could have just done `count = count + isVisible(x,y)`, since boolean values in MiniScript are just `0` and `1`.)

## Part B

In the second part of the challenge, the elves want to find the tree with the best view.  The "scene score" of a tree is defined as the product of how far you can see in each of the 4 directions.

To solve this, I copied my `isVisInDir` function and modified it into a `viewDist` function.  But the basic idea is the same: walk in direction (dx,dy) until we go out of bounds or hit a sufficiently large value.  But as we go, we count how many steps we took, representing the view distance in that direction.

Then, I copied `isVisible` to make a new `scenicScore` function, which multiplies the `viewDist` of each direction.  And finally, instead of a counting loop, I have a loop at the end that just iterates over all trees and keeps track of the maximum score.  The new code added is shown below.

```
viewDist = function(x, y, dx, dy)
	h = grid[y][x]
	d = 0
	while true
		x = x + dx
		y = y + dy
		if x < 0 or x >= width or y < 0 or y >= height then break
		t = grid[y][x]
		d = d + 1
		if t >= h then break
	end while
	return d
end function

scenicScore = function(x,y)
	return viewDist(x,y, -1,0) *
		viewDist(x,y, 1,0) *
		viewDist(x,y, 0,-1) *
		viewDist(x,y, 0,1)
end function

bestScore = 0
for x in range(0, width-1)
	print "x=" + x + "..."
	for y in range(0, height-1)
		score = scenicScore(x,y)
		if score > bestScore then bestScore = score
	end for
end for

print "final answer (part B): " + bestScore
```

It's a fair amount of code, but it was pretty quick to write; it took me 14 minutes overall, for a rank of 289 (a new personal best!).

Once again, my starter program did me no good; nor did I need any of the stuff I've been gathering in my [custom aoc module](https://github.com/JoeStrout/AoC-2022/blob/main/lib/aoc.ms), or even the standard [/sys/lib](https://github.com/JoeStrout/minimicro-sysdisk/tree/master/sys/lib) modules.  The solution was plain, unadorned [MiniScript](https://miniscript.org/). ❤️