Bash Fib Frog
fib_frog() {
local -n _arr="$1"
local _size=${#_arr[@]}
local -a _fib=(0 1)
local _i=1
while (( _fib[_i] <= _size )); do
((_i++))
_fib[_i]=$(( _fib[_i-1] + _fib[_i-2] ))
done
local -a _q_idx=(-1) _q_jmp=(0)
local _head=0
local -a _steps
for ((_i = 0; _i < _size; _i++)); do _steps[_i]=0; done
while (( _head < ${#_q_idx[@]} )); do
local _cidx=${_q_idx[_head]} _cjmp=${_q_jmp[_head]}
((_head++))
local _fidx
for ((_fidx = ${#_fib[@]} - 1; _fidx >= 2; _fidx--)); do
local _idx=$(( _cidx + _fib[_fidx] ))
if (( _idx == _size )); then
echo $(( _cjmp + 1 ))
return
fi
if (( _idx > _size )) || (( ${_steps[_idx]:-0} )) || (( _arr[_idx] == 0 )); then
continue
fi
if (( _arr[_idx] == 1 )); then
_steps[_idx]=1
_q_idx+=("$_idx")
_q_jmp+=($(( _cjmp + 1 )))
fi
done
done
echo -1
}
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.
C++ Fib Frog
#include <queue>
#include <vector>
int fibFrog(const std::vector<int>& a)
{
int size = static_cast<int>(a.size());
std::vector<int> fib{0, 1};
for (int i = 1; fib[i] <= size;) {
++i;
fib.push_back(fib[i - 1] + fib[i - 2]);
}
struct Path {
int idx;
int jmp;
};
std::queue<Path> paths;
paths.push({-1, 0});
std::vector<bool> steps(size, false);
while (!paths.empty()) {
Path path = paths.front();
paths.pop();
for (int i = static_cast<int>(fib.size()) - 1; i >= 2; --i) {
int idx = path.idx + fib[i];
if (idx == size) {
return path.jmp + 1;
}
if (idx > size || steps[idx] || a[idx] == 0) {
continue;
}
if (a[idx] == 1) {
steps[idx] = true;
paths.push({idx, path.jmp + 1});
}
}
}
return -1;
}
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.
C# Fib Frog
static int FibFrog(int[] a)
{
var size = a.Length;
var fib = new List<int> { 0, 1 };
for (int i = 1; fib[i] <= size;)
{
i++;
fib.Add(fib[i - 1] + fib[i - 2]);
}
var queue = new Queue<(int Idx, int Jmp)>();
queue.Enqueue((-1, 0));
var visited = new bool[size];
while (queue.Count > 0)
{
var (idx0, jmp) = queue.Dequeue();
for (int i = fib.Count - 1; i >= 2; i--)
{
var idx = idx0 + fib[i];
if (idx == size)
{
return jmp + 1;
}
if (idx > size || visited[idx] || a[idx] == 0)
{
continue;
}
if (a[idx] == 1)
{
visited[idx] = true;
queue.Enqueue((idx, jmp + 1));
}
}
}
return -1;
}
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.
Elixir Fib Frog
defmodule FibFrog do
def fib_frog(a) do
size = length(a)
jumps = size |> build_fib([1, 0]) |> Enum.reverse()
a_map = a |> Enum.with_index() |> Map.new(fn {v, i} -> {i, v} end)
bfs([{-1, 0}], MapSet.new(), jumps, a_map, size)
end
defp build_fib(size, [last | _] = acc) when last > size do
acc |> Enum.reverse() |> Enum.drop(2)
end
defp build_fib(size, [a, b | _] = acc), do: build_fib(size, [a + b | acc])
defp bfs([], _visited, _jumps, _a_map, _size), do: -1
defp bfs([{idx, jmp} | rest], visited, jumps, a_map, size) do
case try_jumps(jumps, idx, jmp, size, a_map, visited) do
{:found, result} -> result
{:continue, new_paths, visited} -> bfs(rest ++ new_paths, visited, jumps, a_map, size)
end
end
defp try_jumps(jumps, idx, jmp, size, a_map, visited) do
Enum.reduce_while(jumps, {:continue, [], visited}, fn f, {:continue, paths, visited} ->
next_idx = idx + f
cond do
next_idx == size ->
{:halt, {:found, jmp + 1}}
next_idx > size or MapSet.member?(visited, next_idx) or Map.get(a_map, next_idx) == 0 ->
{:cont, {:continue, paths, visited}}
true ->
{:cont, {:continue, paths ++ [{next_idx, jmp + 1}], MapSet.put(visited, next_idx)}}
end
end)
end
end
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.
Erlang Fib Frog
-module(fib_frog).
-export([fib_frog/1]).
fib_frog(A) ->
Size = length(A),
Arr = array:from_list(A),
Fibs = gen_fibs(Size),
bfs([-1], sets:from_list([-1]), Fibs, Size, Arr, 0).
gen_fibs(Size) ->
gen_fibs(0, 1, Size, []).
gen_fibs(_A, B, Size, Acc) when B > Size ->
lists:reverse(Acc);
gen_fibs(A, B, Size, Acc) ->
gen_fibs(B, A + B, Size, [B | Acc]).
bfs(Frontier, Visited, Fibs, Size, Arr, Level) ->
Hit = lists:any(fun(Idx) ->
lists:any(fun(F) -> Idx + F =:= Size end, Fibs)
end, Frontier),
case Hit of
true -> Level + 1;
false ->
NextCandidates = lists:usort([Idx + F || Idx <- Frontier, F <- Fibs,
Idx + F >= 0, Idx + F < Size,
array:get(Idx + F, Arr) =:= 1,
not sets:is_element(Idx + F, Visited)]),
case NextCandidates of
[] -> -1;
_ ->
Visited1 = sets:union(Visited, sets:from_list(NextCandidates)),
bfs(NextCandidates, Visited1, Fibs, Size, Arr, Level + 1)
end
end.
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.
Go Fib Frog
func fibFrog(a []int) int {
size := len(a)
fib := []int{0, 1}
for i := 1; fib[i] <= size; {
i++
fib = append(fib, fib[i-1]+fib[i-2])
}
type path struct {
idx int
jmp int
}
paths := []path{{idx: -1, jmp: 0}}
steps := make([]bool, size)
for len(paths) > 0 {
cur := paths[0]
paths = paths[1:]
for i := len(fib) - 1; i >= 2; i-- {
idx := cur.idx + fib[i]
if idx == size {
return cur.jmp + 1
}
if idx > size || steps[idx] || a[idx] == 0 {
continue
}
if a[idx] == 1 {
steps[idx] = true
paths = append(paths, path{idx: idx, jmp: cur.jmp + 1})
}
}
}
return -1
}
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.
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.
Java Fib Frog
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
public class Solution {
public static int fibFrog(int[] a) {
int size = a.length;
List<Integer> fib = new ArrayList<>(List.of(0, 1));
for (int i = 1; fib.get(i) <= size; ) {
i++;
fib.add(fib.get(i - 1) + fib.get(i - 2));
}
Deque<int[]> paths = new ArrayDeque<>();
paths.add(new int[]{-1, 0}); // {idx, jmp}
boolean[] steps = new boolean[size];
while (!paths.isEmpty()) {
int[] path = paths.poll();
int curIdx = path[0];
int jmp = path[1];
for (int i = fib.size() - 1; i >= 2; i--) {
int idx = curIdx + fib.get(i);
if (idx == size) {
return jmp + 1;
}
if (idx > size || steps[idx] || a[idx] == 0) {
continue;
}
if (a[idx] == 1) {
steps[idx] = true;
paths.add(new int[]{idx, jmp + 1});
}
}
}
return -1;
}
}
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.
Lisp Fib Frog
(defun fib-frog (a)
(let* ((vec (coerce a 'vector))
(size (length vec))
(fib (make-array 2 :initial-contents '(0 1) :adjustable t :fill-pointer 2)))
(let ((i 1))
(loop while (<= (aref fib i) size)
do (progn
(incf i)
(vector-push-extend (+ (aref fib (1- i)) (aref fib (- i 2))) fib))))
(let ((paths (list (list :idx -1 :jmp 0)))
(steps (make-array size :initial-element nil)))
(loop while paths
do (let ((path (pop paths)))
(loop for i from (1- (length fib)) downto 2
do (let ((idx (+ (getf path :idx) (aref fib i))))
(cond
((= idx size) (return-from fib-frog (1+ (getf path :jmp))))
((or (> idx size)
(aref steps idx)
(zerop (aref vec idx)))
nil)
((= (aref vec idx) 1)
(setf (aref steps idx) t)
(setf paths (append paths (list (list :idx idx :jmp (1+ (getf path :jmp))))))))))))
-1)))
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.
PHP Fib Frog
function fibFrog(array $a): int
{
$size = count($a);
$fib = [0, 1];
for ($i = 1; $fib[$i] <= $size;) {
$i++;
$fib[$i] = $fib[$i - 1] + $fib[$i - 2];
}
$paths = [
[
'idx' => -1,
'jmp' => 0
]
];
$steps = array_fill(0, $size, false);
while (count($paths) > 0) {
$path = array_shift($paths);
for ($i = count($fib) - 1; $i >= 2; $i--) {
$idx = $path['idx'] + $fib[$i];
if ($idx === $size) {
return $path['jmp'] + 1;
}
if ($idx > $size
|| $steps[$idx]
|| $a[$idx] === 0
) {
continue;
}
if ($a[$idx] === 1) {
$steps[$idx] = true;
$paths[] = [
'idx' => $idx,
'jmp' => $path['jmp'] + 1
];
}
}
}
return -1;
}
This precomputes Fibonacci jumps, then uses a breadth-first search to find the shortest valid path across the river.