Global Variable “total” Does Not Update Properly - haskell

I'm working on an assignment to calculate the sum of all integers in a list. I am supposed to do so without help from any standard library functions other than the standard addition operator.
I assume this means I cannot use length. I'm understanding that correct, right? This becomes and issue as I'm not sure how I'd know when to stop my recursive function to iterate through the array.
The input's a should be expected to deal with are [] and [0-X] where x is any integer. The example has X as 10, so don't expect anything huge to be tested.
The assignment mentioned it should be in the following format, but I'm not sure I follow:
sum1 [] = ...
sum1 (x:xs) = ...
Here's what I have utilizing length. It works correctly, and I don't really care if it's inefficient. It's my first time using Haskell:
iterate_list :: [Int] -> Int -> Int -> IO()
iterate_list func_list index total = do
if index < length func_list
then do
let new_total = total + (func_list !! index)
let new_index = index + 1
iterate_list func_list new_index new_total
else
print(total)
sum1 :: [Int] -> IO()
sum1 list = do
if length list < 1
then do
print(0)
else
iterate_list list 0 0
update: Based on comments, here is the code I've produced.
total :: Int
total = 0
sum1 :: [Int] -> IO()
sum1 (x:xs) = do
if xs == []
then do
print(total)
else do
let total = total + x
sum1 xs
However, the issue I'm having now is total returns 0, almost like it's a constant. I might be programming it that way, but I'm not too sure what's going on.
Based on the assignment description, I cannot pass a variable through the recursive function to store this value. I've done it that way before. Does anyone know if there is a way to have a "total" variable outside of the function.

total :: Int
total = 0
sum1 :: [Int] -> IO()
sum1 (x:xs) = do
if xs == []
then do
print(total)
else do
let total = total + x
sum1 xs
What this code says:
The global total is a constant integer, equal to 0
sum1 takes a list of integers and produces an IO action that produces no result
If sum1 is given a non-empty list, then:
If the tail of that list is empty (i.e., the whole list has 1 element), then print the global variable total
Otherwise:
Create a new local variable named total, hiding the global one, and define it as x plus itself (an infinite loop)
Recursively call sum1 on the tail of the list
If sum1 is given an empty list, it will throw an error
This shows that you’re thinking very imperatively. Rather than trying to define a bottom-up procedure for updating the total incrementally until it builds up to the final result, you need to think in terms of how to compute the total as a value by breaking down the input. Variables in Haskell are immutable; when you write =, it means equal, never “assign” or “update”.
First, sum1 should return Int because you don’t need IO or do notation for this.
sum1 :: [Int] -> Int
If you want to print the result of sum1 applied to some list someList (for example from main), use print there, i.e., print (sum1 someList).
Next, the function should be defined in terms of the the two possible cases of the input: an empty list and a non-empty list.
sum1 [] = …
sum1 (x : xs) = …
You need to define these cases so that an input like sum1 [1, 2, 3, 4], which you’ll recall is syntactic sugar for sum1 (1 : (2 : (3 : (4 : [])))) produces something equivalent to 1 + 2 + 3 + 4.
First, in the case of an empty list, what should the result be? You can deduce this from the fact that the sum of two lists appended together should be the same as the sum of each of them separately; that is, for any lists xs and ys, these expressions should produce the same result:
sum1 xs + sum1 ys
sum1 (xs ++ ys)
Supposing xs or ys is empty, it should not change the sum:
sum1 [] + sum1 ys = sum1 ([] ++ ys) = sum1 ys
sum1 xs + sum1 [] = sum1 (xs ++ []) = sum1 xs
Second, as for the non-empty case: you’re given an element x :: Int and a list xs :: [Int], and you need to compute the total of the two. For example, given [1, 2, 3, 4], x is set to 1 and xs is [2, 3, 4]. Suppose you had the sum of xs already; what is the result in terms of that and x? And how can you obtain the sum of xs?

