f# sum after last negative number - list

Hello i have to make exercise with list. I had one with checking arithmetic with lists code :
let rec q3 lista r =
match lista with
| [] -> false
| [x] -> true
| x1::x2::xs -> if r = x2 - x1 then (q3 xs r) else false
q3 [2;4;6] 2;;
But after this excersize i have problem. I have to calculate sum for numbers in list after last negative number
or for all if i have only positive numbers in my list.
this is code for sum . This is pretty easy but how do make this :( I am quite new in f# programming :P Any reflections ?
I have list for exmaple like this :
let lists = [4;-3;1;9]
// sum =10
//calculate
let rec sum values =
match values with
| [] -> 0
| head::tail -> head + sum(tail)
//test
let x = sum lists

I guess that you're learning F# and so I'm not going to show the full answer (then you wouldn't learn much).
You want to sum all numbers in a list after the last negative number. Another way to look at this is that you want to restart the counting (to start from zero again) every time you find a negative number as you are walking over the list.
This is not easy to do with your version of sum, but you can rewrite the sum function to use the accumulator argument (which keeps the sum of numbers so far):
let rec sumAcc acc values =
match values with
| [] ->
// return the sum of values in the list so far
| head::tail ->
// add the value in the 'head' to the sum so far
// and call 'sumAcc' recursively on the rest of the list
let sum values = sumAcc 0 values
Now, you can solve the problem quite easily - because when head is negative, you can just reset the "sum so far" in the accumulator argument. So, you just need to add another case looking like:
| head::tail when head < 0 ->
// Ignore the sum so far and call 'sumAcc' on the rest of the list

let rec sumList acc lst =
match lst with
| [] -> acc
| hd::tl -> hd + sumList acc tl
|hd::tl when hd < 0 -> sumList acc lst
let sum lst = sumList 0 lst ;;
sum [1;2;-5] ;;
Dont know how to do this //'sumAcc' recursively on the rest of the list
sumList acc lst is rather wrong :D because still get -2 value :D

Related

Outputting first n elements in the list

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.

F# Recursive function for adding even list elements

I have a problem, namely, I would like to turn the following code into a recursive function for adding even list elements, but unfortunately I do not know how much ...
let even = List.filter(fun x -> x%2=0)[1..100]
let sum = List.length even
printfn "Even: %A sum: %d " even sum
Thank you for any help!
You can use pattern matching to check if the first element in your list is even,
and if so, to add it into accumulator list and call the same method on the rest of the list. In case the element is odd - just call the same method for the rest of the list without adding anything to accumulator. When list is empty - return the accumulator and you will have list of just even numbers.
let rec getEven (input : int list) (acc: int list) =
match input with
| head :: tail when head % 2 = 0 -> (getEven tail (head :: acc))
| head :: tail when head % 2 = 1 -> (getEven tail (acc))
| _ -> acc
let even = getEven [1..10] []
let sum = List.sum even
Function above will produce:
val getEven : input:int list -> acc:int list -> int list
val even : int list = [10; 8; 6; 4; 2]
val sum : int = 30
P.S. to calculate sum of the elements, you should use List.sum instead of List.length that will return you the number of elements in list.
Also note, that you can calculate sum of even elements in getEven function, storing not the list of even elements, but their sum.

OCaml - How do I return list of lists from a list?

I have a following problem. From a list, I must separate mod 3 = 0 element, mod 3 = 1 element and mod 3 = 2 element to 3 different lists and return list of these 3 lists. My question is pretty obvious - how do I do that? Is there some kind of simple rule to this I'm missing?
What I have so far is not much but there you go:
let separate xs =
let rec help xs i =
match xs i with
| [] _ -> []
| hd a -> if a mod 3 = 0 //HOW DO I RETURN
else if a mod 3 = 1
else
UPDATED:
Finished code:
let separate xs =
let rec help (list, i, xs1, xs2, xs3) =
match list with
| [] -> [xs1;xs2;xs3]
| head :: tail -> (if i mod 3 = 0 then help (tail, i+1, head::xs1, xs2, xs3)
else if i mod 3 = 1 then help (tail, i+1, xs1, head::xs2, xs3)
else help (tail, i+1, xs1, xs2, head::xs3))
in help (xs, 0, [], [], []);;
You'll need to accumulate the partial results in lists, and then return those lists :
let split_by_mod_3 l =
let rec aux l mod0 mod1 mod2 = match l with
| [] -> [mod0; mod1; mod2]
| hd::tail when hd mod 3 == 0 -> aux tail (hd::mod0) mod1 mod2
| hd::tail when hd mod 3 == 1 -> aux tail mod0 (hd::mod1) mod2
| hd::tail when hd mod 3 == 2 -> aux tail mod0 mod1 (hd::mod2)
in
aux l [] [] [];;
A usual way is to use List.fold* function, that generalizes an idea of list iteration. But, in your case, it may not be appropriate (depending on what your teachers are asking).
You can iterate over your list maintaining some notion of state (indeed, you need three extra "variables" for three different lists). Here is a pattern for iterating over lists
let my_function lst =
let rec loop acc lst = match lst with
| [] -> <do_some_post_iteration_work> acc
| head :: rest ->
let result = <do_something_with_nth_element> head in
let accum = <add_result_to_accumulator> result acc in
loop accum rest in
let accum = <initialize_accumulator> in
loop accum lst
I used long names so that you can understand the meaning without extra comments, although you're welcome to ask. Also, keep in mind, that your state (aka accumulator), can be also a value of any type. Using a triple would be a not a bad idea in your case.

OCaml. Return first n elements of a list

I am new to OCaml and functional programming as a whole. I am working on a part of an assignment where I must simply return the first n elements of a list. I am not allowed to use List.Length.
I feel that what I have written is probably overly complicated for what I'm trying to accomplish. What my code attempts to do is concatenate the front of the list to the end until n is decremented to 1. At which point the head moves a further n-1 spots to that the tail of the list and then return the tail. Again, I realize that there is probably a much simpler way to do this, but I am stumped and probably showing my inability to grasp functional programming.
let rec take n l =
let stopNum = 0 - (n - 1) in
let rec subList n lst =
match lst with
| hd::tl -> if n = stopNum then (tl)
else if (0 - n) = 0 then (subList (n - 1 ) tl )
else subList (n - 1) (tl # [hd])
| [] -> [] ;;
My compiler tells me that I have a syntax error on the last line. I get the same result regardless of whether "| [] -> []" is the last line or the one above it. The syntax error does not exist when I take out the nested subList let. Clearly there is something about nested lets that I am just not understanding.
Thanks.
let rec firstk k xs = match xs with
| [] -> failwith "firstk"
| x::xs -> if k=1 then [x] else x::firstk (k-1) xs;;
You might have been looking for this one.
What you have to do here, is to iterate on your initial list l and then add elements of this list in an accumulator until n is 0.
let take n l =
let rec sub_list n accu l =
match l with
| [] -> accu (* here the list is now empty, return the partial result *)
| hd :: tl ->
if n = 0 then accu (* if you reach your limit, return your result *)
else (* make the call to the recursive sub_list function:
- decrement n,
- add hd to the accumulator,
- call with the rest of the list (tl)*)
in
sub_list n [] l
Since you're just starting with FP, I suggest you look for the simplest and most elegant solution. What you're looking for is a way to solve the problem for n by building it up from a solution for a smaller problem.
So the key question is: how could you produce the first n elements of your list if you already had a function that could produce the first (n - 1) elements of a list?
Then you need to solve the "base" cases, the cases that are so simple that the answer is obvious. For this problem I'd say there are two base cases: when n is 0, the answer is obvious; when the list is empty, the answer is obvious.
If you work this through you get a fairly elegant definition.

Split list into two equal lists in F#

I'm really new to F#, and I need a bit of help with an F# problem.
I need to implement a cut function that splits a list in half so that the output would be...
cut [1;2;3;4;5;6];;
val it : int list * int list = ([1; 2; 3], [4; 5; 6])
I can assume that the length of the list is even.
I'm also expected to define an auxiliary function gencut(n, xs) that cuts xs into two pieces, where n gives the size of the first piece:
gencut(2, [1;3;4;2;7;0;9]);;
val it : int list * int list = ([1; 3], [4; 2; 7; 0; 9])
I wouldn't normally ask for exercise help here, but I'm really at a loss as to where to even start. Any help, even if it's just a nudge in the right direction, would help.
Thanks!
Since your list has an even length, and you're cutting it cleanly in half, I recommend the following (psuedocode first):
Start with two pointers: slow and fast.
slow steps through the list one element at a time, fast steps two elements at a time.
slow adds each element to an accumulator variable, while fast moves foward.
When the fast pointer reaches the end of the list, the slow pointer will have only stepped half the number of elements, so its in the middle of the array.
Return the elements slow stepped over + the elements remaining. This should be two lists cut neatly in half.
The process above requires one traversal over the list and runs in O(n) time.
Since this is homework, I won't give a complete answer, but just to get you partway started, here's what it takes to cut the list cleanly in half:
let cut l =
let rec cut = function
| xs, ([] | [_]) -> xs
| [], _ -> []
| x::xs, y::y'::ys -> cut (xs, ys)
cut (l, l)
Note x::xs steps 1 element, y::y'::ys steps two.
This function returns the second half of the list. It is very easy to modify it so it returns the first half of the list as well.
You are looking for list slicing in F#. There was a great answer by #Juliet in this SO Thread: Slice like functionality from a List in F#
Basically it comes down to - this is not built in since there is no constant time index access in F# lists, but you can work around this as detailed. Her approach applied to your problem would yield a (not so efficient but working) solution:
let gencut(n, list) =
let firstList = list |> Seq.take n |> Seq.toList
let secondList = list |> Seq.skip n |> Seq.toList
(firstList, secondList)
(I didn't like my previous answer so I deleted it)
The first place to start when attacking list problems is to look at the List module which is filled with higher order functions which generalize many common problems and can give you succinct solutions. If you can't find anything suitable there, then you can look at the Seq module for solutions like #BrokenGlass demonstrated (but you can run into performance issues there). Next you'll want to consider recursion and pattern matching. There are two kinds of recursion you'll have to consider when processing lists: tail and non-tail. There are trade-offs. Tail-recursive solutions involve using an accumulator to pass state around, allowing you to place the recursive call in the tail position and avoid stack-overflows with large lists. But then you'll typically end up with a reversed list! For example,
Tail-recursive gencut solution:
let gencutTailRecursive n input =
let rec gencut cur acc = function
| hd::tl when cur < n ->
gencut (cur+1) (hd::acc) tl
| rest -> (List.rev acc), rest //need to reverse accumulator!
gencut 0 [] input
Non-tail-recursive gencut solution:
let gencutNonTailRecursive n input =
let rec gencut cur = function
| hd::tl when cur < n ->
let x, y = gencut (cur+1) tl //stackoverflow with big lists!
hd::x, y
| rest -> [], rest
gencut 0 input
Once you have your gencut solution, it's really easy to define cut:
let cut input = gencut ((List.length input)/2) input
Here's yet another way to do it using inbuilt library functions, which may or may not be easier to understand than some of the other answers. This solution also only requires one traversal across the input. My first thought after I looked at your problem was that you want something along the lines of List.partition, which splits a list into two lists based on a given predicate. However, in your case this predicate would be based on the index of the current element, which partition cannot handle, short of looking up the index for each element.
We can accomplish creating our own equivalent of this behavior using a fold or foldBack. I will use foldBack here as it means you won't have to reverse the lists afterward (see Stephens excellent answer). What we are going to do here is use the fold to provide our own index, along with the two output lists, all as the accumulator. Here is the generic function that will split your list into two lists based on n index:
let gencut n input =
//calculate the length of the list first so we can work out the index
let inputLength = input |> List.length
let results =
List.foldBack( fun elem acc->
let a,b,index = acc //decompose accumulator
if (inputLength - index) <= n then (elem::a,b,index+1)
else (a,elem::b,index+1) ) input ([],[],0)
let a,b,c = results
(a,b) //dump the index, leaving the two lists as output.
So here you see we start the foldBack with an initial accumulator value of ([],[],0). However, because we are starting at the end of the list, the 0 representing the current index needs to be subtracted from the total length of the list to get the actual index of the current element.
Then we simply check if the current index falls within the range of n. If it does, we update the accumulator by adding the current element to list a, leave list b alone, and increase the index by 1 : (elem::a,b,index+1). In all other cases, we do exactly the same but add the element to list b instead: (a,elem::b,index+1).
Now you can easily create your function that splits a list in half by creating another function over this one like so:
let cut input =
let half = (input |> List.length) / 2
input |> gencut half
I hope that can help you somewhat!
> cut data;;
val it : int list * int list = ([1; 2; 3], [4; 5; 6])
> gencut 5 data;;
val it : int list * int list = ([1; 2; 3; 4; 5], [6])
EDIT: you could avoid the index negation by supplying the length as the initial accumulator value and negating it on each cycle instead of increasing it - probably simpler that way :)
let gencut n input =
let results =
List.foldBack( fun elem acc->
let a,b,index = acc //decompose accumulator
if index <= n then (elem::a,b,index-1)
else (a,elem::b,index-1) ) input ([],[],List.length input)
let a,b,c = results
(a,b) //dump the index, leaving the two lists as output.
I have the same Homework, this was my solution. I'm just a student and new in F#
let rec gencut(n, listb) =
let rec cut n (lista : int list) (listb : int list) =
match (n , listb ) with
| 0, _ -> lista, listb
| _, [] -> lista, listb
| _, b :: listb -> cut (n - 1) (List.rev (b :: lista )) listb
cut n [] listb
let cut xs = gencut((List.length xs) / 2, xs)
Probably is not the best recursive solution, but it works. I think
You can use List.nth for random access and list comprehensions to generate a helper function:
let Sublist x y data = [ for z in x..(y - 1) -> List.nth data z ]
This will return items [x..y] from data. Using this you can easily generate gencut and cut functions (remember to check bounds on x and y) :)
check this one out:
let gencut s xs =
([for i in 0 .. s - 1 -> List.nth xs i], [for i in s .. (List.length xs) - 1 -> List.nth xs i])
the you just call
let cut xs =
gencut ((List.length xs) / 2) xs
with n durationn only one iteration split in two