I have made function that takes a list and a list of lists and returns a new list of lists.
let rec calculator list SS =
match (List.item(0) SS) with
|[] -> []
|_ -> match (validate list (List.item(0) SS)) with
|(validate theCode list) -> List.append [(List.item(0) SS)] (calculator list (SS.[1..]))
|_ -> (calculator list (SS.[1..]))
validate is a function that returns two tupled ints. example (1,1)
list is a list of four ints
SS is a list of lists with four ints
theCode is a list of four ints
i get the error "The pattern discriminator 'validate' is not defined."
Perhaps this is a silly question but none the less i don't know the answer to it.
Is it not allowed to use a function as an argument in a match expression. Or is it something entirely different going on here?
to the best of my knowledge the two validate functions will return two tupled ints and therefore should be able to match upon that.
If your question is how to get this to compile then you only need a small change – a function call is not itself a pattern, so you need to bind to a value and use a when guard:
let rec calculator list SS =
match (List.item(0) SS) with
| [] -> []
| _ ->
match (validate list (List.item(0) SS)) with
// vvvvvvvvvv
| x when x = (validate theCode list) ->
List.append [(List.item(0) SS)] (calculator list (SS.[1..]))
| _ -> (calculator list (SS.[1..]))
However, if your question is indeed "what is the preferred method", then while that's too subjective for this site (IMO), I'll submit this as an option that I consider ideally readable for this logic:
let rec calculator list (h::t) =
if List.isEmpty h then h
elif validate list h = validate theCode list then h::(calculator list t)
else calculator list t
(This assumes that SS is an F# list and not a System.Collections.Generic.List.)
This is not actually an answer to the question of how to implement the when guard, since #ildjarn answered that for you.
I think you'd actually be better served by a library function. What you're trying to do appears to be to filter out elements which don't pass validation, but also to stop on the first empty element. If you can guarantee that you definitely want to loop through every element of SS, you could simply do
let calculator list = List.filter (fun s -> validate list s = validate theCode list)
If it's you must stop at the empty element, you could define a function that cuts the list at the first empty element, something like
let upToElement element list =
let rec loop acc = function
| [] -> List.rev acc
| h :: t when h = element -> List.rev acc
| h :: t -> loop (h :: acc) t
loop [] list
then you can do
let calculator list =
upToElement [] >> List.filter (fun s -> validate list s = validate theCode list)
Related
While learning Ocaml, I saw a code that removing duplicate elements from the list.
let rec remove =
function
| [] -> []
| x::[] -> x::[]
| x::y::tl ->
if x=y then remove (y::tl)
else x::remove (y::tl)
However, what I found is that this code only removes successive duplicates so if I try some duplicates that takes a place separately such as [6;6;8;9;4;2;5;1;5;2;3], the code deals with 6 which has successive duplicate but not with 2 or 5 which are separated.
How can I completely make the list have only unique elements?
like remove [6;6;8;9;4;2;5;1;5;2;3] -> [6;8;9;4;2;5;1;3].
p.s. I managed to delete duplicate which comes first but cannot have figured out how to delete duplicates that come later.
From your description, you coded the quadratic version of the algorithm.
There is also a O(n log n) version, using a set of already seen values:
let remove_duplicates (type a) (l: a list) =
let module S = Set.Make(struct type t = a let compare = compare end) in
let rec remove acc seen_set = function
| [] -> List.rev acc
| a :: rest when S.mem a seen_set -> remove acc seen_set rest
| a :: rest -> remove (a::acc) (S.add a seen_set) rest in
remove [] S.empty l
(the code above uses the polymorphic compare, you may want to provide a compare function argument in real code)
This question is pretty old but here is a solution that doesn't use sets, in case that's useful :
let rec remove_duplicates l =
let rec contains l n =
match l with
| [] -> false
| h :: t ->
h = n || contains t n
in
match l with
| [] -> []
| h :: t ->
let acc = remove_duplicates t in
if contains acc h then acc else h :: acc
;;
I finally figured out.
Without sorting, I made an element check and element remove functions, so I can check if the tail of the list has a duplicate of head and decide to append head and tail after deleting the duplicates in the tail. Making the main function as recursive it finally removes all duplicates without changing orders(and also preserves the first coming duplicate.)
Thanks you, glennsl.
I have a list of tuples with three different elements like so:
[(a0:string, b0:string, c0:int); (a1, b1, c1); (and so on...)].
I need to make a function that takes this list and a "name" in the form of a and gives a list of all the bs where the name matches the a in the tuple. But I'm not sure how to iterate and match everything.
input: function name tuplelist
output: [b0 if a0 = name; b1 if a1 = name; b2 if a2 = name]
I also cannot use libraries!!!
When writing code in a functional style you will often use recursion, if not explicitly then implicitly since most list/array/sequence functions all use recursion under the hood.
In F#, you need to explicitly state that a function is recursive, so the function you create will use the let rec syntax in its definition. Given your requirements, your function will probably look like this:
let rec myFilter (name: string) (input: (string * string * int) list) =
...
For this class of problems, where you iterate over a list recursively, you usually use pattern matching to check if you are at the end of a list, and if so, return an empty list.
let rec myFilter (name: string) (input: (string * string * int) list) =
match input with
| [] -> []
...
Now you need to write a pattern match that checks the first item in the tuple against the supplied name. You can use pattern matching on the head of the list, and F#'s when syntax to deconstruct the head of the list for comparison
let rec myFilter (name: string) (input: (string * string * int) list) =
match input with
| [] -> []
| ((a, b, _) :: rest) when a = name -> b :: myFilter name rest
...
This second case matches when a matches the queried name. When it matches, it will return a new list of which b is the head of the list, and then it will take the rest of the list of tuples and call myFilter recursively. This is how you iterate through the list recursively.
We have one more case to check for: If we don't find a match, we want to keep stepping through the list without collecting b. This can be expressed by peeling off the head and recursively calling myFilter, sending only the rest of the tuples.
let rec myFilter (name: string) (input: (string * string * int) list) =
match input with
| [] -> []
| ((a, b, _) :: rest) when a = name -> b :: myFilter name rest
| (_ :: rest) -> myFilter name rest
Calling myFilter "a" [("a","x",3);("b","y",4);("a","z",5)] then yields ["x"; "z"], as expected.
Powerful F# pattern matching and recursion along with type inference easily compensate for dropping libraries limitation.
You need to build a map function converting one list into another list, this is to be addressed with recursion, the mapping function applied to each element of the list may use pattern matching to disassemble tuple into components and perform the conversion.
Something like the following will do:
let filter name (tupleList:(string*string*int) list) =
let checkElement name = function | (a,b,c) -> if a = name then Some b else None
let rec mapList name inputList outputList =
match inputList with
| [] -> outputList
| h::t -> let filter = checkElement name h
mapList name t (if filter = None then outputList else (outputList # [filter.Value]))
mapList name tupleList []
Here checkElement is the mapping function that takes the name and a tuple (a,b,c) and returns an option value either Some b if a = name, or None if not.
Recursive function mapList on each step operates with the unprocessed part of inputList of tuples and outputList accumulating on each recursion step parts from matched elements only. On each recursion step it checks if the inputList is empty. If yes, then we are done and it's time to return the accumulated result, otherwise we split the head element off inputList and apply the mapping function to it, changing the accumulated list, if this is the case. Then we do the next recursion step on the tail of inputList and the accumulator.
This task requires you to write your own recursive list processing function. I was able to implement it by using two sub-functions.
While the answers by #GeneBelitski and #ChadGilbert are great for learning, they are not tail-recursive, so I'll add my own.
Sub-function aux takes an accumulator and the list to process, and matches against the shape of the list. If it is empty, it returns the result accumulated so far. If it is a 3-tuple with a tail, it compares the first element to name, and if they are equal, continues running itself prepending the second element to the results accumulated, and the tail of the original list, otherwise just the results accumulated so far, and the tail of the original list.
As this way of accumulating results inverts the order of the resulting list, we need to reverse it before returning it; this is what the sub-function rev does, and as you see, the code looks almost identical to aux, prepending elements to the results accumulated so far but without doing any comparing or processing.
let filter_b name lst =
let rec aux acc = function
| [] -> acc
| (a : string, b : string, c : int) :: tl ->
if a = name
then aux (b :: acc) tl
else aux acc tl
let rec rev acc = function
| [] -> acc
| hd :: tl -> rev (hd :: acc) tl
lst
|> aux [] // process list with aux function
|> rev [] // reverse resulting list
I am very new to F# and functional programming in general, and would like to recursively create a function that takes a list, and doubles all elements.
This is what I used to search for a spacific element, but im not sure how exactly I can change it to do what I need.
let rec returnN n theList =
match n, theList with
| 0, (head::_) -> head
| _, (_::theList') -> returnN (n - 1) theList'
| _, [] -> invalidArg "n" "n is larger then list length"
let list1 = [5; 10; 15; 20; 50; 25; 30]
printfn "%d" (returnN 3 list1 )
Is there a way for me to augment this to do what I need to?
I would like to take you through the thinking process.
Step 1. I need a recursive function that takes a list and doubles all the elements:
So, let's implement this in a naive way:
let rec doubleAll list =
match list with
| [] -> []
| hd :: tl -> hd * 2 :: doubleAll tl
Hopefully this logic is quite simple:
If we have an empty list, we return another empty list.
If we have a list with at least one element, we double the element and then prepend that to the result of calling the doubleAll function on the tail of the list.
Step 2. Actually, there are two things going on here:
I want a function that lets me apply another function to each element of a list.
In this case, I want that function to be "multiply by 2".
So, now we have two functions, let's do a simple implementation like this:
let rec map f list =
match list with
| [] -> []
| hd :: tl -> f hd :: map f tl
let doubleAll list = map (fun x -> x * 2) list
Step 3. Actually, the idea of map is such a common one that it's already built into the F# standard library, see List.map
So, all we need to do is this:
let doubleAll list = List.map (fun x -> x * 2) list
With a list of integers such as:
[1;2;3;4;5;6;7;8;9]
How can I create a list of list of ints from the above, with all new lists the same specified length?
For example, I need to go from:
[1;2;3;4;5;6;7;8;9] to [[1;2;3];[4;5;6];[7;8;9]]
with the number to split being 3?
Thanks for your time.
So what you actually want is a function of type
val split : int list -> int -> int list list
that takes a list of integers and a sub-list-size. How about one that is even more general?
val split : 'a list -> int -> 'a list list
Here comes the implementation:
let split xs size =
let (_, r, rs) =
(* fold over the list, keeping track of how many elements are still
missing in the current list (csize), the current list (ys) and
the result list (zss) *)
List.fold_left (fun (csize, ys, zss) elt ->
(* if target size is 0, add the current list to the target list and
start a new empty current list of target-size size *)
if csize = 0 then (size - 1, [elt], zss # [ys])
(* otherwise decrement the target size and append the current element
elt to the current list ys *)
else (csize - 1, ys # [elt], zss))
(* start the accumulator with target-size=size, an empty current list and
an empty target-list *)
(size, [], []) xs
in
(* add the "left-overs" to the back of the target-list *)
rs # [r]
Please let me know if you get extra points for this! ;)
The code you give is a way to remove a given number of elements from the front of a list. One way to proceed might be to leave this function as it is (maybe clean it up a little) and use an outer function to process the whole list. For this to work easily, your function might also want to return the remainder of the list (so the outer function can easily tell what still needs to be segmented).
It seems, though, that you want to solve the problem with a single function. If so, the main thing I see that's missing is an accumulator for the pieces you've already snipped off. And you also can't quit when you reach your count, you have to remember the piece you just snipped off, and then process the rest of the list the same way.
If I were solving this myself, I'd try to generalize the problem so that the recursive call could help out in all cases. Something that might work is to allow the first piece to be shorter than the rest. That way you can write it as a single function, with no accumulators
(just recursive calls).
I would probably do it this way:
let split lst n =
let rec parti n acc xs =
match xs with
| [] -> (List.rev acc, [])
| _::_ when n = 0 -> (List.rev acc, xs)
| x::xs -> parti (pred n) (x::acc) xs
in let rec concat acc = function
| [] -> List.rev acc
| xs -> let (part, rest) = parti n [] xs in concat (part::acc) rest
in concat [] lst
Note that we are being lenient if n doesn't divide List.length lst evenly.
Example:
split [1;2;3;4;5] 2 gives [[1;2];[3;4];[5]]
Final note: the code is very verbose because the OCaml standard lib is very bare bones :/ With a different lib I'm sure this could be made much more concise.
let rec split n xs =
let rec take k xs ys = match k, xs with
| 0, _ -> List.rev ys :: split n xs
| _, [] -> if ys = [] then [] else [ys]
| _, x::xs' -> take (k - 1) xs' (x::ys)
in take n xs []
I'm working with a list of lists in OCaml, and I'm trying to write a function that combines all of the lists that share the same head. This is what I have so far, and I make use of the List.hd built-in function, but not surprisingly, I'm getting the failure "hd" error:
let rec combineSameHead list nlist = match list with
| [] -> []#nlist
| h::t -> if List.hd h = List.hd (List.hd t)
then combineSameHead t nlist#uniq(h#(List.hd t))
else combineSameHead t nlist#h;;
So for example, if I have this list:
[[Sentence; Quiet]; [Sentence; Grunt]; [Sentence; Shout]]
I want to combine it into:
[[Sentence; Quiet; Grunt; Shout]]
The function uniq I wrote just removes all duplicates within a list. Please let me know how I would go about completing this. Thanks in advance!
For one thing, I generally avoid functions like List.hd, as pattern maching is usually clearer and less error-prone. In this case, your if can be replaced with guarded patterns (a when clause after the pattern). I think what is happening to cause your error is that your code fails when t is []; guarded patterns help avoid this by making the cases more explicit. So, you can do (x::xs)::(y::ys)::t when x = y as a clause in your match expression to check that the heads of the first two elements of the list are the same. It's not uncommon in OCaml to have several successive patterns which are identical except for guards.
Further things: you don't need []#nlist - it's the same as just writing nlist.
Also, it looks like your nlist#h and similar expressions are trying to concatenate lists before passing them to the recursive call; in OCaml, however, function application binds more tightly than any operator, so it actually appends the result of the recursive call to h.
I don't, off-hand, have a correct version of the function. But I would start by writing it with guarded patterns, and then see how far that gets you in working it out.
Your intended operation has a simple recursive description: recursively process the tail of your list, then perform an "insert" operation with the head which looks for a list that begins with the same head and, if found, inserts all elements but the head, and otherwise appends it at the end. You can then reverse the result to get your intended list of list.
In OCaml, this algorithm would look like this:
let process list =
let rec insert (head,tail) = function
| [] -> head :: tail
| h :: t ->
match h with
| hh :: tt when hh = head -> (hh :: (tail # t)) :: t
| _ -> h :: insert (head,tail) t
in
let rec aux = function
| [] -> []
| [] :: t -> aux t
| (head :: tail) :: t -> insert (head,tail) (aux t)
in
List.rev (aux list)
Consider using a Map or a hash table to keep track of the heads and the elements found for each head. The nlist auxiliary list isn't very helpful if lists with the same heads aren't adjacent, as in this example:
# combineSameHead [["A"; "a0"; "a1"]; ["B"; "b0"]; ["A"; "a2"]]
- : list (list string) = [["A"; "a0"; "a1"; "a2"]; ["B"; "b0"]]
I probably would have done something along the lines of what antonakos suggested. It would totally avoid the O(n) cost of searching in a list. You may also find that using a StringSet.t StringMap.t be easier on further processing. Of course, readability is paramount, and I still find this hold under that criteria.
module OrderedString =
struct
type t = string
let compare = Pervasives.compare
end
module StringMap = Map.Make (OrderedString)
module StringSet = Set.Make (OrderedString)
let merge_same_heads lsts =
let add_single map = function
| hd::tl when StringMap.mem hd map ->
let set = StringMap.find hd map in
let set = List.fold_right StringSet.add tl set in
StringMap.add hd set map
| hd::tl ->
let set = List.fold_right StringSet.add tl StringSet.empty in
StringMap.add hd set map
| [] ->
map
in
let map = List.fold_left add_single StringMap.empty lsts in
StringMap.fold (fun k v acc-> (k::(StringSet.elements v))::acc) map []
You can do a lot just using the standard library:
(* compares the head of a list to a supplied value. Used to partition a lists of lists *)
let partPred x = function h::_ -> h = x
| _ -> false
let rec combineHeads = function [] -> []
| []::t -> combineHeads t (* skip empty lists *)
| (hh::_ as h)::t -> let r, l = List.partition (partPred hh) t in (* split into lists with the same head as the first, and lists with different heads *)
(List.fold_left (fun x y -> x # (List.tl y)) h r)::(combineHeads l) (* combine all the lists with the same head, then recurse on the remaining lists *)
combineHeads [[1;2;3];[1;4;5;];[2;3;4];[1];[1;5;7];[2;5];[3;4;6]];;
- : int list list = [[1; 2; 3; 4; 5; 5; 7]; [2; 3; 4; 5]; [3; 4; 6]]
This won't be fast (partition, fold_left and concat are all O(n)) however.