Hello i resolved problem with ealier task.
Now if i have for example list = [ 2; 3; 2 ; 6 ] want to translate it like this [2;5;7;13].
I declared x as my first element and xs as my rest and used List.scan . Idea below
(fun x n -> x + n) 0
but this make something like this
val it : int list = [0; 2; 5; 7; 13]
How to rewrite it to make list looking like this [2;5;7;13] with using any starting parameter. When i delete 0 i get error message.
Another question how it's going to look like List.Fold i tried to write something similar but it can get only sum of this list ;( .
Here's how I would do this with a fold (with type annotations):
let orig = [2; 3; 2; 6]
let workingSum (origList:int list) : int list =
let foldFunc (listSoFar: int list) (item:int) : int list =
let nextValue =
match listSoFar with
| [] -> item
| head::_ -> head + item
nextValue::listSoFar
origList |> List.fold foldFunc [] |> List.rev
For help learning fold, here's how I would do this with a recursive function:
let workingSum' (origList: int list): int list =
let rec loop (listSoFar: int list) (origListRemaining:int list): int list =
match origListRemaining with
| [] -> listSoFar
| remainHead::remainTail ->
let nextValue =
match listSoFar with
| [] -> remainHead
| head::_ -> head + remainHead
loop (nextValue::listSoFar) remainTail
origList |> loop [] |> List.rev
Note that the signature of the inner loop function is really similar to the foldFunc of the previous example, with one major difference: instead of being passed in the next element, it's being passed in the remainder of the original list that hasn't been processed yet. I'm using a match expression to account for the two different possibilities of that remainder of the original list: either the list is empty (meaning we're done), or it's not (and we need to return a recursive call to the next step).
Related
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
I'm supposed to remove consecutive duplicates from an int list without using recursion and using only List.fold, map, filter, fold_left, fold_right.
I almost got it, but the problem with my code is that it checks if each element equals the 2nd element, and not the next element.
For example if let z = int list [3;1;4;5;5;1;1] my code will return [3;4;5] and not [3;1;4;5;1]. I'm not sure how to change it so filter uses a dynamically changing list parameter and not simply the original one (so it doesn't compare each element to the second element (1 in this case) each time):
let dupe (ls: int list) : int list =
List.filter (fun x -> if List.length ls = 0 then true else if x = List.hd (List.tl xs) then false else true) ls
The type of List.filter is this:
# List.filter;;
- : ('a -> bool) -> 'a list -> 'a list = <fun>
Notably, the filter function can see only one element of the list at a time. You need to see two consecutive elements to decide what to do, so I'd say List.filter won't do the job.
You're going to have to use map or one of the folds, I'd say. You can figure out which one(s) will work, with similar reasoning.
(I assume this is the sort of reasoning the assignment is supposed to illustrate. So I'm going to leave it there.)
Without rec
let remove = function
[] -> []
| x::tl ->
let (_,lxRes)=
List.fold_left (
fun (xPrec,lxRes) xCour ->
if xPrec=xCour then
(xCour,lxRes)
else
(xCour,lxRes#[xCour])
) (x+1,[]) (x::tl)
in
lxRes
Test:
# remove [3;1;4;5;5;1;1];;
- : int list = [3; 1; 4; 5; 1]
# remove [1;1];;
- : int list = [1]
# remove [1;1;1;1;2;2;3;4;5;5];;
- : int list = [1; 2; 3; 4; 5]
With rec (just for information)
let rec remove =
function
| [] -> []
| x::[] -> x::[]
| x::y::tl ->
if x=y then remove (y::tl)
else x::remove (y::tl)
Using just List.fold_left can be a little bit more concise than the previous answer. Of course, this will build up the list in reverse order, so we need to reverse the result.
let remove lst =
List.(
lst
|> fold_left
(fun acc x ->
match acc with
| [] -> [x]
| hd::_ when x = hd -> acc
| _ -> x::acc)
[]
|> rev
)
Of course, if you're not allowed to use List.rev we can reimplement it easily using List.fold_left, List.cons and Fun.flip.
let rev lst =
List.fold_left (Fun.flip List.cons) [] lst
Studying for a midterm and was looking through some old exam questions. This one doesn't have a solution posted and is stumping me:
partition: int list -> int -> (int list * int list) divides its
first argument into two lists, one containing all elements less than
its second argument, and the other all the elements greater than or
equal to its second argument. partition [5;2;10;4] 4 = ([2],
[5;10;4])
oh, and i'm supposed to be able to find the solution without using an auxiliary function
here is as far as i've gotten:
let rec partition l n = match l with
| [] -> ([], []) (* must return this type *)
| x :: xs -> if x < n then (* append x to first list, continue recursing *)
else (* append x to second list, continue recursing *)
normally, I'd use an aux function with an extra parameter to store the pair of lists i'm building, but that can't be done here. i'm a bit stuck
You should use the let in construction to match the return value of the recursive call:
let rec partition l n = match l with
| [] -> ([], [])
| x :: xs -> let a, b = partition xs n in
if x < n then (x::a), b
else a, (x::b);;
I am using OCaml to write a function that takes a list of ints and an int element and returns a list of pairs where the first element of every pair is the int element and the second element of the pair is a member from the list. For example, let say I have the number 1 and the list [10; 20; 30] as inputs. I like the function to return [(1, 10); (1, 20); (1, 30)]. I wrote the following function:
let rec f (lst : int list) (elm : int) : (int*int) list =
match lst with
| [] -> failwith "empty list"
| [x] -> [(x, elm)];;
I am getting the following error:
Characters 59-120:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
_::_::_ val f : int list -> int -> (int * int) list = <fun>
What am I missing?
Here is your code
let rec f (lst : int list) (elm : int) : (int*int) list =
match lst with
| [] -> failwith "empty list"
| [x] -> [(x, elm)]
In your match, you listed two cases: [] and [x].
Your first case is [], you mean empty, no problem.
Your second case is [x], what did you want to mean? In OCaml, it means a list with only one element.
How about the cases where there are more than one element?
For any if else or match with, you should include all cases.
When you fix this problem, you will soon find you really missed something more there.
Here is the correct code:
let rec f e l =
match l with
| [] -> []
| x::[] -> [(e,x)]
| x::tl -> (e,x)::(f e tl)
Note
above code is not tail-recursive and you normally should consider about it, I will leave that to you.
you don't need ;; if you write your code in file and compile the file
You don't need to declare types in most cases and that is one of the best thing ocaml has.
Your patterns match lists of length 0 ([]) and of length 1 ([x]). The compiler is telling you that there are other lengths that a list might have, so your pattern is probably wrong (which is true).
I might note that it's not an error to get an empty list as an argument. Thinking this way will make it much harder to answer the problem. If you get an empty list, the correct answer is an empty list of pairs.
let rec f e = function
| [] -> []
| x::tl -> (e,x)::f e tl
Or
let f e = List.map (fun x -> (e,x))
Test
# f 1 [];;
- : (int * 'a) list = []
# f 1 [10;20;30];;
- : (int * int) list = [(1, 10); (1, 20); (1, 30)]
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.