I have a function where I want to transform a list of floats into another one, where for each element I want to have x percent of element i spill over into element i + 1
example:
let p3 = [0.1; 0.2; 0.4; 0.2; 0.1]
then p3_s should be:
[0.05; 0.15; 0.3; 0.3; 0.2]
To do this I took half of each element and added it to the next element.
0.1 became 0.05 because it gave 0.05 to the next, there is no previous element
0.2 became 0.15 because it gave 0.1 to the next and got 0.05 from the
first
etc
and finally 0.1 became 0.2 because it .01 from the
previous. There is no next element.
Now I came up with this which works but only for list of size 5:
// create list
let p3 = [0.1; 0.2; 0.4; 0.2; 0.1]
let shiftList orgList shift =
// chop list up in tuples of what stays and what moves
let ms = orgList |> List.map (fun p-> (p * shift, p * (1.0-shift)))
// map new list
ms |> List.mapi (fun i (move, stay) ->
match i with
| 0 -> stay
| 4 -> stay + fst ms.[i-1] + move // note hardcoded 4
| _ -> stay + fst ms.[i-1])
// get shifted list
shiftList p3 0.5
Now for the questions:
1) How do I make it match on any length list? Now I hardcoded the 4 in the match expression but I'd like to be able to accept any lenght list.
I tried this:
let shiftList orgList shift =
// chop list up in tuples of what stays and what moves
let ms = orgList |> List.map (fun p-> (p * shift, p * (1.0-shift)))
// find length
let last = orgList.Length - 1
// map new list
ms |> List.mapi (fun i (move, stay) ->
match i with
| 0 -> stay
| last -> stay + fst ms.[i-1] + move
| _ -> stay + fst ms.[i-1]) // now this one will never be matched
But this will not treat last as the number 4, instead it becomes a variable for i even though last is already declared above.
So how could I match on a variable, so that I can treat the last elmement differently? Finding the first one is easy because it's at 0.
2) How would you do this? I'm still pretty fresh to F# there are many things I don't know about yet. Guess the general case here is: how do I map a different function to the first and last element of a list, and a general one to the others?
Thanks in advance,
Gert-Jan
Here is a more functional solution
let func (input:float list) =
let rec middle_end input_ =
match input_ with
|h::t::[] -> ((h/2.0)+t)::[]
|h::t::tt ->((h+t)/2.0)::(middle_end (t::tt))
| _ -> [] //fix short lists
let fst = input.Head/2.0
fst::middle_end(input)
Also, this only requires a single pass through the list, rather than the 3 in Ramon's solution, as well as less temporary storage.
As an alternative to writing your own recursive function, you can also use built-in functions. The problem can be solved quite easily using Seq.windowed. You still need a special case for the last element though:
let p3 = [0.1; 0.2; 0.4; 0.2; 0.1]
// Prefix zero before the list, pre-calculate the length
let p3' = (0.0 :: p3)
let l = p3.Length
// Perform the transformation
p3'
|> Seq.windowed 2
|> Seq.mapi (fun i ar ->
(if i = l - 1 then ar.[1] else ar.[1] / 2.0) + ar.[0] / 2.0)
|> List.ofSeq
You want to do:
let shiftList orgList shift =
// chop list up in tuples of what stays and what moves
let ms = orgList |> List.map (fun p-> (p * shift, p * (1.0-shift)))
// find length
let last = orgList.Length - 1
// map new list
ms |> List.mapi (fun i (move, stay) ->
match i with
| 0 -> stay
| last' when last' = last -> stay + fst ms.[i-1] + move
| _ -> stay + fst ms.[i-1]) // now this one will never be matched
Using List.scan:
let lst = [0.1; 0.2; 0.4; 0.2; 0.1]
let len = (lst.Length-1)
lst
|> List.mapi (fun i e -> (i,e))
|> List.scan (fun (c,_) (i,e) -> if i = len then (0.0,e+c) else ((e/2.0),(e/2.0)+c)) (0.0,0.0) |> List.tail
|> List.map snd
Just another idea,
let bleh p3 =
match Seq.fold (fun (give,acc) i -> i*0.5,((i*0.5 + give) :: acc)) (0.0,[]) p3 with
|(give,h::t) -> give+h :: t |> List.rev
|(_,[]) -> []
Related
I am new to F# & tuples and I am trying to split a list into three lists of tuples using recursion and matching.
For example, a list of [1; 2; 3] would return:
l1 = [1]
l2 = [2]
l3 = [3]
or
[1;2;3;4;5;6;7]:
l1 = [1;2;3]
l2 = [4; 5]
l3 = [6; 7]
So far my code starts out as
let rec split x =
match x with
| _ -> [], [], []
I'm not sure where to start when inserting elements into each list.
The most basic approach would be to walk over the list, process the rest of it recursively and then append the current element to one of the three returned lists. You will need to add an extra parameters i to the function to keep track of how far in the list you are (and then use this to determine where should the current elemnt go). The general structure in the most basic form is:
let split l =
let length = List.length l
let rec loop i l =
match l with
| [] ->
// Empty list just becomes a triple of empty lists
[], [], []
| x::xs ->
// Process the rest of the list recursively. This
// gives us three lists containing the values from 'xs'
let l1, l2, l3 = loop (i + 1) xs
// Now comes the tricky bit. Here you need to figure out
// whether 'x' should go into 'l1', 'l2' or 'l3'.
// Then you can append it to one of them using something like:
l1, x::l2, l3
// Walk over the list, starting with index 'i=0'
loop 0 l
What to do about the tricky bit? I do not have a solution that works exactly as you wanted, but the following is close - it simply looks whether i is greater than 1/3 of the length or 2/3 of the length:
let split l =
let length = List.length l
let rec loop i l =
match l with
| [] -> [], [], []
| x::xs ->
let l1, l2, l3 = loop (i + 1) xs
if i >= length / 3 * 2 then l1, l2, x::l3
elif i >= length / 3 then l1, x::l2, l3
else x::l1, l2, l3
loop 0 l
This will always create groups of length / 3 and put remaining elements in the last list:
split [1..3] // [1], [2], [3]
split [1..4] // [1], [2], [3; 4]
split [1..5] // [1], [2], [3; 4; 5]
split [1..6] // [1; 2], [3; 4], [5; 6]
You should be able to adapt this to the behaviour you need - there is some fiddly calculation that you need to do to figure out exactly where the cut-off points are, but that's a matter of getting the +/-1s right!
There is a function for that in the List module.
You can test it easily in F# interactive (fsi).
let input = [1;2;3];;
let output = List.splitInto 3 input;;
output;;
val it : int list list = [[1]; [2]; [3]]
So it returns a list of lists.
If you want to do it by hand, you can still use other list functions (which might be good exercise in itself):
let manualSplitInto count list =
let l = List.length list
let n = l / count
let r = l % count
List.append
[(List.take (n+r) list)]
(List.unfold (fun rest ->
match rest with
| [] -> None
| _ -> let taken = min n (List.length rest)
Some (List.take taken rest, List.skip taken rest))
(List.skip (n+r) list))
Here, List.unfold does the iteration (recursing) part for you.
So, if you really want to train working with recursive functions, you will end up writing your own List.unfold replacement or something more tailored to your concrete use case.
let pedestrianSplitInto count list =
let l = List.length list
let n = l / count
let r = l % count
let rec step rest acc =
match rest with
| [] -> acc
| _ ->
let taken = min n (List.length rest)
step (List.skip taken rest) ((List.take taken rest) :: acc)
List.rev (step (List.skip (n+r) list) [List.take (n+r) list])
Please observe how similar the implementation of function step is to the lambda given to List.unfold in manualSplitInto.
If you also do not want to use functions like List.take or List.skip, you will have to go even lower level and do element wise operations, such as:
let rec splitAtIndex index front rear =
match index with
| 0 -> (List.rev front, rear)
| _ -> splitAtIndex (index - 1) ((List.head rear) :: front) (List.tail rear)
let stillLivingOnTreesSplitInto count list =
let l = List.length list
let n = l / count
let r = l % count
let rec collect result (front,rear) =
match rear with
| [] -> (front :: result)
| _ -> collect (front :: result) (splitAtIndex n [] rear)
let x = splitAtIndex (n+r) [] list
collect [] x |> List.rev
If you know it will always be triplets then this should work.
let xs = [1..7]
let n = List.length xs
let y = List.mapi (fun i x -> (x, 3 * i / n)) xs
List.foldBack (fun (x, i) (a,b,c) -> match i with 0 -> (x::a,b,c) | 1 -> (a,x::b,c) | 2 -> (a,b,x::c)) y (([],[],[]))
I'm looking for the best way to partition a list (or seq) so that groups have a given size.
for ex. let's say I want to group with size 2 (this could be any other number though):
let xs = [(a,b,c); (a,b,d); (y,z,y); (w,y,z); (n,y,z)]
let grouped = partitionBySize 2 input
// => [[(a,b,c);(a,b,d)]; [(y,z,y);(w,y,z)]; [(n,y,z)]]
The obvious way to implement partitionBySize would be by adding the position to every tuple in the input list so that it becomes
[(0,a,b,c), (1,a,b,d), (2,y,z,y), (3,w,y,z), (4,n,y,z)]
and then use GroupBy with
xs |> Seq.ofList |> Seq.GroupBy (function | (i,_,_,_) -> i - (i % n))
However this solution doesn't look very elegant to me.
Is there a better way to implement this function (maybe with a built-in function)?
This seems to be a repeating pattern that's not captured by any function in the F# core library. When solving similar problems earlier, I defined a function Seq.groupWhen (see F# snippets) that turns a sequence into groups. A new group is started when the predicate holds.
You could solve the problem using Seq.groupWhen similarly to Seq.group (by starting a new group at even index). Unlike with Seq.group, this is efficient, because Seq.groupWhen iterates over the input sequence just once:
[3;3;2;4;1;2;8]
|> Seq.mapi (fun i v -> i, v) // Add indices to the values (as first tuple element)
|> Seq.groupWhen (fun (i, v) -> i%2 = 0) // Start new group after every 2nd element
|> Seq.map (Seq.map snd) // Remove indices from the values
Implementing the function directly using recursion is probably easier - the solution from John does exactly what you need - but if you wanted to see a more general approach then Seq.groupWhen may be interesting.
List.chunkBySize (hat tip: Scott Wlaschin) is now available and does exactly what you're talking about. It appears to be new with F# 4.0.
let grouped = [1..10] |> List.chunkBySize 3
// val grouped : int list list =
// [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]; [10]]
Seq.chunkBySize and Array.chunkBySize are also now available.
Here's a tail-recursive function that traverses the list once.
let chunksOf n items =
let rec loop i acc items =
seq {
match i, items, acc with
//exit if chunk size is zero or input list is empty
| _, [], [] | 0, _, [] -> ()
//counter=0 so yield group and continue looping
| 0, _, _::_ -> yield List.rev acc; yield! loop n [] items
//decrement counter, add head to group, and loop through tail
| _, h::t, _ -> yield! loop (i-1) (h::acc) t
//reached the end of input list, yield accumulated elements
//handles items.Length % n <> 0
| _, [], _ -> yield List.rev acc
}
loop n [] items
Usage
[1; 2; 3; 4; 5]
|> chunksOf 2
|> Seq.toList //[[1; 2]; [3; 4]; [5]]
I like the elegance of Tomas' approach, but I benchmarked both our functions using an input list of 10 million elements. This one clocked in at 9 secs vs 22 for his. Of course, as he admitted, the most efficient method would probably involve arrays/loops.
What about a recursive approach? - only requires a single pass
let rec partitionBySize length inp dummy =
match inp with
|h::t ->
if dummy |> List.length < length then
partitionBySize length t (h::dummy)
else dummy::(partitionBySize length t (h::[]))
|[] -> dummy::[]
Then invoke it with partitionBySize 2 xs []
let partitionBySize size xs =
let sq = ref (seq xs)
seq {
while (Seq.length !sq >= size) do
yield Seq.take size !sq
sq := Seq.skip size !sq
if not (Seq.isEmpty !sq) then yield !sq
}
// result to list, if you want
|> Seq.map (Seq.toList)
|> Seq.toList
UPDATE
let partitionBySize size (sq:seq<_>) =
seq {
let e = sq.GetEnumerator()
let empty = ref true;
while !empty do
yield seq { for i = 1 to size do
empty := e.MoveNext()
if !empty then yield e.Current
}
}
array slice version:
let partitionBySize size xs =
let xa = Array.ofList xs
let len = xa.Length
[
for i in 0..size..(len-1) do
yield ( if i + size >= len then xa.[i..] else xa.[i..(i+size-1)] ) |> Array.toList
]
Well, I was late for the party. The code below is a tail-recursive version using high-order functions on List:
let partitionBySize size xs =
let i = size - (List.length xs - 1) % size
let xss, _, _ =
List.foldBack( fun x (acc, ls, j) ->
if j = size then ((x::ls)::acc, [], 1)
else (acc, x::ls, j+1)
) xs ([], [], i)
xss
I did the same benchmark as Daniel did. This function is efficient while it is 2x faster than his approach on my machine. I also compared it with an array/loop version, they are comparable in terms of performance.
Moreover, unlike John's answer, this version preserves order of elements in inner lists.
here's my code: (should work fine)
let rec interleave = function
| ([],ys) -> []
| (xs,[]) -> []
| (x::xs,y::ys) -> x :: y :: interleave (xs, ys)
let gencut n list =
let first = list |> Seq.take n |> Seq.toList
let last = list |> Seq.skip n |> Seq.toList
(first, last)
let cut list = gencut ((List.length list)/2) list
let shuffle x = interleave (cut x)
let isNotSame (list1, list2) = if list1 = list2 then false else true
let countShuffles xs =
let mutable newList = xs
let mutable x = 1
if (List.length(xs) > 1) then newList <- shuffle newList
while isNotSame (newList, xs) do
newList <- shuffle newList
x <- x + 1
x
//lists countShuffles from 1 to x
let listShuffles x =
for i = 1 to x/2 do
let y = [1..(i*2)]
let z = countShuffles y
printf "A deck of %d cards takes %d shuffles\n" (i*2) z
printf ""
The flow is (from main function down to 1st helper):
listShuffles -> countShuffles -> shuffle + isNotSame -> cut -> gencut + interleave
(so just try listShuffles)
What "countShuffles" does is:
take an int, creates a list, (1..n), (which is supposed to represent a deck of cards),
cuts it in half, does a perfect-out shuffle (perfect bridge shuffle)
and counts how many shuffles it takes to make the deck original again
What listShuffles does is:
takes an int, and prints out countShuffles 1 through n
(you need an even amount of cards in the deck)
Sorry about the explanation, now my question:
is it possible to see how many times a certain number is returned?
i.e.:
listShuffles 10000;;
see how many times "16" appeared.
i was thinking of making a list.
and incrementing a given index.
which represents a certain number that was returned.
but i cant find how to do that...
p.s. i dont care how my code is wrong or anything like that,
this is my first F# program, and it is homework based on my professor's criteria,
(the assignment is complete, this question is for curiosity)
There are a few alternatives
If you only want one number you can do
List |> Seq.sumBy (fun t -> if t = 16 then 1 else 0)
If you want a range of different numbers, it may be better to do
let map = List |> Seq.countBy (fun t -> t) |> Map.ofSeq
then map.[16] is the number of times that 16 occurs in the list
You can do something like:
let listShuffles x =
[| for i = 1 to x/2 do
yield countShuffles [1..(i*2)] |]
Now this function return array and then you can use Array module functions to find how many times a number appears
listShuffles 1000 |> Array.filter ((=) 16) |> Array.length
Or to print all such numbers and their occurrence count:
listShuffles 100
|> Array.toSeq |> Seq.groupBy id
|> Seq.iter (fun (k,v) -> printfn "%d appears %d times" k (v.Count()))
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.
i'm trying to learn ocaml right now and wanted to start with a little program, generating all bit-combinations:
["0","0","0"]
["0","0","1"]
["0","1","0"]
... and so on
My idea is the following code:
let rec bitstr length list =
if length = 0 then
list
else begin
bitstr (length-1)("0"::list);
bitstr (length-1)("1"::list);
end;;
But i get the following error:
Warning S: this expression should have type unit.
val bitstr : int -> string list -> string list = <fun>
# bitstr 3 [];;
- : string list = ["1"; "1"; "1"]
I did not understand what to change, can you help me?
Best regards
Philipp
begin foo; bar end executes foo and throws the result away, then it executes bar. Since this makes only sense if foo has side-effects and no meaningful return value ocaml emits a warning if foo has a return value other than unit, since everything else is likely to be a programmer error (i.e. the programmer does not actually intend for the result to be discarded) - as is the case here.
In this case it really does make no sense to calculate the list with "0" and then throw it away. Presumably you want to concatenate the two lists instead. You can do this using the # operator:
let rec bitstr length list =
if length = 0 then
[list]
else
bitstr (length-1)("0"::list) # bitstr (length-1)("1"::list);;
Note that I also made the length = 0 case return [list] instead of just list so the result is a list of lists instead of a flat list.
Although sepp2k's answer is spot on, I would like to add the following alternative (which doesn't match the signature you proposed, but actually does what you want) :
let rec bitstr = function
0 -> [[]]
| n -> let f e = List.map (fun x -> e :: x) and l = bitstr (n-1) in
(f "0" l)#(f "1" l);;
The first difference is that you do not need to pass an empty list to call the function bitsr 2 returns [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]. Second, it returns a list of ordered binary values. But more importantly, in my opinion, it is closer to the spirit of ocaml.
I like to get other ideas!
So here it is...
let rec gen_x acc e1 e2 n = match n with
| 0 -> acc
| n -> (
let l = List.map (fun x -> e1 :: x) acc in
let r = List.map (fun x -> e2 :: x) acc in
gen_x (l # r) e1 e2 (n - 1)
);;
let rec gen_string = gen_x [[]] "0" "1"
let rec gen_int = gen_x [[]] 0 1
gen_string 2
gen_int 2
Result:
[["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]
[[0; 0]; [0; 1]; [1; 0]; [1; 1]]