f# function to count number of digraphs in a string - f#

Im getting an error with this function. Im new to f# so I don't fully know what the code is doing, I tried duplicating a function that only takes one parameter to find vowels in a string.
let rec countDigraph c1 c2 L =
match L with
| [] -> 0
| hd::tl when hd = c1 -> 1 + count c1 tl
| hd::tl when tl = c2 -> 1 + count c2 tl
| _::tl ->0 + countDigraph c1 c2 tl
gets called later in the code:
let printCountDigraph digraph L =
let c1 = List.head digraph
let c2 = List.head digraph
printfn "%A,%A: %A" c1 c2 (countDigraph c1 c2 L)
let digraphs = [['a';'i']; ['c';'h']; ['e';'a']; ['i';'e']; ['o';'u']; ['p';'h']; ['s';'h']; ['t';'h']; ['w';'h'];]
List.iter (fun digraph -> printCountDigraph digraph L) digraphs

In countDigraph, you need to check that the first two characters of the list match the digraph. You seem to be trying to do this by first checking the first one (in the first case) and then the second one (in the second case), but this is not how pattern matching works.
The easiest option is to have a single clause that uses the pattern l1::l2::tl to extract the first two letters, followed by the rest of the list. You need to think whether e.g. eai counts as two digraphs or just one. If two, you need to recursively call countDigraph on c2::tl as below - if just one, you would recursively call countDigraph on just tl.
let rec countDigraph c1 c2 L =
match L with
| [] -> 0
| l1::l2::tl when l1=c1 && l2=c2 -> 1 + countDigraph c1 c2 (c2::tl)
| _::tl ->0 + countDigraph c1 c2 tl
The rest of the code gets much easier if you represent digraphs as a list of pairs, rather than a list of two-element lists:
let printCountDigraph (c1, c2) L =
printfn "%A,%A: %A" c1 c2 (countDigraph c1 c2 L)
let digraphs = [('a','i'); ('c','h'); ('e','a'); ('i','e');
('o','u'); ('p','h'); ('s','h'); ('t','h'); ('w','h')]
let L = List.ofSeq "chai"
List.iter (fun digraph -> printCountDigraph digraph L) digraphs

Related

recursive tuples in F# [duplicate]

