Alternating series using Haskell - list

I am trying to use Haskell to read in a list and perform an alternating series, so starting with the first element adding every other and subtracting every other from the second element. For instance [1, 2, 3, 4] would be 1-2+3-4=-2. I thought I had figured out how to do this for lists of a specific length (I wrote it to accommodate empty lists and lists up to 4 elements long), but it doesn't do what I thought it would. It just returns the first element from the list. Here is what I have:
altSeries :: Num a => [a] -> a
altSeries [] = 0
altSeries (x:xs) = if length xs == 1 then x
else if length xs == 2 then x
else if length xs == 3 then (x - xs!!1 + xs!!2)
else (x - xs!!1 + xs!!2 - xs!!3)
Also, what if I wanted to be able to use any list size?

What you want is a list that ultimately looks something like this [1,-2,3,-4] which you could sum.
You can make a list of alternating sign [1,-1]. this can be made infinite using the cycle function. let alternatingSigns = cycle [1,-1]
To transform a list of [1,2,3,4] you can zip the infinite alternating list with your list like this zipWith (*) alternatingSigns input
The whole function would look something like this:
altSeries :: Num a => [a] -> a
altSeries input = let alternatingSigns = cycle [1,-1]
in sum $ zipWith (*) alternatingSigns input

I think it is clear that this solution does not scale: even if you would write up function up to lists with length thousand, it would break from the moment that someone enters a list with thousand and one elements.
List processing usually is done recursively: we process the head (or the first k heads) of a list, and perform recursion on the tail of the list. Furthermore we have a number of basecases (can be one) to terminate recursion.
You already provided a single base case: the empty list:
altSeries [] = 0
In case we enter an empty list, it is clear that we should return 0. Now we might ask what to do in case we obtain a list of length 1: in that case the list has shape [x]. So in that case we should return x, since we should add x, and can not subtract the second number. So we add:
altSeries [x] = x
Now the question is what to do with lists with length two or more. In that case the list has pattern (x1:x2:t) with x1 the first element, x2 the second element, and t the remaining elements. Based on your description we should caculate x1-x2 and add altSeries t:
altSeries (x1:x2:t) = x1 - x2 + altSeries t
This works since altSeries will then recursively extract x3 and x4, so then it will recurse to:
altSeries [x1,x2,x3,x4,x5] = x1 - x2 + altSeries [x3,x4,x5]
= x1 - x2 + x3 - x4 + altSeries [x5]
= x1 - x2 + x3 - x4 + x5
So the full implementation is:
altSeries :: Num n => [n] -> n
altSeries [] = 0
altSeries [x] = x
altSeries (x1:x2:t) = x1 - x2 + altSeries t

Related

Haskell function that returns a list of elements in a list with more than given amount of occurrences