You cannot simply update a variable in Haskell. All values are immutable. You should be thinking in terms of how to use the return value of a recursive call, not simply calling a function for its side effect.
The hint from your original question was to define
sum [] = ...
sum (x:xs) = ...
First, what is the sum of the non-empty list? It must include x, so you'll be adding something to x:
sum (x:xs) = x + ...
Second, what is the sum of an empty list? While it might not make sense to even define a value for an empty list, think about what sum [3] must surely return, and the fact that sum (3:[]) == 3 + .... There's a rather simple definition for sum [] that is almost dictated by the definition of addition.

Related

Haskell find divisors based on comprehension method

I need a little help understanding a comprehension method function.
compdivides :: Integer -> [Integer]
compdivides x
| x > 0 = [a | a <-[1..div x 2], mod x a == 0] ++ [x]
| otherwise = compdivides (abs x)
I understand that if x is positive we do the 3rd line otherwise the 4th line.
In the third line we check whether mod x a == 0 only then do we do everything else.
However, I cannot seem to understand this part a <-[1..div x 2] What exactly happens here?
Also, why do we do this at the end ++ [x] ? What exactly are we doing here anyways?
itemTotal :: [(String, Float)] -> [(String, Float)]
itemTotal [] = []
itemTotal [x] = [x]
I am having some trouble with this as well.
I understand that if the list is empty we simply return an empty list.
However, what are we saying here? itemTotal [x] = [x] That if the list only has one thing we simply return that one thing?
Thank you so much for the help!
However, I cannot seem to understand this part a <-[1..div x 2] What exactly happens here?
This is a generator of the list comprehension. The list comprehension:
[ a | a <- [1 .. div x 2 ], mod x a == 0 ]
will evaluate such that a takes each item in the list (so 1, 2, …, x/2), and in case mod x a == 0 (x is dividable by a), it will add a to the list.
Also, why do we do this at the end ++ [x] ? What exactly are we doing here anyways?
It appends x at the end of the list. This is done because a number x is always dividable by itself (x), since the a <- [1 .. div x 2] stops at div x 2, it will never check if x divides x.
The function will get stuck in an infinite loop for compdivides 0, so you might want to rewrite the function to cover this case as well.
However, what are we saying here? itemTotal [x] = [x] That if the list only has one thing we simply return that one thing?
Yes. Usually a pattern like itemTotal (x : xs) = x : itemTotal xs is used where we thus return a list where x is the first item, and we recurse on the tail of the list xs.
Your itemTotal function however only makes a copy of the list for the first two clauses. You thus can simply define itemTotal = id. Likely you will need to rewrite the function to determine the total of the items in the list.

Convert binary string to integer value using first order functions

Given a finite list of 0 and 1, how can I convert them to their integer value using first order function?
The head of the list is the least significant digit. For instance, 1011 evaluates to 13.
In this problem, I struggle to find both the recursive step and the base step because all depends wether it's a 0 and 1.
EDIT :
The goal is to define a function that will compute the decimal value given a binary string. An empty list should return 0 I guess, so it would be the base case.
Wrapping up my comments:
convert :: [Int] -> Int
convert [] = 0
convert (x : xs) = x + 2 * convert xs
The base case is the empty list, returning 0.
The recursive case follows from the fact that x is the least significant digit. convert xs (the recursive call) gives us the result for the tail of the list; to get the result of the whole list we need to multiply by 2 (to "shift over" the digits) and add x (0 or 1).
Here's my initial thoughts about how to handle this situation.
import Data.Char (digitToInt)
myFunction :: String -> Int
myFunction = foldr step 0
where step x y = (+) (digitToInt x) ( (*) y 2 )
Assuming the input is a list of 1s and 0s.
bin2num :: [Int] -> Int
bin2num list = go list 0
where go [] _ = 0
go (x:xs) n = (x*(2^n)) + (go xs (n+1))
Just double the acc and add it to the new element of the list . Easily use digitToInt to get the right list from the string _ st here . and foldl' for efficiency. This is Sanaz's answer
fromBin st = foldl' (\x acc -> x * 2 + acc ) 0 (map (digitToInt) st)

