You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.6 KiB
107 lines
3.6 KiB
module Task5
|
|
|
|
open System
|
|
|
|
type ChurchList<'a> = ('a -> 'b -> 'b) -> 'b -> 'b
|
|
|
|
let nil : ChurchList<'a> = fun _ z -> z
|
|
|
|
let cons (x: 'a) (xs: ChurchList<'a>) : ChurchList<'a> =
|
|
fun f z -> f x (xs f z)
|
|
|
|
let toList (churchList: ChurchList<'a>) : 'a list =
|
|
churchList (fun x acc -> x :: acc) []
|
|
|> List.rev
|
|
|
|
let ofList (lst: 'a list) : ChurchList<'a> =
|
|
List.foldBack cons lst nil
|
|
|
|
let countFrequencies (churchList: ChurchList<'a>) : ('a * int) list when 'a : equality =
|
|
let regularList = toList churchList
|
|
|
|
let rec countTailRec lst acc =
|
|
match lst with
|
|
| [] -> acc
|
|
| x :: xs ->
|
|
let rec updateCount freqList element =
|
|
match freqList with
|
|
| [] -> [(element, 1)]
|
|
| (key, count) :: rest ->
|
|
if key = element then
|
|
(key, count + 1) :: rest
|
|
else
|
|
(key, count) :: updateCount rest element
|
|
|
|
let newAcc = updateCount acc x
|
|
countTailRec xs newAcc
|
|
|
|
countTailRec regularList []
|
|
|
|
let findMaxFrequency (frequencies: ('a * int) list) : ('a * int) option =
|
|
let rec findMaxTailRec lst currentMax =
|
|
match lst with
|
|
| [] -> currentMax
|
|
| (element, count) :: rest ->
|
|
match currentMax with
|
|
| None -> findMaxTailRec rest (Some (element, count))
|
|
| Some (_, maxCount) ->
|
|
if count > maxCount then
|
|
findMaxTailRec rest (Some (element, count))
|
|
else
|
|
findMaxTailRec rest currentMax
|
|
|
|
findMaxTailRec frequencies None
|
|
|
|
let findMostFrequent (churchList: ChurchList<'a>) : 'a option when 'a : equality =
|
|
let frequencies = countFrequencies churchList
|
|
match findMaxFrequency frequencies with
|
|
| Some (element, _) -> Some element
|
|
| None -> None
|
|
|
|
let getMostFrequentCount (churchList: ChurchList<'a>) : int when 'a : equality =
|
|
let frequencies = countFrequencies churchList
|
|
match findMaxFrequency frequencies with
|
|
| Some (_, count) -> count
|
|
| None -> 0
|
|
|
|
[<EntryPoint>]
|
|
let main argv =
|
|
let testList1 = ofList [1; 2; 3; 2; 4; 2; 5; 3; 2]
|
|
let frequencies1 = countFrequencies testList1
|
|
frequencies1 |> List.iter (fun (elem, count) -> printfn "%A: %d" elem count)
|
|
|
|
match findMostFrequent testList1 with
|
|
| Some element ->
|
|
let count = getMostFrequentCount testList1
|
|
printfn "Most frequent: %A (%d times)" element count
|
|
| None -> printfn "Empty list"
|
|
|
|
let testList2 = ofList ["apple"; "banana"; "apple"; "cherry"; "banana"; "apple"]
|
|
match findMostFrequent testList2 with
|
|
| Some element ->
|
|
let count = getMostFrequentCount testList2
|
|
printfn "Most frequent string: %A (%d times)" element count
|
|
| None -> printfn "Empty list"
|
|
|
|
let testList3 = ofList [5; 5; 5; 5]
|
|
match findMostFrequent testList3 with
|
|
| Some element ->
|
|
let count = getMostFrequentCount testList3
|
|
printfn "All same: %A (%d times)" element count
|
|
| None -> printfn "Empty list"
|
|
|
|
let testList4 = ofList [1; 2; 3; 4; 5]
|
|
match findMostFrequent testList4 with
|
|
| Some element ->
|
|
let count = getMostFrequentCount testList4
|
|
printfn "All unique, first: %A (%d times)" element count
|
|
| None -> printfn "Empty list"
|
|
|
|
let testList5 = nil
|
|
match findMostFrequent testList5 with
|
|
| Some element ->
|
|
let count = getMostFrequentCount testList5
|
|
printfn "Should not happen: %A (%d times)" element count
|
|
| None -> printfn "Empty list handled correctly"
|
|
|
|
0 |