Directly using recursion, write a function truesAndLength : bool list -> int * int that
returns both the length of the list (in the first component of the pair), and the number of
elements of the list that are true (in the second component). Your function must only iterate
over the elements of the list once. (Do not use any of the functions from the List module.)
this is my code so far:
let rec length bs =
match bs with
| [] -> 0
| b::bs -> 1 + length bs
let rec trues bs =
match bs with
| [] -> 0
| b::bs -> if b = true then 1 + trues bs else trues bs
let truesandlength bs =
let l = length bs
let t = trues bs
(l, t)
truesandlength [true; true; false]
This works by im iterating through the list 2 times, i can't figure out how to iterate only 1. Any tips?
Based on your comments, here's how I suggest you think about the b::bs case:
Call truesAndLengths recursively on the tail of the list. This gives you tTail (the # of trues) and lTail (the length) of the tail.
Compute t and l for the full list based on the value of b. (E.g. l is one more than lTail.)
Return t, l.
The key is to call truesAndLengths recursively in only one place in your code, passing it the tail of the list.
let rec truesAndLength bs =
let sum a b = (fst a + fst b, snd a + snd b)
match bs with
| [] -> 0, 0
| head::tail ->
if head then sum (1,1) (truesAndLength tail) else sum (1, 0) (truesAndLength tail)

trues and length of bool list f#

Directly using recursion, write a function truesAndLength : bool list -> int * int that
returns both the length of the list (in the first component of the pair), and the number of
elements of the list that are true (in the second component). Your function must only iterate
over the elements of the list once. (Do not use any of the functions from the List module.)
this is my code so far:
let rec length bs =
match bs with
| [] -> 0
| b::bs -> 1 + length bs
let rec trues bs =
match bs with
| [] -> 0
| b::bs -> if b = true then 1 + trues bs else trues bs
let truesandlength bs =
let l = length bs
let t = trues bs
(l, t)
truesandlength [true; true; false]
This works by im iterating through the list 2 times, i can't figure out how to iterate only 1. Any tips?
Based on your comments, here's how I suggest you think about the b::bs case:
Call truesAndLengths recursively on the tail of the list. This gives you tTail (the # of trues) and lTail (the length) of the tail.
Compute t and l for the full list based on the value of b. (E.g. l is one more than lTail.)
Return t, l.
The key is to call truesAndLengths recursively in only one place in your code, passing it the tail of the list.
let rec truesAndLength bs =
let sum a b = (fst a + fst b, snd a + snd b)
match bs with
| [] -> 0, 0
| head::tail ->
if head then sum (1,1) (truesAndLength tail) else sum (1, 0) (truesAndLength tail)

Tail recursive addition of Peano numbers in F# using accumulators

At Uni we were given a challenge of creating a tail recursive addition of Peano numbers using an accumulator. We aren't allowed to use any library function or other functions that we have created, but we are allowed to 'hide' the accumulator in an auxiliary function
Here's the type
type Peano =
| O
| S of Peano
I'm stuck at how to execute the accumulator as it has no operation on the type defined, i.e. the following is not possible
let tailAdd p1 p2 =
let rec aux p1 p2 acc =
match p1, p2 with
| O, _ -> acc
| S v, b -> aux v b (acc + v)
aux p1 p2 O
Help xD
I don't want to give away the answer, since this is a homework problem, but I'll give you a hint: In the case where p1 matches with S v, you know that v = p1 - 1. Therefore, p1 + p2 = v + (p2 + 1). So how do you write p2 + 1 in Peano numbers?
Figured it out
let tailAdd p1 p2 =
let rec aux p1 p2 acc =
match p1, p2 with
| O, O -> acc
| a, S v -> aux v a (S (acc))
| S v, b -> aux v b (S (acc))
aux p1 p2 O

F# elegance needed for Master-Detail scenario

The master-detail scenario. Been around forever. OK, if not forever, at least I was doing master-detail with FORTRAN on punch cards in the 70's. It's still around - plenty of master-detail questions here on STO.
I looked for a good way to do a master-detail recognizer in F#, didn't find it. Apologies if I missed it, and if so, can someone just reply with the sto thread or url? thanks
Here's my F#-newbie take on doing a master-detail recognizer in F#. That is: Reducing a raw/flat list of master-detail strings to a list of F#-records, where the master-strings are paired with their detail string-list.
Not looking for code golf here folks. Elegance. I had hoped to end up with something elegant, but the below is just a straight-forward recursive list walk. My F#-newbie brain failed to see how to make good use here of folds, comprehensions, fold-backs, maps, active patterns, computation expressions, etc.
Let's keep it to what can be done in F#. If there is a pre-built flat-file master-detail XML-data loader in .Net that makes master-detail .txt files into .Net XML in a one-line .Net call, that's quite interesting because it can be used in F#.
As someone with a long imperative programming history, I was trying to stick to immutable F# for practice. But if dipping into imperative or mutable code is really the best way for this in F#, please explain away. The output could be a list of tuples, a sequence of records, an array of tuples, etc.
Any comments/feedback.... thanks
let testInput =
["master Homer" ; "Doh.."; "Doh!!" ;
"master Has none" ;
"master JoyJoyJoy"; "Yaa!" ; "Yaa!!!"; "Yaa!!!!!!"]
type md = {m: string; d: string list}
member x.addDetail newd = {m = x.m; d = x.d # [newd]}
static member noMaster = {m = "" ; d = []} // master records can never be null-strings, so "" works here
static member isMaster (L:string) = L.StartsWith("master ")
static member isDetail (L:string) = not (md.isMaster L) // There is no third kind of record - if not a master then it is a detail
let rec masterDetails flatList currentMaster =
if md.noMaster = currentMaster then
match flatList with
| [] -> [] // If no master and no more input: input list was empty and the empty list is the overall result
| h :: t -> if md.isMaster h then // If no master, then head becomes the first master of the run
masterDetails t {m = h; d = []}
else
failwith "Bad input: First record must be a master record"
else
match flatList with
| [] -> [currentMaster] // End of input; return current master as a one-entry-list
| h :: t -> if md.isMaster h then // Head will now replace the current master as the new master
[currentMaster] # masterDetails t {m = h; d = []}
else // Keep current master; and add detail record to current master's detail list
masterDetails t (currentMaster.addDetail h)
let testSolution = // Required: 1) Preserve order of the master sets. 2) Preserve sort order of details-within-masters.
[{m = "master Homer" ; d = ["Doh.."; "Doh!!" ]};
{m = "master Has none" ; d = [ ]};
{m = "master JoyJoyJoy"; d = ["Yaa!"; "Yaa!!!"; "Yaa!!!!!!"]} ]
let tryIt = masterDetails testInput md.noMaster
let testTry = (tryIt = testSolution)
This sounds like a job for takeDrop.
// split a list into a prefix of elements that all
// meet predicate 'p', and the suffix remainder
let takeDrop p l =
let rec loop acc l =
match l with
| h::t when p h -> loop (h::acc) t
| _ -> List.rev acc, l
loop [] l
let rec masterDetail input =
[match input with
| [] -> ()
| h::t ->
assert(md.isMaster h)
let det, rest = takeDrop (not << md.isMaster) t
yield { m = h; d = det }
yield! masterDetail rest]
Full test code below.
let testInput =
["master Homer" ; "Doh.."; "Doh!!" ;
"master Has none" ;
"master JoyJoyJoy"; "Yaa!" ; "Yaa!!!"; "Yaa!!!!!!"]
type md = {m: string; d: string list}
static member isMaster (s:string) = s.StartsWith("master ")
let testSolution = // Required: 1) Preserve order of the master sets.
// 2) Preserve sort order of details-within-masters.
[{m = "master Homer" ; d = ["Doh.."; "Doh!!" ]};
{m = "master Has none" ; d = [ ]};
{m = "master JoyJoyJoy"; d = ["Yaa!"; "Yaa!!!"; "Yaa!!!!!!"]} ]
// split a list into a prefix of elements that all
// meet predicate 'p', and the suffix remainder
let takeDrop p l =
let rec loop acc l =
match l with
| h::t when p h -> loop (h::acc) t
| _ -> List.rev acc, l
loop [] l
let rec masterDetail input =
[match input with
| [] -> ()
| h::t ->
assert(md.isMaster h)
let det, rest = takeDrop (not << md.isMaster) t
yield { m = h; d = det }
yield! masterDetail rest]
let briSol = masterDetail testInput
printfn "%A" (briSol = testSolution)
As far as I know, there is no built-in function that would automatically split a list in this fashion. In the real-world, you would probably use a different representation of the data in the first place, so you wouldn't need to solve this problem (when loading data from XML, you'd already have hierarchical structure and when grouping data using LINQ, you'd also get hierarchical data). However, your function may still be needed, for example when loading data from a text-file.
Here is a slightly simpler version that uses sequence expression to generate the outer collection (of master-details records). The inner collection is accumulated in a parameter in the usual way:
let rec groupMasterDetails l acc master = seq {
match l with
// No master found yet, if the first element isn't master, we throw
| x::xs when not (md.isMaster x) && master = None ->
failwith "The first element must be master"
// Starting a new group, yield the previous group
| x::xs when md.isMaster x ->
if master <> None then yield { m = master.Value; d = List.rev acc }
yield! groupMasterDetails xs [] (Some x)
// Continue the current group
| x:: xs ->
yield! groupMasterDetails xs (x::acc) master
// End of processing, yield the last group
| [] ->
if master <> None then yield { m = master.Value; d = List.rev acc } }
let masterDetails l = l [] None
Note that the elements are accumulated in the reversed order (as opposed to using [el]#rest and then reversed, because this is a lot more efficient - using # involves copying of the entire list, so it is a bad practice to use it often). This also means that the implementation doesn't need your addDetail member.
However, this is still relatively long piece of code - I'm interested to see if this can be implemented by composing standard F# functions (I didn't find any good way to do this).
Here's an example, building off of Brain's answer, that takes separation too far however it does show the power of functional programming.
let takeDrop p l =
let rec loop acc l =
match l with
| h::t when p h -> loop (h::acc) t
| _ -> List.rev acc, l
loop [] l
let rec listSplit spliter neo l =
[match l with
| [] -> ()
| h::t ->
let det, rest = spliter t
yield neo h det
yield! listSplit spliter neo rest]
let masterDetail =
listSplit
(takeDrop (not << md.isMaster))
(fun h det -> { m = h; d = det })

Avoiding code duplication in F#

I have two snippets of code that tries to convert a float list to a Vector3 or Vector2 list. The idea is to take 2/3 elements at a time from the list and combine them as a vector. The end result is a sequence of vectors.
let rec vec3Seq floatList =
seq {
match floatList with
| x::y::z::tail -> yield Vector3(x,y,z)
yield! vec3Seq tail
| [] -> ()
| _ -> failwith "float array not multiple of 3?"
}
let rec vec2Seq floatList =
seq {
match floatList with
| x::y::tail -> yield Vector2(x,y)
yield! vec2Seq tail
| [] -> ()
| _ -> failwith "float array not multiple of 2?"
}
The code looks very similiar and yet there seems to be no way to extract a common portion. Any ideas?
Here's one approach. I'm not sure how much simpler this really is, but it does abstract some of the repeated logic out.
let rec mkSeq (|P|_|) x =
seq {
match x with
| P(p,tail) ->
yield p
yield! mkSeq (|P|_|) tail
| [] -> ()
| _ -> failwith "List length mismatch" }
let vec3Seq =
mkSeq (function
| x::y::z::tail -> Some(Vector3(x,y,z), tail)
| _ -> None)
As Rex commented, if you want this only for two cases, then you probably won't have any problem if you leave the code as it is. However, if you want to extract a common pattern, then you can write a function that splits a list into sub-list of a specified length (2 or 3 or any other number). Once you do that, you'll only use map to turn each list of the specified length into Vector.
The function for splitting list isn't available in the F# library (as far as I can tell), so you'll have to implement it yourself. It can be done roughly like this:
let divideList n list =
// 'acc' - accumulates the resulting sub-lists (reversed order)
// 'tmp' - stores values of the current sub-list (reversed order)
// 'c' - the length of 'tmp' so far
// 'list' - the remaining elements to process
let rec divideListAux acc tmp c list =
match list with
| x::xs when c = n - 1 ->
// we're adding last element to 'tmp',
// so we reverse it and add it to accumulator
divideListAux ((List.rev (x::tmp))::acc) [] 0 xs
| x::xs ->
// add one more value to 'tmp'
divideListAux acc (x::tmp) (c+1) xs
| [] when c = 0 -> List.rev acc // no more elements and empty 'tmp'
| _ -> failwithf "not multiple of %d" n // non-empty 'tmp'
divideListAux [] [] 0 list
Now, you can use this function to implement your two conversions like this:
seq { for [x; y] in floatList |> divideList 2 -> Vector2(x,y) }
seq { for [x; y; z] in floatList |> divideList 3 -> Vector3(x,y,z) }
This will give a warning, because we're using an incomplete pattern that expects that the returned lists will be of length 2 or 3 respectively, but that's correct expectation, so the code will work fine. I'm also using a brief version of sequence expression the -> does the same thing as do yield, but it can be used only in simple cases like this one.
This is simular to kvb's solution but doesn't use a partial active pattern.
let rec listToSeq convert (list:list<_>) =
seq {
if not(List.isEmpty list) then
let list, vec = convert list
yield vec
yield! listToSeq convert list
}
let vec2Seq = listToSeq (function
| x::y::tail -> tail, Vector2(x,y)
| _ -> failwith "float array not multiple of 2?")
let vec3Seq = listToSeq (function
| x::y::z::tail -> tail, Vector3(x,y,z)
| _ -> failwith "float array not multiple of 3?")
Honestly, what you have is pretty much as good as it can get, although you might be able to make a little more compact using this:
// take 3 [1 .. 5] returns ([1; 2; 3], [4; 5])
let rec take count l =
match count, l with
| 0, xs -> [], xs
| n, x::xs -> let res, xs' = take (count - 1) xs in x::res, xs'
| n, [] -> failwith "Index out of range"
// split 3 [1 .. 6] returns [[1;2;3]; [4;5;6]]
let rec split count l =
seq { match take count l with
| xs, ys -> yield xs; if ys <> [] then yield! split count ys }
let vec3Seq l = split 3 l |> Seq.map (fun [x;y;z] -> Vector3(x, y, z))
let vec2Seq l = split 2 l |> Seq.map (fun [x;y] -> Vector2(x, y))
Now the process of breaking up your lists is moved into its own generic "take" and "split" functions, its much easier to map it to your desired type.

Resources