I like f # puzzles, so I hit that one. I hope you will like it.
let orgList = [(2, 1); (3, 2); (4, 2); (5, 3); (6, 4); (7, 3)] let orgMap = orgList |> List.fold (fun acc item -> let key = snd item match Map.tryFind key acc with | Some(value) -> let map' = Map.remove key acc Map.add(key) (item::value) map' | None -> Map.add(key) (item::[]) acc ) Map.empty<int, (int*int) list> let findReports supervisor = let rec findReports' acc collection = match collection with | head::tail -> (findReports' (head::acc) tail) @ match Map.tryFind (fst head) orgMap with | Some(value) -> (findReports' [] value) | None -> [] | [] -> acc findReports' [] (Map.find supervisor orgMap) findReports 2 |> List.map fst |> List.distinct
returns
val it : int list = [3; 4; 5; 7; 6]
findReports 2 returns
val it : (int * int) list = [(3, 2); (4, 2); (5, 3); (7, 3); (6, 4)]
I will break it to clarify.
let orgList = [ (1, 2); (1, 3); (1, 4); (2, 5); (3, 6); (4, 5); (5, 6); (5, 7) ]
We take your list of tuples and create a functional boss map in the list ((report, boss)). This may be known as an adjacency list, which is used to move graphs.
let orgMap = orgList |> List.fold (fun acc item -> let key = snd item match Map.tryFind key acc with
If there is a list of reports under the boss, add to this list.
| Some(reports) -> let map' = Map.remove key acc Map.add(key) (item::reports) map'
Otherwise, add to the empty list and paste into the dictionary.
| None -> Map.add(key) (item::[]) acc
Start with a blank card as a battery.
) Map.empty<int, (int*int) list>
Count items to find all reports.
let findReports supervisor = let rec findReports' acc collection = match collection with
If there is an item, add it to the battery. This is a BFS. If you switch the expression before and after the concatenation operator (@), it will become DFS.
| head::tail -> (findReports' (head::acc) tail)
Combine the current list with a recursive list of reports in reports.
@ match Map.tryFind (fst head) orgMap with | Some(value) -> (findReports' [] value) | None -> []
If at the end of the list, return the list.
| [] -> acc
Run the recursive function.
findReports' [] (Map.find supervisor orgMap)
Run the function.
findReports 7
Return only reports
|> List.map fst
Do not report twice.
|> List.distinct