Check an array whether sum(x_0, x_1...x_k) == sum(x_k+1,..x_n) are equal in Haskell

I need to implement to an algorithm to solve following problem in Haskell:
Given an array, check whether sum(x_0, x_1...x_k) == sum(x_k+1,...,x_n)
If the array is have NO element, then the sum is zero
1:
arr = [1]
sum([]) = 0
sum([1]) = 1
sum([]) != sum([1])
there is no such k
return False
2:
arr = [1,2,3]
sum([1,2]) == sum([3])
there is such k
return True
Here is my current implementation so far:
checkSum::[Int]->Int->Bool
checkSum [] _ = True
checkSum [x] _ = x == 0
checkSum l inx | sum(take inx l) == sum(drop inx l) = True
| inx <= length l = checkSum l (inx+1)
| otherwise = False
It works, but I need to change function prototype as following:
checkSum::[Int]->Bool
.....
Does anyone know how to implement the new function without passing index to the function?
This function comes up a surprising amount:
import Data.List (inits, tails)
splits :: [a] -> [([a],[a])]
splits xs = zip (inits xs) (tails xs)
Example usage:
ghci> splits [1,2,3]
[([],[1,2,3]),([1],[2,3]),([1,2],[3]),([1,2,3],[])]
You might also be interested in the any function.
I think you can take it from here.
A more primitive approach
checkSum :: [Int] -> Bool
checkSum a = go a 0 (sum a)
where go [] left right = left==right
go (x:xs) left right = left==right || go xs (left+x) (right-x)
at each step you're adding the element to the left value and subtracting from the right, where the initial values are 0 and sum. Terminates when equality reached at any step or when the array is exhausted.
A clever way to think about this: if we need
x[1] + ... + x[k] == x[k+1] + ... + x[n],
then we can add the left-hand side to both sides to get
(x[1] + ... + x[k]) * 2 == sum(x).
Thus, we can generate all doubled prefix sums, then look for sum(x) in them.
checkSum :: [Int] -> Bool
checkSum xs = sum xs `elem` doublePrefixSums
where doublePrefixSums = scanl (\acc x -> acc + 2*x) 0 xs
A solution using built-in functions.
Use scanl and scanr to find all the sums from the left and right.
scanl (+) 0 [1,2,3] gives you [0, 0+1, 0+1+2, 0+1+2+3]
λ> scanl (+) 0 [1,2,3]
[0,1,3,6]
scanr (+) 0 [1,2,3] gives you [1+2+3+0, 2+3+0, 3+0, 0]
λ> scanr (+) 0 [1,2,3]
[6,5,3,0]
Then zipWith to identify positions where the lists have equal elements.
λ> zipWith (==) [0,1,3,6] [6,5,3,0]
[False,False,True,False]
Then or to check if this list contains True anywhere.
λ> or [False,False,True,False]
True
The complete function:
checkSum :: [Int] -> Bool
checkSum xs = or (zipWith (==) leftSums rightSums)
where
leftSums = scanl (+) 0 xs
rightSums = scanr (+) 0 xs
(This will return True on the empty list. This seems reasonable to
me, but if you want it to be False you could write a special case for
it or just change scanr to scanr1.)
My interpretation of the question is: for some Int list x, determine ∃k::Integer. sum[x₀,…,xₖ] == sum[xₖ,…,xₙ]. Reasonably, 0 ≤ k < length x (and n = length x) because otherwise xₖ is ⊥ and we are not interested in that case.
So how would you prove that proposition? Are we interested in infinite lists? Probably not, so let us assume the list is finite. Then, if the list is finite there are also finite choices for k because 0 ≤ k < length x. A proof then can be done by checking for every choice of k. If at least one choice of k satisfies the proposition then it is true, and otherwise it is false.
When translating our method to Haskell we want to leverage existing definitions to their fullest. We can just focus on the splits of the list itself, leaving k out of the implementation. luqui's answer beautifully demonstrates this. Be aware that an abstract notation (mathematical, logical, a specification, etc) does not always indicate a good implementation.
Once we know all the splits of the list, we can sum and compare for equality. If at least one comparison succeeds then yield True, otherwise yield False.