I tried making a function that as in the title takes 2 arguments, a number that specifies how many times the number must occur and a list that we are working on, I made a function that counts number of appearances of given number in a list and I tried using it in my main function, but I cannot comprehend how the if else and indentations work in Haskell, it's so much harder fixing errors than in other languages, i think that I'm missing else statement but even so I don't know that to put in there
count el list = count el list 0
where count el list output
| list==[] = output
| head(list)==el = count el (tail(list)) output+1
| otherwise = count el (tail(list)) output
moreThan :: Eq a => Int -> [a] -> [a]
moreThan a [] = []
moreThan a list = moreThan a list output i
where moreThan a list [] 0
if i == length (list)
then output
else if elem (list!!i) output
then moreThan a list output i+1
else if (count (list!!i) list) >= a
then moreThan a list (output ++ [list!!i]) i+1
All I get right now is
parse error (possibly incorrect indentation or mismatched brackets)
You just forgot the = sign and some brackets, and the final else case. But also you switched the order of the internal function declaration and call:
moreThan :: Eq a => Int -> [a] -> [a]
moreThan a [] = []
moreThan a list = go a list [] 0 -- call
where go a list output i = -- declaration =
if i == length (list)
then output
else if elem (list!!i) output
then go a list output (i+1) -- (i+1) !
else if (count (list!!i) list) >= a
then go a list (output ++ [list!!i]) (i+1) -- (i+1) !
else
undefined
I did rename your internal function as go, as is the custom.
As to how to go about fixing errors in general, just read the error messages, slowly, and carefully -- they usually say what went wrong and where.
That takes care of the syntax issues that you asked about.
As to what to put in the missing else clause, you've just dealt with this issue in the line above it -- you include the ith element in the output if its count in the list is greater than or equal to the given parameter, a. What to do else, we say in the else clause.
And that is, most probably, to not include that element in the output:
then go a list (output ++ [list!!i]) (i+1)
else ---------------------
undefined
So, just keep the output as it is, there, instead of the outlined part, and put that line instead of the undefined.
More importantly, accessing list elements via an index is an anti-pattern, it is much better to "slide along" by taking a tail at each recursive step, and always deal with the head element only, like you do in your count code (but preferably using the pattern matching, not those functions directly). That way our code becomes linear instead of quadratic as it is now.
Will Ness's answer is correct. I just wanted to offer some general advice for Haskell and some tips for improving your code.
First, I would always avoid using guards. The syntax is quite inconsistent with Haskell's usual fare, and guards aren't composable in the same way that other Haskell syntax is. If I were you, I'd stick to using let, if/then/else, and pattern matching.
Secondly, an if statement in Haskell is very often not the right answer. In many cases, it's better to avoid using if statements entirely (or at least as much as possible). For example, a more readable version of count would look like this:
count el list = go list 0 where
go [] output = output
go (x:xs) output = go xs (if x == el
then 1 + output
else output)
However, this code is still flawed because it is not properly strict in output. For example, consider the evaluation of the expression count 1 [1, 1, 1, 1], which proceeds as follows:
count 1 [1, 1, 1, 1]
go [1, 1, 1, 1] 0
go [1, 1, 1] (1 + 0)
go [1, 1] (1 + (1 + 0))
go [1] (1 + (1 + (1 + 0)))
go [] (1 + (1 + (1 + (1 + 0))))
(1 + (1 + (1 + (1 + 0))))
(1 + (1 + 2))
(1 + 3)
4
Notice the ballooning space usage of this evaluation. We need to force go to make sure output is evaluated before it makes a recursive call. We can do this using seq. The expression seq a b is evaluated as follows: first, a is partially evaluated. Then, seq a b evaluates to b. For the case of numbers, "partially evaluated" is the same as being totally evaluated.
So the code should in fact be
count el list = go list 0 where
go [] output = output
go (x:xs) output =
let new_output = if x == el
then 1 + output
else output
in seq new_output (go xs new_output)
Using this definition, we can again trace the execution:
go [1, 1, 1, 1] 0
go [1, 1, 1] 1
go [1, 1] 2
go [1] 3
go [] 4
4
which is a more efficient way to evaluate the expression. Without using library functions, this is basically as good as it gets for writing the count function.
But we're actually using a very common pattern - a pattern so common, there is a higher-order function named for it. We're using foldl' (which must be imported from Data.List using the statement import Data.List (foldl')). This function has the following definition:
foldl' :: (b -> a -> b) -> b -> [a] -> b
foldl' f = go where
go output [] = output
go output (x:xs) =
let new_output = f output x
in seq new_output (go new_output xs)
So we can further rewrite our count function as
count el list = foldl' f 0 list where
f output x = if x == el
then 1 + output
else output
This is good, but we can actually improve even further on this code by breaking up the count step into two parts.
count el list should be the number of times el occurs in list. We can break this computation up into two conceptual steps. First, construct the list list', which consists of all the elements in list which are equal to el. Then, compute the length of list'.
In code:
count el list = length (filter (el ==) list)
This is, in my view, the most readable version yet. And it is also just as efficient as the foldl' version of count because of laziness. Here, Haskell's length function takes care of finding the optimal way to do the counting part of count, while the filter (el ==) takes care of the part of the loop where we check whether to increment output. In general, if you're iterating over a list and have an if P x statement, you can very often replace this with a call to filter P.
We can rewrite this one more time in "point-free style" as
count el = length . filter (el ==)
which is most likely how the function would be written in a library. . refers to function composition. The meaning of this is as follows:
To apply the function count el to a list, we first filter the list to keep only the elements which el ==, and then take the length.
Incidentally, the filter function is exactly what we need to write moreThan compactly:
moreThan a list = filter occursOften list where
occursOften x = count x list >= a
Moral of the story: use higher-order functions whenever possible.
Whenever you solve a list problem in Haskell, the first tool you should reach for is functions defined in Data.List, especially map, foldl'/foldr, filter, and concatMap. Most list problems come down to map/fold/filter. These should be your go-to replacement for loops. If you're replacing a nested loop, you should use concatMap.
in a functional way, ;)
moreThan n xs = nub $ concat [ x | x <- ( group(sort(xs))), length x > n ]
... or in a fancy way, lol
moreThan n xs = map head [ x | x <- ( group(sort(xs))), length x > n ]
...
mt1 n xs = [ head x | x <- ( group(sort(xs))), length x > n ]

