Graph traversal nonsense should be the kind of stuff Dusa is great at, and indeed this seemed to go straightforwardly for me on a day that some folks got stumped on the Part 2. Most of my issues were that there wasn’t just one way to solve the problem, so I did a bit of unfocused exploration.
First step was to explode the input into charAt (pair X Y) is Ch facts. So here we’d have:
charAt (pair 0 0) is "7"charAt (pair 1 0) is "-"charAt (pair 2 0) is "F"  01234
0 7-F7-
1 .FJ|7
2 SJLL7
3 |F--J
4 LJ.LJ
With that in place, we list out the ways in which the 6 relevant characters imply connections in the x and y directions.
**connectX "L"  1. connectY "L" -1.
connectX "J" -1. connectY "J" -1.
connectX "F"  1. connectY "F"  1.
connectX "7" -1. connectY "7"  1.
connectY "|" -1. connectY "|"  1.
connectX "-" -1. connectX "-"  1.**
From this, we’ll generate an edge relation. This requires a bit of duplication — everything is described once for the x direction and once for the y direction.
Here’s the x direction version: there’s an edge if there’s an agreement that there is a connection in both the forwards and backwards directions.
**edge A B :-
    *# Check for forwards connection*
    charAt A is Ch, A == pair X1 Y,
    connectX Ch Delta, X2 == plus X1 Delta,
    *# Check for backwards connection*
    B == pair X2 Y, charAt B is Ch2,
    connectX Ch2 (minus 0 Delta).**
Once that’s in place we’re off to the races of using Dusa for graph algorithms. But where shall we start? The distinguished starting point is marked with an “S” character:
**start is A :- charAt A is "S".**
and so the first step we take will be to one of the two neighbors that have a connection to that character. (Again, this is the x-direction version and there’s a y-direction version too.)
**edge start (pair X Y) :-
    charAt (pair X Y) is Ch,
    connectX Ch Delta,
    start == pair (plus X Delta) Y.**
The first set of rules were naturally symmetric, and the connected-to-start rules are not. We could solve this with a scalpel, especially if we supported multiple conclusions so the rule above could say edge (pair X Y) start as well as edge start (pair X Y). But no matter, we can also solve it with a hammer and force the relation to be symmetric:
**edge A B :- edge B A.**
It’s helpful for both parts to for us to trace our way around the loop in one direction, and which direction doesn’t matter. But that’s Dusa’s whole thing: we can create an after relation that starts at the start and proceeds to an arbitrary edge connected to start, and henceforch all the way around the loop:
**after start is { A? } :- edge start A.
after B is C :-
     after A is B,
     edge B C,
     C != A.**