Iterating a function and analysing the result in haskell

Ok, referring back to my previous question, I am still working on learning haskell and solving the current problem of finding the longest chain from the following iteration:
chain n | n == 0 = error "What are you on about?"
| n == 1 = [1]
| rem n 2 == 0 = n : chain (n `div` 2)
| otherwise = n : chain (3 * n + 1)
I have this bit sorted, but I need to find the longest chain from a starting number below 1,000,000. So how do I make it do each starting number up to 1,000,000 and then print the one with the longest chain length.
I can do it for one example with:
Main> length (chain n)
I assume I need the output as an array and then use the maximum function to find the value largest chain length and then see how far along it is in the array of answers.
Is this a good way to go about finding a solution or is there a better way (perhaps with better efficiency)?
You are right about the maximum part. To get the list (that's what Haskell's []s are, arrays are different structures) you need to use the map higher-order function, like this:
chainLength n = length (chain n)
lengths = map chainLength [1..1000000]
Essentially, map takes as arguments a function and a list. It applies the function to each element in the list and returns the list of the results.
Since you will be needing the number whose chain has that length, you may want change the chainLength function to return the number as well, like this:
chainLength n = (n, length (chain n))
That way you will have an array of pairs, with each number and its chain length.
Now you need to get the pair with the largest second component. That's where the maximumBy function comes in. It works just like maximum but takes a function as a parameter to select how to compare the values. In this case, the second component of the pair. This comparison function takes two numbers and returns a value of type Ordering. This type has only three possible values: LT, EQ, GT, for less than, equal, and greater than, respectively.
So, we need a function that given two pairs tells us how the second components compare to each other:
compareSnd (_, y1) (_, y2) = compare y1 y2
-- Or, if you import Data.Function, you can write it like this (thanks alexey_r):
compareSnd = compare `on` snd -- reads nicely
I used the default compare function that compares numbers (well, not just numbers).
Now we only need to get the maximum using this function:
longestChain = maximumBy compareSnd lengths
That gets you a pair of the number with the longest chain and the corresponding length. Feel free to apply fst and snd as you please.
Note that this could be more much more concisely using zip and composition, but since you tagged the question as newbie, I thought it better to break it down like this.
SPOILER (solving the problem for positive integers under 100):
module Test where
import Data.List -- this contains maximumBy
chain n
| n == 0 = error "What are you on about?"
| n == 1 = [1]
| rem n 2 == 0 = n : chain (n `div` 2)
| otherwise = n : chain (3 * n + 1)
chains = map (\x -> (x,chain x)) [1..100]
cmpSnd (a,b) (c,d)
| length b > length d = GT
| length b == length d = EQ
| otherwise = LT
solve = (fst . maximumBy cmpSnd) chains
The chains function makes use of map. It applies a function to every element of a list of a values, so
map succ [1,2]
is the same as
[succ 1,succ 2]
The cmpSnd function is a comparison function that probably exists somewhere deep in the Hierarchical Libraries, but I could not find it, so I created it. GT means "the first value is greater than the second", the rest is trivial.
Solve takes the maximum (by utilizing the comparison function we defined earlier) of the list. This will be a pair of an integer and a list. It will return the integer only (because of the fst).
A comment: Your chain function is not tail-recursive. This means that large chains will inevitably result in a Stack Overflow. You shall add an explicit accumulator variable and make it tail-recursive.
Something like
fst $ maximumBy (length . snd) $ zip [1..1000000] $ map chain [1..1000000]
(untested)
i.e. don't work out how far along the longest chain is in the list of longest chains, but carry around the seed values with the chains instead.
I studied Haskell years ago, so I don't remember it that well. On the other hand I've tested this code and it works. You will get the max chain and the number that generates it. But as fiships has stated before, it will overflow for big values.
chain :: Int -> [Int]
chain n
| n == 0 = []
| n == 1 = [1]
| rem n 2 == 0 = n : chain (n `div` 2)
| otherwise = n : chain (3 * n + 1)
length_chain :: Int -> Int
length_chain n = length (chain n)
max_pos :: (Int,Int) -> Int -> [Int] -> (Int,Int)
max_pos (m,p) _ [] = (m,p)
max_pos (m,p) a (x:xs)
| x > m = max_pos (x,a) (a+1) xs
| otherwise = max_pos (m,p) (a+1) xs
The instruction will be
Main> max_pos (0,0) 1 (map length_chain [1..10000])
(262,6171)