(sml) I want to count the number of corresponding values in the list

I would like to know the number of cases in which 1 dollar can be expressed in 1,5,10,20,50 cents.
For example, the count(100,[50,25]) is:
Because 50 * 1 + 25 * 2, it = 3:int is printed.
However, in my code, only the front part of the list is printed, so even if I count (100,[50,25]), it = 2:int is printed.
In other words, My code is not taking advantage of the whole list.
How do I solve this?
SML coin count function:
fun count(x,[]) = 0
| count (x,y::ys) =
let val cnt = 0
in if y*2 = x then cnt+2
else if y*4 = x then cnt + 4
else if y*10 = x then cnt + 10
else if y*10 = x then cnt + 10
else if y*20 = x then cnt + 20
else count(x-y,ys)
end;
Consider what happens as you evaluate your test expression of count (100, [50, 25]).
cnt is 0, y is 50, and ys is [25].
y times 2 does equal 100, so it returns cnt+2 which is 2. Nothing further happens.
When it comes to recursion, remember than the parameter list to a function is your means of communication. It seems like cnt is something that should be passed as a parameter so you can update it between recursive calls.
With count(x, []) = 0 you already have an exit point that will stop the recursion.
Edit: Based on comments, it looks like you're trying to figure out how many times each value in a list goes into a value x.
So the end result of your recursive function isn't a single integer. It's a list of integers. Or better yet, of tuples containing the value to look for, and the number of times it goes into x.
So if the list is empty, the result is obvious.
fun count(x, []) = []
It's an empty list. Otherwise, we need to append something onto a list.
fun count(x, []) = []
| count(x, y::ys) =
(y, x div y) :: count(x, ys)
Of course, we also have functions like map that basically do this for us.
fun count(x, lst) = List.map (fn y => (y, x div y)) lst

Smallest sub-list that contains all numbers

