Haskell - Form a matrix based on a list Matrix - haskell

I would to make a haskell function that takes a list of Item Ratings(a data type I declared), looking like this:
[[NoRating,R 5.0],[R 5.0,R 4.0],[R 3.0,R 1.0]]
the declaration of Rating looks like this:
data Rating c = NoRating | R c deriving (Show, Eq)
in the list each sublist represents ratings belonging to a user, each sublist contains multiple items, in the previous example 2 items were in the sublist,
What I would like to return is a list of item rating differences from a matrix like input, The value at row i and column j represents the sum of the differences between the ratings given to item i and item j by the same user
for example, for the input
dMatrix [[NoRating,R 5.0],[R 5.0,R 4.0],[R 3.0,R 1.0]]
I would like to return
[0.0,3.0,-3.0,0.0]
I have already implemented a difference function that takes 2 ratings and returns the difference, it looks like this, would be nice to use it through
differenceRatings :: Fractional a => Rating a -> Rating a -> a
differenceRatings NoRating (R a) = 0
differenceRatings (R a) NoRating = 0
differenceRatings (R a) (R b) = a - b
I'm having a hard time implementing this because the only way I know to loop in haskell is recursion but in this instance I need to do in a specific matrix order and access multiple sublist items of same index at same time, thanks for your help.
Picture as like example, first we do column 0 with column 0, difference is 0,
then we do column 0 with column 1, rating of item 0 for user 1 - item 2 for user 1, and so on for user 2 and 3 then sum them, put that in the second index of result list
then we do column 1 with column 0, negative of what is before generally
lastly column 1 with column 1, difference is 0
I have drafted this code and tried it but am getting a type error
dMatrix :: Fractional a => [[Rating a]] -> [a]
dMatrix [] = []
dMatrix x = dMatrixH1 x 0 0
dMatrixH1 (x:xs) i j = (dMatrixH x:xs i j) ++ (if (j < ((length (x:xs))-1))
then dMatrixH (x:xs) i (j+1) else if (i < ((length xs)-1)) then dMatrixH
(x:xs) (i+1) 0 else 0)
dMatrixH [] _ _ = 0
dMatrixH (x:xs) i j = (differeneRatings (x!!i) (x!!j)) + dMatrixH xs i j

Managed to do it using 2 of my helper functions, posting them first
matrixPairs :: Num a => a -> [(a,a)]
matrixPairs 0 = []
matrixPairs c = matrixPairsH 0 0 (c-1)
matrixPairsH a b c = [(a,b)] ++ if ((b == c) && (a == c)) then [] else if (b == c) then (if (a==c) then [] else matrixPairsH (a+1) 0 c ) else matrixPairsH a (b+1) c
and
differeneRatings :: Fractional a => Rating a -> Rating a -> a
differeneRatings NoRating (R a) = 0
differeneRatings (R a) NoRating = 0
differeneRatings NoRating NoRating = 0
differeneRatings (R a) (R b) = a - b
and here's the code for the required function
dMatrix :: Fractional a => [[Rating a]] -> [a]
dMatrix [] = []
dMatrix (x:xs) = dMatrixH (x:xs) (matrixPairs (length x))
dMatrixH _ [] = []
dMatrixH x ((a,b):ys) = [(dMatrixH2 x a b)] ++ dMatrixH x ys
dMatrixH2 [] _ _ = 0
dMatrixH2 (x:xs) a b = (differeneRatings (x!!a) (x!!b)) + dMatrixH2 xs a b

Related

Haskell - Count occurrences from multiple elements and return tuple

