I wrote this F# function to partition a list up to a certain point and no further -- much like a cross between takeWhile and partition.
let partitionWhile c l =
let rec aux accl accr =
match accr with
| [] -> (accl, [])
| h::t ->
if c h then
aux (h::accl) t
else
(accl, accr)
aux [] l
The only problem is that the "taken" items are reversed:
> partitionWhile ((>=) 5) [1..10];;
val it : int list * int list = ([5; 4; 3; 2; 1], [6; 7; 8; 9; 10])
Other than resorting to calling rev, is there a way this function could be written that would have the first list be in the correct order?
Here's a continuation-based version. It's tail-recursive and returns the list in the original order.
let partitionWhileCps c l =
let rec aux f = function
| h::t when c h -> aux (fun (acc, l) -> f ((h::acc), l)) t
| l -> f ([], l)
aux id l
Here are some benchmarks to go along with the discussion following Brian's answer (and the accumulator version for reference):
let partitionWhileAcc c l =
let rec aux acc = function
| h::t when c h -> aux (h::acc) t
| l -> (List.rev acc, l)
aux [] l
let test =
let l = List.init 10000000 id
(fun f ->
let r = f ((>) 9999999) l
printfn "%A" r)
test partitionWhileCps // Real: 00:00:06.912, CPU: 00:00:07.347, GC gen0: 78, gen1: 65, gen2: 1
test partitionWhileAcc // Real: 00:00:03.755, CPU: 00:00:03.790, GC gen0: 52, gen1: 50, gen2: 1
Cps averaged ~7s, Acc ~4s. In short, continuations buy you nothing for this exercise.
I expect you can use continuations, but calling List.rev at the end is the best way to go.
I usually prefer Sequences over List as they are lazy and you got List.toSeq and Seq.toList functions to convert between them. Below is the implementation of your partitionWhile function using sequences.
let partitionWhile (c:'a -> bool) (l:'a list) =
let fromEnum (e:'a IEnumerator) =
seq { while e.MoveNext() do yield e.Current}
use e = (l |> List.toSeq).GetEnumerator()
(e |> fromEnum |> Seq.takeWhile c |> Seq.toList)
,(e |> fromEnum |> Seq.toList)
You can rewrite the function like this:
let partitionWhile c l =
let rec aux xs =
match xs with
| [] -> ([], [])
| h :: t ->
if c h then
let (good, bad) = aux t in
(h :: good, bad)
else
([], h :: t)
aux l
Yes, as Brian has noted it is no longer tail recursive, but it answers the question as stated. Incidentally, span in Haskell is implemented exactly the same way in Hugs:
span p [] = ([],[])
span p xs#(x:xs')
| p x = (x:ys, zs)
| otherwise = ([],xs)
where (ys,zs) = span p xs'
A good reason for preferring this version in Haskell is laziness: In the first version all the good elements are visited before the list is reversed. In the second version the first good element can be returned immediately.
I don't think I'm the only one to learn a lot from (struggling with) Daniel's CPS solution. In trying to figure it out, it helped me change several potentially (to the beginner) ambiguous list references, like so:
let partitionWhileCps cond l1 =
let rec aux f l2 =
match l2 with
| h::t when cond h -> aux (fun (acc, l3) -> f (h::acc, l3)) t
| l4 -> f ([], l4)
aux id l1
(Note that "[]" in the l4 match is the initial acc value.) I like this solution because it feels less kludgey not having to use List.rev, by drilling to the end of the first list and building the second list backwards. I think the other main way to avoid .rev would be to use tail recursion with a cons operation. Some languages optimize "tail recursion mod cons" in the same way as proper tail recursion (but Don Syme has said that this won't be coming to F#).
So this is not tail-recursive safe in F#, but it makes my answer an answer and avoids List.rev (this is ugly to have to access the two tuple elements and would be a more fitting parallel to the cps approach otherwise, I think, like if we only returned the first list):
let partitionWhileTrmc cond l1 =
let rec aux acc l2 =
match l2 with
| h::t when cond h -> ( h::fst(aux acc t), snd(aux acc t))
| l3 -> (acc, l3)
aux [] l1
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
)
My Quicksort code works for some values of N (size of list), but for big values (for example, N = 82031) the error returned by OCaml is:
Fatal error: exception Stack_overflow.
What am I doing wrong?
Should I create an iterative version due to the fact that OCaml does not support recursive functions for big values?
let rec append l1 l2 =
match l1 with
| [] -> l2
| x::xs -> x::(append xs l2)
let rec partition p l =
match l with
| [] -> ([],[])
| x::xs ->
let (cs,bs) = partition p xs in
if p < x then
(cs,x::bs)
else
(x::cs,bs)
let rec quicksort l =
match l with
| [] -> []
| x::xs ->
let (ys, zs) = partition x xs in
append (quicksort ys) (x :: (quicksort zs));;
The problem is that none of your recursive functions are tail-recursive.
Tail-recursivity means that no further actions should be done by the caller (see here). In that case, there is no need to keep the environment of the caller function and the stack is not filled with environments of recursive calls. A language like OCaml can compile that in an optimal way but for this you need to provide tail-recursive functions.
For example, your first function, append :
let rec append l1 l2 =
match l1 with
| [] -> l2
| x::xs -> x::(append xs l2)
As you can see, after append xs l2 has been called, the caller needs to execute x :: ... and this function end up by not being tail-recursive.
Another way of doing it in a tail-recursive way is this :
let append l1 l2 =
let rec aux l1 l2 =
match l1 with
| [] -> l2
| x::xs -> append xs (x :: l2)
in aux (List.rev l1) l2
But, actually, you can try to use List.rev_append knowing that this function will append l1 and l2 but l1 will be reversed (List.rev_append [1;2;3] [4;5;6] gives [3;2;1;4;5;6])
Try to transform your other functions in tail-recursive ones and see what it gives you.
Best to fix the underlying problem as noted above, but if you really need a big stack, set ulimit -s. See also:
https://stackoverflow.com/a/71375559/14055985
Is there a library function to find List1 minus elements that appear in List2? I've been googling around and haven't found much.
It doesn't seem too trivial to write it myself. I've written a function to remove a specific element from a list but that's much more simple:
let rec difference l arg = match l with
| [] -> []
| x :: xs ->
if (x = arg) then difference xs arg
else x :: difference xs arg;;
Will this do?
let diff l1 l2 = List.filter (fun x -> not (List.mem x l2)) l1
What I ended up actually doing was just writing another function which would call the first one I posted
let rec difference l arg = match l with
| [] -> []
| x :: xs ->
if (x = arg) then difference xs arg
else x :: difference xs arg;;
let rec list_diff l1 l2 = match l2 with
| [] -> l1
| x :: xs -> list_diff (difference l1 x) xs;;
Although the solution I accepted is much more elegant
For [1;2;3;4;5], I want to return [[1;2;3;4;5];[2;3;4;5];[3;4;5;];[4;5];[5];[]]
I'm trying to use the List library but I'm unsure how to. So far, I know I have to use List.tl to get the list without the first element
let rec tailsoflist (l : 'a list) : 'a list list =
match l with
[] -> [[]]
| x::xs -> l::(tails xs)
I did this recursively but now I want to just use the list library without using recursion.
let tails (l : 'a list) : 'a list list
EDIT: Sorry guys, what I specified for the function to return is incorrect. Just updated it with the correct output.
As I said in the comment, these are not the tails of l but copies of the tails of l:
# let tails l = List.fold_right (fun e acc -> (e::(List.hd acc))::acc) l [[]] ;;
val tails : 'a list -> 'a list list = <fun>
# tails [1; 2; 3; 4] ;;- : int list list = [[1; 2; 3; 4]; [2; 3; 4]; [3; 4]; [4]; []]
There is no good way to write that function in terms of the built-in functions.
The answer you give in your question is fine but it would be more idiomatic to not annotate the types and use function:
let rec tails = function
| [] -> [[]]
| _::xs' as xs -> xs::tails xs'
Other languages, like F#, provide a List.unfold function that tails can be written in terms of.
Ah, the old trick to accumulate on the original list to cast tails as a catamorphism. This is done without explicit recursion using just functions on the List module:
let tails l = List.rev ( [] :: snd (List.fold_right
(fun _ (t,ts) -> List.tl t, t::ts) l (l, [])) )
It produces the tails as you expect:
# tails [1;2;3;4;5];;
- : int list list = [[1; 2; 3; 4; 5]; [2; 3; 4; 5]; [3; 4; 5]; [4; 5]; [5]; []]
and the tails are the actual structural tails of the input list, so that List.tl l == List.hd (List.tl (tails l)).
"Without using recursion"... why ? Recursion is a useful tool, even outside the List library.
let rec suffixes = function
| [] -> [[]]
| hd::tl as suff -> suff :: suffixes tl
Your function (which doesn't compile because you use tails instead of tailsoflist) returns the list of suffixes of a list. Due to the list structure, it's easier to compute than the prefixes.
You can express the prefixes from the suffixes :
let prefixes li = List.map List.rev (suffixes (List.rev li));;
You could do a direct version using an accumulator:
let prefixes li =
let rec pref acc = function
| [] -> List.rev acc :: []
| hd::tl -> List.rev acc :: pref (hd :: acc) tl
in pref [] li
and express it using List.fold_left if you want to avoid recursion, but this is convoluted so you should prefer the direct version in my opinion:
let prefixes li =
let acc, res =
List.fold_left
(fun (acc, res) e -> (e :: acc), (List.rev acc :: res))
([], []) li in
List.rev acc :: res
Finally, it is possible to destroy your brain with a version using continuations, but I don't remember the exact code. Roughly, the continuation is equivalent to the "accumulator" of the direct version.
One more question about most elegant and simple implementation of element combinations in F#.
It should return all combinations of input elements (either List or Sequence).
First argument is number of elements in a combination.
For example:
comb 2 [1;2;2;3];;
[[1;2]; [1;2]; [1;3]; [2;2]; [2;3]; [2;3]]
One less concise and more faster solution than ssp:
let rec comb n l =
match n, l with
| 0, _ -> [[]]
| _, [] -> []
| k, (x::xs) -> List.map ((#) [x]) (comb (k-1) xs) # comb k xs
let rec comb n l =
match (n,l) with
| (0,_) -> [[]]
| (_,[]) -> []
| (n,x::xs) ->
let useX = List.map (fun l -> x::l) (comb (n-1) xs)
let noX = comb n xs
useX # noX
There is more consise version of KVB's answer:
let rec comb n l =
match (n,l) with
| (0,_) -> [[]]
| (_,[]) -> []
| (n,x::xs) ->
List.flatten [(List.map (fun l -> x::l) (comb (n-1) xs)); (comb n xs)]
The accepted answer is gorgeous and quickly understandable if you are familiar with tree recursion. Since elegance was sought, opening this long dormant thread seems somewhat unnecessary.
However, a simpler solution was asked for. Iterative algorithms sometimes seem simpler to me. Furthermore, performance was mentioned as an indicator of quality, and iterative processes are sometimes faster than recursive ones.
The following code is tail recursive and generates an iterative process. It requires a third of the amount of time to compute combinations of size 12 from a list of 24 elements.
let combinations size aList =
let rec pairHeadAndTail acc bList =
match bList with
| [] -> acc
| x::xs -> pairHeadAndTail (List.Cons ((x,xs),acc)) xs
let remainderAfter = aList |> pairHeadAndTail [] |> Map.ofList
let rec comboIter n acc =
match n with
| 0 -> acc
| _ ->
acc
|> List.fold (fun acc alreadyChosenElems ->
match alreadyChosenElems with
| [] -> aList //Nothing chosen yet, therefore everything remains.
| lastChoice::_ -> remainderAfter.[lastChoice]
|> List.fold (fun acc elem ->
List.Cons (List.Cons (elem,alreadyChosenElems),acc)
) acc
) []
|> comboIter (n-1)
comboIter size [[]]
The idea that permits an iterative process is to pre-compute a map of the last chosen element to a list of the remaining available elements. This map is stored in remainderAfter.
The code is not concise, nor does it conform to lyrical meter and rhyme.
A naive implementation using sequence expression. Personally I often feel sequence expressions are easier to follow than other more dense functions.
let combinations (k : int) (xs : 'a list) : ('a list) seq =
let rec loop (k : int) (xs : 'a list) : ('a list) seq = seq {
match xs with
| [] -> ()
| xs when k = 1 -> for x in xs do yield [x]
| x::xs ->
let k' = k - 1
for ys in loop k' xs do
yield x :: ys
yield! loop k xs }
loop k xs
|> Seq.filter (List.length >> (=)k)
Method taken from Discrete Mathematics and Its Applications.
The result returns an ordered list of combinations stored in arrays.
And the index is 1-based.
let permutationA (currentSeq: int []) (n:int) (r:int): Unit =
let mutable i = r
while currentSeq.[i - 1] = n - r + i do
i <- (i - 1)
currentSeq.[i - 1] <- currentSeq.[i - 1] + 1
for j = i + 1 to r do
currentSeq.[j - 1] <- currentSeq.[i - 1] + j - i
()
let permutationNum (n:int) (r:int): int [] list =
if n >= r then
let endSeq = [|(n-r+1) .. n|]
let currentSeq: int [] = [|1 .. r|]
let mutable resultSet: int [] list = [Array.copy currentSeq];
while currentSeq <> endSeq do
permutationA currentSeq n r
resultSet <- (Array.copy currentSeq) :: resultSet
resultSet
else
[]
This solution is simple and helper function costs constant memory.
My solution is less concise, less effective (altho, no direct recursion used) but it trully returns all combinations (currently only pairs, need to extend filterOut so it can return a tuple of two lists, will do little later).
let comb lst =
let combHelper el lst =
lst |> List.map (fun lstEl -> el::[lstEl])
let filterOut el lst =
lst |> List.filter (fun lstEl -> lstEl <> el)
lst |> List.map (fun lstEl -> combHelper lstEl (filterOut lstEl lst)) |> List.concat
comb [1;2;3;4] will return:
[[1; 2]; [1; 3]; [1; 4]; [2; 1]; [2; 3]; [2; 4]; [3; 1]; [3; 2]; [3; 4]; [4; 1]; [4; 2]; [4; 3]]
Ok, just tail combinations little different approach (without using of library function)
let rec comb n lst =
let rec findChoices = function
| h::t -> (h,t) :: [ for (x,l) in findChoices t -> (x,l) ]
| [] -> []
[ if n=0 then yield [] else
for (e,r) in findChoices lst do
for o in comb (n-1) r do yield e::o ]