let rec list_add l i =
match l with
[] -> [i]
| h::t -> h::(list_add t i)
list add for adding each pair of integers from two lists
(Type) list add : int list -> int list -> int list
(Description) list add [a; b; c; ...] [x; y; z; ...] returns [a + x; b + y; c + z; ...]. If one list is longer than the other, the remaining list of elements is appended to the result.
(Example) list add [1; 2] [3; 4; 5] returns [4; 6; 5].
let rec add l1 l2 = match l1 with
[] -> l2
|h::t -> (*you can do the rest*)
;;
Related
I tried to write my own solution for this exercise by iterating through a list with a empty complst list where all non duplicates are inserted into and then get returned.
I know it is a over complicated approach after looking up the solution but would still like to understand why the pattern matching does not work as intended:
let compress list =
let rec aux complst lst =
match lst with
| [] -> complst
| a :: (b :: c) -> if a = b then aux complst (b::c) else aux (a::complst) (b::c)
| x -> x
in aux [] list;;
val comp : 'a list -> 'a list = <fun>
Regardless of the input, the output is always a list with only the last element:
compress [1;1;2;2;3];;
- : int list = [3]
compress [1;2;3];;
- : int list = [3]
Pattern matching
Your pattern-matching matches against three patterns:
The empty list: []
The list with at least two elements: a :: (b :: c)
A catch-all, which must by process of elimination be a list with a single element.
Consider what happens when we evaluate your example:
compress [1; 1; 2; 2; 3]
aux [] [1; 1; 2; 2; 3]
aux [] [1; 2; 2; 3]
aux [1] [2; 2; 3]
aux [1] [2; 3]
aux [2; 1] [3]
[3]
Oops, as soon as it hit lst being [3] it just returned it.
Let's rewrite your function to handle that single element list by adding to complst.
let compress lst =
let rec aux complst lst =
match lst with
| [] -> complst
| [x] -> aux (x::complst) []
| a :: (b :: c) ->
if a = b then aux complst (b::c)
else aux (a::complst) (b::c)
in
aux [] list
Now:
compress [1; 1; 2; 2; 3]
aux [] [1; 1; 2; 2; 3]
aux [] [1; 2; 2; 3]
aux [1] [2; 2; 3]
aux [1] [2; 3]
aux [2; 1] [3]
aux [3; 2; 1] []
[3; 2; 1]
Clean up and reversing the resulting list
Of course, there are also ways to clean up your code a bit using a conditional guard and _ for values you don't need to bind names to. You probably also want to reverse your accumulator.
let compress lst =
let rec aux complst lst =
match lst with
| [] -> List.rev complst
| [x] -> aux (x::complst) []
| a :: (b :: _ as tl) when a = b -> aux complst tl
| a :: (_ :: _ as tl) -> aux (a::complst) tl
in
aux [] lst
Fold
When you see this pattern of iterating over a list one element at a time and accumulating a new value, you can usually map that pretty well to List.fold_left.
let compress lst =
List.(
fold_left
(fun i x ->
match i with
| (x'::_) when x = x' -> i
| _ -> x::i)
[] lst
|> rev
)
Because List.fold_left can only be aware of one element at a time on the list, the function we pass as its first argument can't be aware of the next element in the list. But it is aware of the accumulator or "init" value. In this case that's another list, and we can pattern match out that list.
If it's not empty and the first element is equal to the current element we're looking at, don't add it to the result list. Otherwise, do add it. This also handles the first element case where the accumulator is empty.
Kudos on creating a tail-recursive solution to this problem!
The problem with your code here is mainly the last part, which corresponds to when you have the last element in your list so here [3], and you return that list with this single element.
What you need to do instead is append it to complst like this :
let compress list =
let rec aux complst lst =
match lst with
| [] -> complst
| a :: (b :: c ) -> if a=b then aux complst (b::c) else aux (a::complst) (b::c)
| x::e -> x::complst
in aux [] list;;
val comp : 'a list -> 'a list = <fun>
Now you can check with the given example :
compress [1;1;2;2;3];;
- : int list = [3; 2; 1]
Hope it helps you understand your mistake better.
Note regarding comments:
you should keep the [] case, because although it can only happen in one scenario, it is still a valid input meaning it must be kept!.
I've been trying to add a list to a list of lists.
What I want :
l1 : [[]] / [] / Empty list
l2 : [1;2]
result : [[1;2]]
add [1;3] to result :
result : [[1; 2]; [1; 3]]
I've tried to play with the # and the :: operator for quite a while now, still no results.
Here's my problem :
type sign = Neg | Zero | Pos | Error
let all_pairs (l1: sign list) (l2 : sign list) : sign list list =
let rec aux acc list =
match list with
| [] -> acc
| hd :: tl ->
let rec m_aux m_acc m_list =
match m_list with
| [] -> aux (m_acc :: acc) tl
| m_hd :: m_tl -> m_aux (m_hd :: m_acc) m_tl
in m_aux [hd] l2
in aux [] l1
With a given L1, L2 which are sign list, return a sign list list with every combination of two signs x and y, x is in L1 and y is in L2
Example :
L1 : [Pos; Error]
L2 : [Neg; Zero]
all_pairs L1 L2 should return
[ [Pos; Neg]; [Pos; Zero]; [Error; Neg]; [Error; Zero] ]
In this exact order
I don't understand your first line. But here's a session showing how to build up the results you seem to be asking for:
# let l1 = [];;
val l1 : 'a list = []
# let l2 = [1;2];;
val l2 : int list = [1; 2]
# let result1 = l1 # [l2];;
val result1 : int list list = [[1; 2]]
# let l3 = [1;3];;
val l3 : int list = [1; 3]
# let result2 = result1 # [l3];;
val result2 : int list list = [[1; 2]; [1; 3]]
A problem is that you're trying to extend your lists at the end. This isn't natural (or efficient) in OCaml. If you think about a adding new value to the beginning of a list things are simpler.
# let result3 = l3 :: l1;;
val result3 : int list list = [[1; 3]]
# let result4 = l2 :: result3;;
val result4 : int list list = [[1; 2]; [1; 3]]
The :: operator adds a new value to the beginning of a list. There's no single operator for adding to the end of a list (because it's not natural or efficient).
Update
You can code your function like this:
let all_pairs l1 l2 =
List.concat
(List.map
(fun a -> List.map (fun b -> [a;b]) l2)
l1)
It works for me.
I wish to write something that can make copies of all the elements in a list. So if I wanted 2 of list
[1; 2; 3; 4]
it would become
[1; 1; 2; 2; 3; 3; 4; 4]
So I was planning on writing a function recursively with
let rec dupeElem row count =
match row with
| [] -> []
| hd::tl -> (makeCopy hd count) # dupeElem tl count
where count is the number of copies I want. The function will take each head element in the list and send it to the copy function to make copies to insert back into the list. Then makeCopy would look like:
let makeCopy elem Count =
match Count with
| 0 -> []
| 1 -> elem
| 2 -> elem :: elem
|....
But I get errors for when it returns back to dupeElem. I understand doing hard cases would not be the wisest idea but it was to test whether it can work or not. How would I fix/improve what I have to get it to work?
Just for the sake of non-recursive solutions:
let xs = [1; 2; 3; 4; 5]
xs |> List.collect (fun x -> List.replicate 3 x)
//val it : int list = [1; 1; 1; 2; 2; 2; 3; 3; 3; 4; 4; 4; 5; 5; 5]
makeCopy returns a list for the 0 case, but for the 1 case you are returning a single element. Changing the case for 1 to the following should fix a compile time error:
| 1 -> [elem]
For case 2, your use of :: is invalid because the right hand side is not a list, but it is a single element. Consider replacing it with either of the following:
| 2 -> elem :: [elem]
Or...
| 2 -> [ elem; elem ]
A mutually recursive way:
let rec dupl n = function
| [] -> []
| h::t -> cons h (dupl n t) n
and cons h t = function
| 0 -> t
| n -> cons h (h::t) (n-1)
The answer by s952163 is clean and straightforward. For more generality, if you don't just want to replicate, you could define functions f, g, and h, and do the following:
let xs = [1; 2; 3; 4]
let f = id // No need for type annotation, given the definitions of g and h
let g x = x * x
let h x = x * x * x
(List.zip3 xs xs xs) |> List.map (fun (a, b, c) -> [f a; g b; h c]) |> List.concat
For your specific case in which you just want to replicate you could do
let f = id<int> // The type annotation is necessary
and similarly for g and h or just use f for all three cases. Of course in this case the solution proposed by s952163 is much preferred.
I have a function that returns every "sublists" from a given list:
let rec sublists = function
[] -> [[]]
| h::t -> let st = sublists t in
List.map (function l -> h::l) st # st;;
For example, if you try
sublists [1;4;9;12]
it will return:
[[1; 4; 9; 12]; [1; 4; 9]; [1; 4; 12]; [1; 4]; [1; 9; 12]; [1; 9]; [1; 12];
[1]; [4; 9; 12]; [4; 9]; [4; 12]; [4]; [9; 12]; [9]; [12]; []]
That are every possible combinations of elements in the list (order doesn't matter)
I have to do a function that returns a different sublists pair that fulfill a given property.
Function must have this type: ('a list -> 'a list -> bool) -> 'a list -> 'a list * 'a list
For example, if we have the previous list and we try
search (<4) [1;4;9;12]
It will return:
([9;12], [9]) because these lists satisfaces the given condition (<4). Order does not matter, it could return ([9], [12]) instead, or another possible combination.
I'm stucked at this, I have done a function that check if a given list is a sublist of another list:
let is_sublist_of l1 l2 =
let sub = sublists l1 in
List.mem l2 sub;;
But I think that is useless here. Coul anyone help me?
Can't you just filter the list first and then apply the two first runs of sublist to it ?
let filter_sublist f l =
let l = List.filter f l in
let rec sublists = function
| [] -> [], []
| h :: t ->
let st1, st2 = sublists t in
h :: st1, st2
in sublists l
The problem here is that f is of type 'a -> bool because I don't understand your type ('a list -> 'a list -> bool). What is it supposed to represent ?
Need help!!
Define the function "Is_member," which the first parameter is the given matrix and the second parameter is x: int.
Check if element x is in the matrix1.
val Is_member: int list list -> int -> bool = <fun>
Example:
#let matrix1 = [[1; 2]; [3; 4]];;
#val matrix1 : int list list = [[1; 2]; [3; 4]]
# Is_member matrix1 3;;
- : bool = true
I can reduce your problem to just fill blank spaces:
# matrix1;;
- : int list list = [[1; 2]; [3; 4]]
# is_member 1 matrix1;;
- : bool = true
# let is_member x xs = List.____ (fun acc xs -> acc ____ (List.____ x xs)) false xs;;
val is_member : 'a -> 'a list list -> bool = <fun>
It will be easy for you now!