Heyy, I'm Haskell beginner and I pretend to do the following function:
occurrences 3 7 [-1,3,-4,3,4,3,-8,7,7,3]
Output that I want:
(4,2)
I made this try but doesn't worked so well, guess I having troubles to count the elements individually and to return the tuple
occurrences a b [] = 0
occurrences a b (x:xs)
| x == a = 1 + occurrences a b xs
| x == b = 1 + occurrences a b xs
| otherwise = occurrences a b xs
I appreciate any tip and help, thanks ;)
A good approach is to add a type signature, and use the error messages to guide you:
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b [] = 0
occurrences a b (x:xs)
| x == a = 1 + occurrences a b xs
| x == b = 1 + occurrences a b xs
| otherwise = occurrences a b xs
The first error is “Could not deduce (Num (Int, Int)) arising from the literal 0 from the context Eq a”. This means that we can’t use 0 in the first equation because it’s not a tuple, or more precisely, there is no Num instance that allows us to convert from the literal 0 to a tuple via fromIntegral. In the base case, we should return a tuple containing 0 for both sums:
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b [] = (0, 0)
occurrences a b (x:xs)
| x == a = 1 + occurrences a b xs
| x == b = 1 + occurrences a b xs
| otherwise = occurrences a b xs
The next error is “Could not deduce (Num (Int, Int)) arising from a use of + from the context Eq a. This means we’re trying to use + on the result of occurrences, but as with the previous error, it doesn’t have a Num instance to provide +, because it’s now a tuple. The fix here is to match on the result of occurrences and add to the first or second element of the tuple accordingly:
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b [] = (0, 0)
occurrences a b (x:xs)
| x == a = let (m, n) = occurrences a b xs in (m + 1, n)
| x == b = let (m, n) = occurrences a b xs in (m, n + 1)
| otherwise = occurrences a b xs
Now this produces the expected result:
> occurrences 'a' 'b' "ababcb"
(2,3)
But we can improve this solution in a few ways. First, a and b remain the same throughout the computation, so we can do the recursion in a helper function instead of passing a and b around to every call.
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b = go
where
go [] = (0, 0)
go (x:xs)
| x == a = let (m, n) = go xs in (m + 1, n)
| x == b = let (m, n) = go xs in (m, n + 1)
| otherwise = go xs
The idiom here is to define f a b … = go where go = …, and replace calls to f a b … with go—because they’re defined as equal! This is a great example of equational reasoning, replacing one side of an equation with the other.
Finally, since every equation of go except the base case contains a tail call to go, it suggests we can express this pattern of recursion with a fold. Here, our accumulator is the pair of results, and the combining function can increment the results accordingly as we step through the list. Since our accumulator is just a pair of integers, it’s a good idea to use a strict fold (foldl').
import Data.List (foldl')
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b = foldl' go (0, 0)
where
go (m, n) x
| x == a = (m + 1, n)
| x == b = (m, n + 1)
| otherwise = (m, n)
Finally, instead of keeping an accumulator and adding elements one by one, we can just map each element to a value (0 or 1) and reduce them by summation. This map/reduce pattern is captured by foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m, which maps each element of a container (t a) to a value (m) and combines the results using a Monoid instance. The monoid to use here is Sum from Data.Monoid, whose Monoid and Semigroup instances define mempty = Sum 0 and Sum a <> Sum b = Sum (a + b) respectively.
import Data.Coerce (coerce)
import Data.Foldable (foldMap)
import Data.Monoid (Sum(..))
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b = coerce . foldMap go
where
go x
| x == a = (Sum (1 :: Int), mempty)
| x == b = (mempty, Sum (1 :: Int))
| otherwise = mempty
We can make use of functions like first :: Arrow a => a b c -> a (b, d) (c, d) and second :: Arrow a => a b c -> a (d, b) (d, c) to construct a tuple where we apply a function to one of the two items of the 2-tuple. For example:
Prelude Control.Arrow> first (1+) (1,4)
(2,4)
Prelude Control.Arrow> second (1+) (1,4)
(1,5)
We thus can use this to update the tuple with:
import Control.Arrow(first, second)
import Data.List(foldl')
occurrences :: (Eq a, Integral i, Integral j, Foldable f) => a -> a -> f a -> (i, j)
occurrences a b = foldl' (flip f) (0, 0)
where f c | a == c = first (1+)
| b == c = second (1+)
| otherwise = id
For the sample input, this produces:
Prelude Control.Arrow Data.List> occurrences 3 7 [-1,3,-4,3,4,3,-8,7,7,3]
(4,2)
We can easily extent this behavior, by making use of lenses to update one of the elements of tuple.
#emg184 gave a good way to solve this problem, but there could be cleaner, easier to read ways to go about doing this. For example:
occurrences x y xs = (count x xs, count y xs)
where count = (length .) . filter . (==)
count could also be written in a more readable:
count x = (length . filter (== x))
You could approach this problem a lot of different way's here is an example of doing it with a fold.
occurrences :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences a b list = foldr (\y (a', b') -> ((isEqual y a a'), (isEqual y b b'))) (0, 0) list
where isEqual listEle tupEle count = if (listEle == tupEle) then (count + 1) else count
One of the problem's is you have a type mismatch. you want a type of:
(Int, Int)
Yet you are returning a type of int here once you have an empty list:
occurrences a b [] = 0 -- Int
occurrences a b (x:xs)
| x == a = 1 + occurrences a b xs
| x == b = 1 + occurrences a b xs
| otherwise = occurrences a b xs
You need some type of an accumulator you could do this by where binding a local function that takes your starting tuple of (0, 0) or you could pass it to occurrences like this:
occurrences :: Int -> Int -> [Int] -> (Int, Int) -> (Int, Int)
I would suggest using a local function since you'll always want to start with (0, 0) in this approach.
occurrences' :: (Eq a) => a -> a -> [a] -> (Int, Int)
occurrences' a b list = go list (0,0)
where go x (e1, e2) = if (x == []) then (e1, e2) else (go (tail x) ((isEqual a (head x) e1), (isEqual b (head x) e2)))
isEqual v v' accum = if (v == v') then (accum + 1) else (accum)
This isnt the most idiomatic way to do it but it shows the point. You should try to use types to help with this.,

Number of loops in recursion

I would like to count the number of positive integers/elements in the list. This returns the elements with positive values, how can I count the elements? would like to construct something like count(array(...)).
I would like to see a version with i++ and foldl. That would be very helpful.
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
Here's a hint: follow the same recursion scheme as before, but return an int at every step.
countPositivesRec :: [Int] -> Int
---
countPositivesRec [] = 0 -- no positives in the empty list
countPositivesRec (x:xs) | x >= 0 = ??
| otherwise = ??
where tl = countPositivesRec xs
One you solve this, it can be rewritten using foldr, if you want.
If you really want to use foldl instead, I would suggest you start by defining a function f such that
f (f (f 0 x0) x1) x2
evaluates to the number of positives in x0,x1,x2. Then you can use foldl f 0 inputList
The function you've written is filter (>=0). As Paul pointed out, the only step remaining is to count and length does that. We can transform the function step by step:
countPositivesRec :: [Int] -> [Int]
countPositivesRec [] = []
countPositivesRec (x:xs) | x >= 0 = x : tl
| otherwise = tl
where tl = countPositivesRec xs
Observe that xs is only used in the transformed form tl. That's what makes this a right fold.
onlypos1 = foldr maybekeep []
where maybekeep x tl | x >= 0 = x : tl
| otherwise = tl
This operation is known as a filter, keeping only some parts:
onlypos2 = filter dowekeep
where dowekeep x = x >= 0
onlypos3 = filter (\x -> x >= 0)
onlypos4 = filter (>= 0)
But this is of course only one of many possible approaches. For instance, strictness analysis can lead to the conclusion that length is better implemented as foldl' (\a _ -> succ a) 0 than foldr (\_ a -> succ a) 0. Indeed, that is its basic form in the Prelude:
length = foldl' (\c _ -> c+1) 0
We see that the combining function of length ignores the value of one argument, merely requires it to be there. This can naturally be merged with our condition that only some elements count:
lengthFilter1 = length . filter
lengthFilter2 pred = foldl' predCount 0
where predCount c x = if pred x then c+1 else c
countNonNegative = lengthFilter2 nonNegative
where nonNegative x = x >= 0
Incidentally, 0 isn't positive. It's non-negative.
In the end, Haskell's lazy lists mean we can use them to fuse traversals; length . filter (>=0) will only read the input list once, because the only reason it's processing results from filter is that length consumes them. The filtered list never exists as a fully expanded structure, unlike e.g. Python or PHP. This form is likely one of the most readable, but others exist, e.g.:
countNonNegatives xs = sum [1 | x <- xs, x >= 0]
You have
filtering p cons x r = if | p x -> cons x r | otherwise -> r
countPositives = length
. filter (> 0)
= foldr (\x r -> r + 1) 0 -- r++
. foldr (filtering (> 0) (:) ) []
= foldr (filtering (> 0) (\x r -> r + 1)) 0
(since folds fuse by composing their reducer transformers, a-la "fold replaces the cons with a reducer operation, so why create the cons in the first place if it gonna be replaced anyway"), and
filtering (> 0) (\x r -> r + 1) x r
= if | (> 0) x -> (\x r -> r + 1) x r | otherwise -> r
= if | x > 0 -> r + 1 | otherwise -> r
and thus, a version with fold and increment that you wanted,
countPositives = foldr (\x r -> if | x > 0 -> r + 1 | otherwise -> r) 0 -- r++
You can take it from here.

Haskell - Cannot infer instance

I have written the following predicate (Lines 94-99)
diffFreqMatrix :: Fractional a => [[Rating a]] -> [a]
diffFreqMatrix (x:xs) = diffFreqMatrixH (x:xs) (matrixPairs (length x))
diffFreqMatrixH _ [] = []
diffFreqMatrixH x ((a,b):ys) = [(diffFreqMatrixH2 x a b 0 0)] ++ diffFreqMatrixH x ys
diffFreqMatrixH2 [] _ _ x y = x / y
diffFreqMatrixH2 (x:xs) a b summ num = if (((x!!a) /= NoRating) && ((x!!b) /= NoRating)) then diffFreqMatrixH2 xs a b (summ + ((x!!a) - (x!!b))) (num + 1) else diffFreqMatrixH2 xs a b summ num
supposedly it calculates an average I want but i'm getting this error
ERROR file:.\project.hs:98 - Cannot infer instance
*** Instance : Fractional (Rating a)
*** Expression : diffFreqMatrixH2
Helpers im using in case u want to take a look
matrixPairs :: Num a => a -> [(a,a)]
matrixPairs 0 = []
matrixPairs c = matrixPairsH 0 0 (c-1)
matrixPairsH a b c = [(a,b)] ++ if ((b == c) && (a == c)) then [] else if (b == c) then (if (a==c) then [] else matrixPairsH (a+1) 0 c ) else matrixPairsH a (b+1) c
differeneRatings :: Fractional a => Rating a -> Rating a -> a
differeneRatings NoRating (R a) = 0
differeneRatings (R a) NoRating = 0
differeneRatings NoRating NoRating = 0
differeneRatings (R a) (R b) = a - b
You use Rating as as if they were just numbers here:
(x!!a) - (x!!b)
You presumably need to use case or similar to pattern match on x!!a and x!!b to extract the number they contain. You can move the check for NoRating into that case match to simplify your code. For example:
case (x!!a, x!!b) of
(YesRating ra, YesRating rb) -> diffFreqMatrixH2 xs a b (summ + ra - rb) (num + 1)
_ -> diffFreqMatrixH2 xs a b summ num
Once you get this working the way you want, I encourage you to post to the code review StackExchange; your code can be cleaned up significantly to be both simpler and faster.

Haskell Memoization Codewars Number of trailing zeros of factorial n

I am trying to solve the Codewars problem called: Number of trailing zeros of N! with Haskell.
I know that I don't need to calculate the factorial to know the trailing zeros and in fact I am just counting how many many numbers are divisible by 5 and how many times for each.
I have written 2 version, one that uses memoization when defactoring a number in order to get how many times is divisible by 5 and another one that do not use memoization.
What surprise me is that the supposed DP approach takes longer than the trivial recursive one. I am probably doing something very stupid in my code.
These are the functions:
zeros x = helperZeros [1..x]
helperZeros :: [Integer] -> Integer
helperZeros = sumArrayTuple . filter (\x -> x `mod` 5 == 0)
sumArrayTuple = foldl (\acc x -> acc + (fastDef x)) 0
data Tree a = Tree (Tree a) a (Tree a)
instance Functor Tree where
fmap f (Tree l m r) = Tree (fmap f l) (f m) (fmap f r)
index :: Tree Integer -> Integer -> Integer
index (Tree _ m _) 0 = m
index (Tree l _ r) n = case (n-1) `divMod` 2 of
(q,0) -> index l q
(q,1) -> index r q
nats = go 0 1
where
go n s = Tree (go l s') n (go r s' )
where
l = n + s
r = l + s
s' = s * 2
fastDef:: Integer -> Integer
fastDef x = trace (show x) index memTreetDef x
memTreetDef = fmap (defact fastDef) nats
defact f n
| n `mod` 5 /= 0 = 0
| otherwise = 1 + f (n `div` 5)
zeros' x = helperZeros' [1..x]
helperZeros' :: [Integer] -> Integer
helperZeros' = sumArrayTuple' . filter (\x -> x `mod` 5 == 0)
sumArrayTuple' = foldl (\acc x -> acc + (def x)) 0
def n
| n `mod` 5 /= 0 = 0
| otherwise = 1 + def (n `div` 5)
What I am trying to memoize is the result of the defact function, for example if I have already calculate defact 200, then it would reuse this result to calculate defact 1000.
I am fairly new to DP in Haskell.
If you are tested your code performance with trace and show here, that is the issue: they are very slow compared to the main code. If not, performance of variants must be about the same.
The def function is a poor candidate for memoization. The average depth of recursion is not very different from 1. The rest of the complexity is reduced to the operation mod, that is, the division that is hardly more expensive than table look up (and division by constant can be optimized to multiplication).

Haskell optimization program

Have the task
I need to implement the function Change, which will take the value and split it into the possible combinations from list of coins(random list)
Example:
coins = [2,3,7]
GHCi> change 7
[[2,2,3],[2,3,2],[3,2,2],[7]]
That's what I did:
coins :: Num a => [a]
coins = [2, 3, 7]
change :: (Ord a, Num a) => a -> [[a]]
change n = uniqEl (filter (\x -> sum x == n) take ()(subsequences (replic' n coins coins)))
replic' n x y | n == 1 = y
| otherwise = replic' (n-1) x (y ++ x)
uniqEl :: Eq a => [a] -> [a]
uniqEl [] = []
uniqEl (x:xs) = if (x `elem` xs) then uniqEl xs else x : (uniqEl xs)
But this code is very slow. Help to make this program more quickly. As part of the job it is said that this task is easily done with the help of generators lists and recursion. Thank you in advance for your help.
import Data.List
change :: [Int] -> Int -> [[Int]]
change _ 0 = []
change coins n = do
x <- [c | c <- coins, c <= n]
if x == n
then return [x]
else do
xs <- change coins (n - x)
-- if (null xs)
-- then return [x]
-- else if x < (head xs)
-- then []
-- else return (x:xs)
return (x:xs)
change' :: Int -> [[Int]]
change' = change [2,3,7]
test7 = change' 7
test6 = change' 6
test5 = change' 5
test4 = change' 4
You're doing a lot of filtering, eleming and so on, and placing a lot of constraints on the data types.
Think of this more as a dynamic problem, that you constantly need to figure out how many ways there are to return change for a total amount.
Once you have found the amount of possibilities for a specific coin, you can remove it from the list.
Here is my proposed solution wrapped up in one function.
In the list comprehension, note that I assign values to the remaining variable, and that these values range from [0,total], with jumps every x, where x is the denomination.
For example, if you had to calculate how many times $0.25 goes into a $2 total, that list comprehension ends up doing:
[countChange 2, countChange 1.75,countChange 1.5, countChange 1.25,...], but also these next iterations of countChange don't include the 0.25 coin - because we just "tested" that.
-- Amount to return -> List of Coin denominations available
countChange :: Integer -> [Integer] -> Integer
countChange _ [] = 0 -- No coins at all, so no change can be given
countChange 0 _ = 1 -- Only one way to return 0 change
countChange total (x:xs) = sum [countChange (total-remaining) xs | remaining <- [0,x..total]]
Use MemoCombinators. This is fast ! Pls. try change 100
import Data.List
import qualified Data.MemoCombinators as Memo
coins :: [Int]
coins = [2,3,7]
change :: Int -> [[Int]]
change = Memo.integral change'
change' 0 = []
change' n = do
x <- [c | c <- coins, c <= n]
if x == n
then return [x]
else do
xs <- change (n - x)
-- if (null xs)
-- then return [x]
-- else if x < (head xs)
-- then []
-- else return (x:xs)
return (x:xs)

Resources