Haskell Fib Frog
import Data.Array (Array, listArray, (!))
import qualified Data.Sequence as Seq
import Data.Sequence (Seq, ViewL (..), viewl, (|>))
import qualified Data.Set as Set
fibFrog :: [Int] -> Int
fibFrog a = go (Seq.singleton (-1, 0)) (Set.singleton (-1))
where
n = length a
leaves = listArray (0, n - 1) a :: Array Int Int
-- distinct Fibonacci jump lengths, up to the first one exceeding n
jumps = takeWhile (<= n) fibJumps
where
fibJumps = 1 : 2 : zipWith (+) fibJumps (tail fibJumps)
go :: Seq (Int, Int) -> Set.Set Int -> Int
go queue visited = case viewl queue of
EmptyL -> -1
(pos, steps) :< rest
| any (\j -> pos + j == n) jumps -> steps + 1
| otherwise ->
let (queue', visited') = foldl (enqueue pos steps) (rest, visited) jumps
in go queue' visited'
enqueue pos steps (q, visited) j
| idx >= 0 && idx < n && leaves ! idx == 1 && not (Set.member idx visited) =
(q |> (idx, steps + 1), Set.insert idx visited)
| otherwise = (q, visited)
where
idx = pos + j
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.