type match' = string (* home team *) * int (* goal difference *) * string (* away team *) let matches = [ ("foo", 1, "car"); ("foo", 0, "bar"); ("foo", 1, "far"); ("car", 1, "bar"); ("foo", ~-1, "bar"); ("tar", 1, "fir"); ("bar", 1, "qux"); ("jor", ~-1, "far"); ("xir", 1, "kar"); ("car", ~-1, "qux"); ("far", 1, "qux"); ("car", 1, "foo"); ] let way a b = let rec aux (at : string) (visited : string list) (accum : match' list) = if at = b then [ List.rev accum ] else let matches = matches |> List.filter (function _, score, _ -> score <> 0) in let h = matches |> List.filter (function home, score, away -> score > 0 && home = at && not (List.exists (( = ) away) visited)) |> List.map (function (_, _, away) as x -> aux away (at :: visited) (x :: accum)) |> List.concat in let a = matches |> List.filter (function home, score, away -> score < 0 && away = at && not (List.exists (( = ) home) visited)) |> List.map (function (home, _, _) as x -> aux home (at :: visited) (x :: accum)) |> List.concat in a @ h in aux a [] []