I'm wondering how can I write a function that divides a given list to sublists in a given point, swaps these sublists and returns a resulting list.
For example:
swap([1;3;5;6],2) => [5;6;1;3]
I suppose that the code that I developed is correct?
let rec swap (l,n) =
let rec loop t (count,laux) =
match t with
| h::t when count < n -> loop t (count+1, h::laux)
| h::t -> h::t# List.rev laux
| []->[]
in
loop l (0,[])
;;
You're almost there. The problem is your function handles the case when length of l is greater or equals to n incorrectly.
The pattern [] doesn't mean input list is empty; it means we come to the end of the list. What you should do at that point is returning the accumulator acc in the reverse order.
I rearrange patterns a little bit so base cases come first:
let rec swap (l, n) =
let rec loop xs count acc =
match xs with
| _ when count = n -> xs # List.rev acc
| [] -> List.rev acc
| h::t -> loop t (count+1) (h::acc)
in loop l 0 []
Related
example remplace_par_liste 2 [-4;-5] [1;2;3;2;2;9] --> [1;-4;-5;3;-4;-5-4;-5;9]
I know how to do it with an occurence but not with a list.
example remplace 2 0 [1;2;3;2;2;9] --> [1; 0; 3; 0; 0; 9]
let listere = [1;2;3;2;2;9];;
let rec remplace n p liste = match liste with
[] -> []
|a::q -> (if a = n then p else a)::(remplace n p q);;
remplace 2 0 listere;;
- : int list = [1; 0; 3; 0; 0; 9]
And there is the problem, i need another funtion to insert the list l1 in the list ?
let listerel = [1;2;3;2;2;9];;
let l1 = [-4;-5];;
let rec remplace_par_liste n l1 liste = match liste with
[] -> []
(|a::q -> (if a = n then l1 else a)::(remplace_par_liste n l1 q);;)
remplace_par_liste 2 l1 listerel;;
File "", line 4, characters 113-114:
Error: This expression has type int list
but an expression was expected of type int```
I would suggest you define the second function first.
:: will let us add x to the front of the list created by recursively running the function on the tail of the list.
# will let us concatenate two lists so we can insert the values in the substitute list into the result.
let rec replace_value_with_list v sub lst =
match lst with
| [] -> []
| x::xs when x <> v -> x :: replace_value_with_list v sub xs
| x::xs -> sub # replace_value_with_list v sub xs
The first function is then much simpler, being just a specialized application of the second, putting that single value into a list.
let replace_value v sub lst =
replace_value_with_list v [sub] lst
Downsides to this implementation
I have decided to edit to mention this based on the comments. The above is not tail-recursive. Each time a function is called, it takes up a certain amount of stack space. The stack is limited. Recursively call a function or functions too many times and you will get a stack overflow error.
OCaml (and some other programming languages, primarily in the functional vein) offer tail-call optimization. If the compiler can determine that the last thing a function does is call itself or another function, then the space the caller occupies on the stack can be reused.
We can modify the existing function from ealier.
let rec replace_value_with_list v sub lst =
match lst with
| [] -> []
| x::xs when x <> v -> x :: replace_value_with_list v sub xs
| x::xs -> sub # replace_value_with_list v sub xs
This operation, for instance, makes the function non-tail-recursive:
x :: replace_value_with_list v sub xs
First we have to call replace_value_with_list v sub xs and then add x to the front of it. We can solve this issue by passing along an accumulator that builds up the list. We can hide this detail by using a local auxiliary function. Because the local function is taking care of the recursion, replace_value_with_list no longer needs to be marked as recursive.
let replace_value_with_list v sub lst =
let rec aux v sub lst acc =
match lst with
| [] -> List.rev acc
| x::xs when x <> v -> aux v sub xs (x :: acc)
| x::xs -> replace_value_with_list v sub xs (sub # acc)
in
aux v sub lst []
Note that when we call the aux function, it will build up the accumulator in the reverse order to the way we expect, so we need to reverse the accumulator on the exit condition.
However, this is still not optimal because the # operator which performs the concatenation is not tail-recursive. We can overcome this by replacing # with List.rev_append which is tail-recursive.
let replace_value_with_list v sub lst =
let rec aux v sub lst acc =
match lst with
| [] -> List.rev acc
| x::xs when x <> v -> aux v sub xs (x::acc)
| x::xs -> aux v sub xs (List.rev_append sub acc)
in
aux v sub lst []
This process of iterating over a list and accumulating a value is where folds really shine.
let rvl v sub lst =
List.(
let f acc x = if x <> v then x::acc else rev_append sub acc in
fold_left f [] lst |> rev
)
How do you write a f# recursive function that accepts a positive integer n and a list xs as input, and returns a list containing only the first n elements in xs.
let rec something n xs =
..
something 3 [1..10] = [1;2;3]
The short answer is: Don't, just use Seq.take.
A simple version would be something like:
let rec take n list =
match n with
| 0 -> []
| _ -> List.head list :: take (n - 1) (List.tail list)
A tail-recursive could look like:
let rec take n list =
let rec innertake m innerlist acc =
match m with
| 0 -> List.rev acc
| _ -> innertake (m - 1) (List.tail innerlist) ((List.head innerlist) :: acc)
innertake n list []
Note that neither of these does anything to handle the case that the input list is shorter than the requested number of items.
I'm struggling to write the code, that will calculate sum of int list list. For example, if we consider following list
[[1],[1,5],[7],[2,3,4]]
we can get different possible sums, depending on which integer we choose every time:
[11,12,13,15,16,17]
Can someone give possible ways (not necessary the code) I could solve it?
This is my attempt to make tail-recursive (kinda) version of algorithm with using lists and pattern matching only. It is written in OCaml, not SML and requires ascending order of inner lists
let reverse list =
let rec iter list acc :int list = match list with
[] -> acc
| x::xs -> iter xs (x::acc)
in iter list [];;
let listAdd num list =
let rec iter num list acc :int list = match list with
[] -> acc
| x::xs -> iter num xs ((x + num)::acc)
in reverse( iter num list []);;
let listMerge listX listY =
let rec iter listX listY acc : int list = match listX with
[] -> (reverse acc) # listY
| x :: xs -> match listY with
[] -> (reverse acc ) # listX
| y :: ys -> match ( compare x y ) with
0 -> iter xs ys ( x::acc )
|(-1) -> iter xs listY ( x::acc )
| 1 -> iter listX ys ( y::acc )
in iter listX listY [];;
let listSums listX listY =
let rec iter listX listY acc = match listX with
[] -> acc
| x :: xs -> iter xs listY ( listMerge acc (listAdd x listY ) )
in iter listX listY [];;
let possibleSums shallowList = match shallowList with
[] -> []
| headList :: lists ->
let rec iter acc lists = match lists with
[] -> acc
| headList :: other -> iter ( listSums acc headList ) other
in iter headList lists;;
here possibleSums [[1];[1;5];[7];[2;3;4]];; evaluates to int list = [11; 12; 13; 15; 16; 17]
So basically logical steps are:
the reverse function is just an utility to restore order after resulting accumulator is built - usual concept for tail recursive optimisation
the listAdd function to avoid using map utility in constructing summaries
the listMerge function equal to set union to use sorted lists as integer sets
the listSums function for mapping summation to cartesian product of two sets
the posibleSums function for final level of mapping summation to full cartesian product of all sets.
This algorithm is not just avoiding stack overflow in recursion through TCO, but also providing near optimal solution for this calculation problem.
Also this solution can be further improved with adding premature merge sorting and removing repeating elements from sets, so inner set order is now insignificant:
let split lst =
let rec iter lst partX partY = match lst with
[] -> partX,partY
| x::xs -> iter xs partY (x::partX)
in iter lst [] [];;
let rec mergeSort lst = match lst with
[] -> []
|[x] -> [x]
| _ -> let partX,partY = split lst in
listMerge (mergeSort partX) (mergeSort partY);;
let possibleSums shallowList = match shallowList with
[] -> []
| headList :: lists ->
let rec iter acc lists = match lists with
[] -> acc
| headList :: other -> iter ( listSums acc (mergeSort headList) ) other
in iter (mergeSort headList) lists;;
You can test its efficiency on simple example. Let's define repeat function for making repetitive lists:
let rec repeat elem n = match n with
0 -> []
| _ -> elem :: (repeat elem (n - 1));;
In that case possibleSums( repeat( repeat 1 30) 30 ) will calculate correct singleton answer int list = [30] in no time. While more straightforward solutions (like Jesper's one) will do it forever.
The following is an attempt at breaking the steps up in readable and hopefully understandable parts
fun sums xss =
let
fun extend xss y = map (fn xs => y :: xs) xss
fun extend' xss ys = foldl (fn (y, b) => extend xss y # b) [] ys
fun extend'' xss = foldl (fn (xs,b) => extend' b xs) [[]] xss
fun sum xs = foldl op+ 0 xs
in
map sum (extend'' xss)
end
- sums [[1],[1,5],[7],[2,3,4]];
val it = [17,13,16,12,15,11] : int list
Obviously most of the functions could have been made to take the arguments as pairs in the correct order and thus have been given directly to the map and fold functions instead of wrapping them in anonymous functions.
i would try to solve it with a recursive loop - in pseudocode:
sum = 0;
while (i < arrayOfArrays.length ) {
sumUp(arrayOfArrayElements);
i ++
}
function sumUp() {
while( j < arrayOfArrayElement.length){
sum = sum + arrayOfArrayElement[j].val
j ++
}
}
so you call a function which sums up every array element of an array and sums the values up together inside a function which calls that function for every element inside that array of arrays. lolz
create a function which takes an array of ints and adds the containing ints with a for or while loop .
loop over the main array and call for every containing array element the function for suming up until there are no more elements left, you can achieve this by working with the .length of the array which should be accessible in every script/programming language
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 []
What I'm hoping to make this function do is:
Generate a list of random integers of length specified by count
Generate another random number to replace first element of list
Sort the list
Split list in half, discarding second half
Discard first element of list
Repeat 2-5 unless list is empty
What I have so far (but not working) is below. What is the matter with it?
let go count =
let rec cut l =
if List.length l = 0 then l
printfn "%A" l
let list = System.Random().Next(100)::List.tail l
let cut list =
let firstHalf= list |> Seq.take (List.length list / 2) |> Seq.toList
firstHalf
let listSorted = List.sort list
cut (List.tail listSorted)
let r = System.Random()
let list1 = List.init count (fun numbers -> r.Next(100))
printfn "List = %A" list1
cut list1
A few tips:
Don't test if a list is empty by List.length L = 0. Each test will take as long as the amount of elements in the list. Test with pattern matching instead, that's (almost) instantanteous:
Don't instantiate a new instance of a random number generator each time your cut function is called: let list = System.Random().... Doing that means that you're likely to get the same numbers (each instantiaion seeds the generator with the current system time). Just move your declaration r = System.Random() up a bit, and use that generator throughout your code.
example:
let rec cut l =
match l with
| [] -> // the list is empty, end the recursion here
| head::tail -> // the list consists of the head element and the rest
// you can refer to head and tail in your code here
let newlist = r.next(100) :: tail
You're declaring a function called 'cut' inside your recursive 'cut' function, which means that the last call to 'cut' in your recursive function actually calls the non-recursive one you defined inside. Use different names there.
You've written 'if List.length l = 0 then l', which (apart from not using a pattern match) also presents a problem: an 'if' in F# is an expression, like the ? operator in C#. In C# that would mean something like
(l.Count == 0) ? l : //other case missing! error! danger!
Another tip: once your list is sorted, you don't need to sort again each time you add a new random element. You can write code that inserts a new element in a sorted list that would be more efficient than adding an element and sorting afterwards. I'll leave the insert-into-sorted-list as an excercise.
I hope these tips are useful.
Here it is as simple as making functions for each of your statements.
let rnd = new System.Random()
let genList n =
[for i = 0 to n-1 do yield rnd.Next()]
let replaceHead v lst = match lst with
| [] -> []
| (x::xs) -> (v::xs)
let splitInHalf lst =
let len = (lst |> List.length) / 2
let rec loop n lst =
match (n,lst) with
| 0,_ -> []
| _,[] -> []
| _,(x::xs) -> x :: (loop (n-1) xs)
loop len lst
let start n =
let lst = genList n
let rec loop l =
match l with
| [] -> []
| ls -> match ls |> replaceHead (rnd.Next())
|> List.sort
|> splitInHalf with
| [] -> []
| xs -> xs |> List.tail |> loop
loop lst
start 1
here is my try...
let go count =
System.Random() |> fun rnd -> // With ranomizer ... (we will need it)
let rec repeat = function // So we got recursion
| x::xs when xs.Length <> 1 -> // while we have head and tail
printfn "%A" xs
rnd .Next(100) :: (List.tail xs) // Add random value
|> Seq.sort // Sort
|> Seq.take( abs(xs.Length /2) ) // Make a half
|> Seq.skip 1 // Remove first (just skip)
|> List.ofSeq // Make the list
|> repeat // So and repeat
| x::xs -> printfn "%A" xs
| _ -> () // If we have no head and tail
repeat <| List.init count (fun _ -> rnd.Next(100)) // do it with our random list
It does look like homework :)
But here is my take on it:
#light
// Create random integer sequence
let random_integers_of_length l =
(l, new System.Random())
|> Seq.unfold (fun (c, rnd) -> if c = 0 then None else Some (rnd.Next(), (c-1, rnd)))
|> Seq.cache
let rec mutate numbers =
printfn "%A" (List.ofSeq numbers); // pretty print the list
match numbers with
| _ when (Seq.length numbers) <= 1 -> printfn "Done.." // if length is 1 or 0 we can stop.
| _ ->
numbers
|> Seq.skip 1 // discard first element
|> Seq.append (random_integers_of_length 1) // append random number at the start
|> Seq.sort // sort
|> Seq.take ((Seq.length numbers) / 2) // take the first half, ignore the rest
|> Seq.skip 1 // discard first element
|> mutate // do it again.