Haskell: recursion with array arguments

Disclaimer: I'm new to Haskell and I don't remember a lot about FP from university, so there may be more than one or two errors in my code. This is also my code for Euler Problem 3.
I'm trying to recursively call a function with two arrays as arguments and an array as a result.
The goal:
assume n is 10 for this question
create a list of all natural numbers from 1 to n (variable is 'allNumbers' is code)
create another list of all natural numbers from 1 to n (variable is 'allFactors' is code)
take the first element in 'allFactors' and multiply the rest of the numbers of 'allFactors' by this number. (this generates an array of numbers)
remove all these numbers from 'allNumbers'
continue from 1 to n until 'allFactors' is empty.
Here is my code:
mkList :: Int -> [Int]
mkList n = [1..n-1]
modArray :: Int -> Int -> [Int]
modArray a b = [ x*b | x <- [1..a], x `mod` b == 0]
modArrayAll :: [Int] -> [Int] -> [Int]
modArrayAll [] [] = []
modArrayAll (x:xs) (y:ys) = (e)
where
m = head( ys)
n = length( xs)
e = (modArrayAll xs ys ) \\ modArray n m
(in main)
let allNumbers = mkList (first + 1)
let allFactors = mkList (first + 1)
let mainList2 = modArrayAll allNumbers allFactors
This results in a null list. However, if I have:
e = xs \\ modArray n m --WORKS for one iteration
I get all the odd numbers from 1 to 10.
My Question: Why isn't this working the way I would expect it? I would expect that the recursive stack would hit the empty array condition and just return an empty array which would not be removed from the calling array and it would continue on returning just the prime numbers?
I copied your goal notes:
-- assume n is 10 for this question
n=10
-- create a list of all natural numbers from 1 to n (variable is 'allNumbers' is code)
allNumbers = [1..n]
-- create another list of all natural numbers from 1 to n (variable is 'allFactors' is code)
allFactors = [2..n] -- i suspect you really wanted this rather than [1..n]
-- take the first element in 'allFactors' and
-- multiply the rest of the numbers of 'allFactors' by this number.
-- (this generates an array of numbers)
-- continue from 1 to n until 'allFactors' is empty
factorProducts = [ x*y | x <- allFactors, y <- allFactors]
-- remove all these numbers from 'allNumbers'
whatYouWanted = allNumbers \\ factorProducts
At the moment you seem to still be thinking in a fairly imperative mindset. Try thinking more about what you want, not how to get it :)
modArray n m creates a list of multiples of m, which you then remove from the "main list" of integers. But modArray n m includes 1*m, so each number is removed because it is a "multiple" of itself. In your test case you get only the odd numbers as a result, while you would want 2 to still be in the resulting list. Additionally 1 is included in your list of factors, which will eliminate all numbers, since they are all multiples of 1.
The terminating case of the recursion is modArrayAll [] [] = [], so there an empty list is returned. Then in the surrounding recursive calls this return value is used here:
(modArrayAll xs ys) \\ modArray n m
This tries to remove further elements (those returned by modArray n m) from the already empty list returned by modArrayAll xs ys. No new elements are added anywhere and the result list stays empty. With your algorithm you want the []-case to return the whole list of numbers, not an empty one. Then the \\ modArray n m in the surrounding recursive function calls can filter out more and more of the non-prime factors.

Resources