I am trying to write a program in sml that takes in the length of a list, the max number that will appear on the list and the list of course. It then calculates the length of the smallest "sub-list" that contains all numbers.
I have tried to use the sliding window approach , with two indexes , front and tail. The front scans first and when it finds a number it writes into a map how many times it has already seen this number. If the program finds all numbers then it calls the tail. The tail scans the list and if it finds that a number has been seen more times than 1 it takes it off.
The code I have tried so far is the following:
structure Key=
struct
type ord_key=int
val compare=Int.compare
end
fun min x y = if x>y then y else x;
structure mymap = BinaryMapFn ( Key );
fun smallest_sub(n,t,listall,map)=
let
val k=0
val front=0
val tail=0
val minimum= n;
val list1=listall;
val list2=listall;
fun increase(list1,front,k,ourmap)=
let
val number= hd list1
val elem=mymap.find(ourmap,number)
val per=getOpt(elem,0)+1
fun decrease(list2,tail,k,ourmap,minimum)=
let
val number=hd list2
val elem=mymap.find(ourmap,number)
val per=getOpt(elem,0)-1
val per1=getOpt(elem,0)
in
if k>t then
if (per1=1) then decrease(tl list2,tail+1,k-1,mymap.insert(ourmap,number,per),min minimum (front-tail))
else decrease(tl list2,tail+1,k,mymap.insert(ourmap,number,per),min minimum (front-tail))
else increase (list1, front,k,ourmap)
end
in
if t>k then
if (elem<>NONE) then increase (tl list1,front+1,k,mymap.insert(ourmap,number,per))
else increase(tl list1,front+1,k+1,mymap.insert(ourmap,number,per))
else (if (n>front) then decrease(list2,tail,k,ourmap,minimum) else minimum)
end
in
increase(list1,front,k,map)
end
fun solve (n,t,acc)= smallest_sub(n,t,acc,mymap.empty)
But when I call it with this smallest_sub(10,3,[1,3,1,3,1,3,3,2,2,1]); it does not work. What have I done wrong??
Example: if input is 1,3,1,3,1,3,3,2,2,1 the program should recognize that the parto of the list that contains all numbers and is the smallest is 1,3,3,2 and 3,2,2,1 so the output should be 4
This problem of "smallest sub-list that contains all values" seems to recur in
new questions without a successful answer. This is because it's not a minimal,
complete, and verifiable example.
Because you use a "sliding window" approach, indexing the front and the back
of your input, a list taking O(n) time to index elements is not ideal. You
really do want to use arrays here. If your input function must have a list, you
can convert it to an array for the purpose of the algorithm.
I'd like to perform a cleanup of the code before answering, because running
your current code by hand is a bit hard because it's so condensed. Here's an
example of how you could abstract out the book-keeping of whether a given
sub-list contains at least one copy of each element in the original list:
Edit: I changed the code below after originally posting it.
structure CountMap = struct
structure IntMap = BinaryMapFn(struct
type ord_key = int
val compare = Int.compare
end)
fun count (m, x) =
Option.getOpt (IntMap.find (m, x), 0)
fun increment (m, x) =
IntMap.insert (m, x, count (m, x) + 1)
fun decrement (m, x) =
let val c' = count (m, x)
in if c' <= 1
then NONE
else SOME (IntMap.insert (m, x, c' - 1))
end
fun flip f (x, y) = f (y, x)
val fromList = List.foldl (flip increment) IntMap.empty
end
That is, a CountMap is an int IntMap.map where the Int represents the
fixed key type of the map, being int, and the int parameter in front of it
represents the value type of the map, being a count of how many times this
value occurred.
When building the initialCountMap below, you use CountMap.increment, and
when you use the "sliding window" approach, you use CountMap.decrement to
produce a new countMap that you can test on recursively.
If you decrement the occurrence below 1, you're looking at a sub-list that
doesn't contain every element at least once; we rule out any solution by
letting CountMap.decrement return NONE.
With all of this machinery abstracted out, the algorithm itself becomes much
easier to express. First, I'd like to convert the list to an array so that
indexing becomes O(1), because we'll be doing a lot of indexing.
fun smallest_sublist_length [] = 0
| smallest_sublist_length (xs : int list) =
let val arr = Array.fromList xs
val initialCountMap = CountMap.fromList xs
fun go countMap i j =
let val xi = Array.sub (arr, i)
val xj = Array.sub (arr, j)
val decrementLeft = CountMap.decrement (countMap, xi)
val decrementRight = CountMap.decrement (countMap, xj)
in
case (decrementLeft, decrementRight) of
(SOME leftCountMap, SOME rightCountMap) =>
Int.min (
go leftCountMap (i+1) j,
go rightCountMap i (j-1)
)
| (SOME leftCountMap, NONE) => go leftCountMap (i+1) j
| (NONE, SOME rightCountMap) => go rightCountMap i (j-1)
| (NONE, NONE) => j - i + 1
end
in
go initialCountMap 0 (Array.length arr - 1)
end
This appears to work, but...
Doing Int.min (go left..., go right...) incurs a cost of O(n^2) stack
memory (in the case where you cannot rule out either being optimal). This is a
good use-case for dynamic programming because your recursive sub-problems have a
common sub-structure, i.e.
go initialCountMap 0 10
|- go leftCountMap 1 10
| |- ...
| `- go rightCountMap 1 9 <-.
`- go rightCountMap 0 9 | possibly same sub-problem!
|- go leftCountMap 1 9 <-'
`- ...
So maybe there's a way to store the recursive sub-problem in a memory array and not
perform a recursive lookup if you know the result to this sub-problem. How to
do memoization in SML is a good question in and of itself. How to do purely
functional memoization in a non-lazy language is an even better one.
Another optimization you could make is that if you ever find a sub-list the
size of the number of unique elements, you need to look no further. This number
is incidentally the number of elements in initialCountMap, and IntMap
probably has a function for finding it.

Return the element just before the occurrence of another element in haskell

I want to write a code in Haskell, to return an element just before the occurrence of another element in a list. For ex:
eBefore 3 [1,2,3,4,5] should return 2
I am quiet new to haskell. The code that i've written up till now is :
eBefore :: Eq a => a -> [a] -> Maybe a
eBefore n [] = Nothing
eBefore n (x:xs) = if x == n then Just x else eBefore n xs
I would be highly obliged if some one could help me understand the approach or help me out with the problem. Thank you!
You can match more elaborated patterns:
eBefore n [] = Nothing
eBefore n [_] = Nothing
eBefore n (x1:xs#(x2:_))
| x2 == n = Just x1
| otherwise = eBefore n xs
Here we return Nothing for lists containing zero or one elements because they contain no member with another one preceding them. (x1:xs#(x2:_)) is a pattern that matches a x1:xs, where xs in turn matches x2:_, that is, a list with at least two elements, the first element is bound to x1, the second to x2, the residue is unimportant (matched by _).
We also might write thus:
eBefore n [] = Nothing
eBefore n [_] = Nothing
eBefore n (x1:x2:xs)
| x2 == n = Just x1
| otherwise = eBefore n (x2:xs)
However, this variant might be worse in terms of performance. (x1:x2:xs) is equivalent to (x1:(x2:xs)), and we see that (x2:xs) repeated again as an argument to recursive call. But the compiler may fail to recognize the identity of the two expressions and create a new node. That's a waste. By using the #-notation in the former variant, we give that (x2:_) from the pattern a name, xs, and pass it to the recursive call as a ready whole.
The difficult moment here is what we should return in case n is equal to the head of the list, e. g. eBefore 3 [3,4,5,6,3]. The definition above will skip the first occurrence of 3 and return 6.

Haskell, list of natural number

I am an absolute newbie in Haskell yet trying to understand how it works.
I want to write my own lazy list of integers such as [1,2,3,4,5...].
For list of ones I have written
ones = 1 : ones
and when tried, works fine:
*Main> take 10 ones
[1,1,1,1,1,1,1,1,1,1]
How can I do the same for increasing integers ?
I have tried this but it indeed fails:
int = 1 : head[ int + 1]
And after that how can I make a method that multiplies two streams? such as:
mulstream s1 s2 = head[s1] * head[s2] : mulstream [tail s1] [tail s2]
The reasons that int = 1 : head [ int + 1] doesn't work are:
head returns a single element, but the second argument to : needs to be a list.
int + 1 tries to add a list and a number, which isn't possible.
The easiest way to create the list counting up from 1 to infinity is [1..]
To count in steps other than 1 you can use [firstElement, secondElement ..], e.g. to create a list of all positive odd integers: [1, 3 ..]
To get infinite lists of the form [x, f x, f (f x), f (f (f x)),...] you can use iterate f x, e.g. iterate (*2) 1 will return the list [1, 2, 4, 16,...].
To apply an operation pairwise on each pair of elements of two list, use zipWith:
mulstream s1 s2 = zipWith (*) s1 s2
To make this definition more concise you can use the point-free form:
mulstream = zipWith (*)
For natural numbers you have to use map:
num1 = 1 : map (+1) num1
Or comprehensions:
num2 = 1 : [x+1 | x <- num2]
Or of course:
num3 = [1..]
There is syntax for this in the langauge:
take 10 [1,2..]
=> [1,2,3,4,5,6,7,8,9,10]
You can even do different strides:
take 10 [1,3..]
=> [1,3,5,7,9,11,13,15,17,19]
I'm not sure if this is what you were asking, but it would seem to me that you wanted to build a list of increasing natural numbers, without relying on any other list. So, by that token, you can do things like
incr a = a : inrc (a+1)
lst = inrc 1
take 3 lst
=> [1,2,3]
That, technically, is called an accumulating function (I believe) and then all we did is make a special case of it easily usable with 'lst'
You can go mad from there, doing things like:
lst = 1 : incr lst where incr a = (head a) + 1 : incr (tail a)
take 3 lst
=> [1,2,3]
and so on, though that probably relies on some stuff that you wont have learned yet (where) - judging by the OP - but it should still read pretty easily.
Oh, right, and then the list multiplication. Well, you can use zipWith (*) as mentioned above, or you could reinvent the wheel like this (it's more fun, trust me :)
lmul a b = (head a * head b) : lmul (tail a) (tail b)
safemul a b
| null a || null b = []
| otherwise
= (head a * head b) : safemul (tail a) (tail b)
The reason for safemul, I believe, you can find out by experimenting with the function lmul, but it has to do with 'tail' (and 'head' as well). The trouble is, there's no case for an empty list, mismatched lists, and so on in lmul, so you're either going to have to hack together various definitions (lmul _ [] = []) or use guards and or where and so on ... or stick with zipWith :)
You can define a list of ones up to a certain number and then sum the first to the second by keeping the former intact (and so on) like this:
ones :: Integer -> [Integer]
ones n
| n <= 0 = []
| otherwise = one n []
where
one 1 a = (1:a)
one n a = one (n-k) (one k a)
where
k = (n-1)
sumOf :: [Integer] -> [Integer]
sumOf l = sof l []
where
sof [] a = a
sof (x:[]) a = (x:a)
sof (x:y:zs) a = sof (x:a) (sof ((x+y):zs) a)
Since they're all ones, you can increment them in any way that you feel like, from left to right, to a middle point and so on, by changing the order of their sum. You can test this up to one hundred (or more) by using:
(sumOf . ones) 100
Edit: for its simplification, read the comments below by Will Ness.