Multiplying elements in custom lists in Haskell - haskell

I am trying to implement a custom multiplication operation for my custom list data type in Haskell that uses an Int and [Int].
Int is used to reduce integers by modulus division I will refer to as d.
[Int] represents the content of the list
Let's say a and b are two lists that have the same d.
The length of a is w and the length of b is v
The c = a*b is:
c[k] = a[0] * b[k] + a[1] * b[k - 1] + a[2] * b[k - 2] + · · · + a[k] * b[0]
At the end, c[k] is reduced by mod d.
The length of c = w + v - 1
Meaning the index k in c[k] can be larger than the lengths of w and v.
To deal with this I concatenate a list of 0 elements for indices outside the bounds of the original list.
To clarify:
c[0] = (a[0] * b[0]) % d
c[1] = (a[0] * b[1] + a[1] * b[0]) % d
c[2] = (a[0] * b[2] + a[1] * b[1] + a[2] * b[0]) % d
.
.
.
c[w + v - 1]
For example, a = [3,2,4] and b = [7,9,7,2], both have d = 31.
In the code when they are being multiplied they are [3,2,4,0,0,0] and [7,9,7,2,0,0]
In this example, c = a * b = [21, 10, 5, 25, 1, 8]
This is my code:
module Custom where
data CustomList = CustomList Int [Int]
instance Num CustomList where
(CustomList a1 b1) * (CustomList a2 b2) =
if length b1 >= 1 && length b2 >= 1 then do
let llen = (length b1) + (length b2) - 1
--concatenating a list of 0 elements for indices outside the bounds of the original list.
let sub_b1 = llen - (length b1)
let sub_b2 = llen - (length b2)
let zeros_b1 = map (0*) [1..sub_b1]
let zeros_b2 = map (0*) [1..sub_b2]
--matching list lengths
let new_b1 = b1++zeros_b1
let new_b2 = b2++zeros_b2
--trying to mimic a nested for loop
let ans = [ (new_b1 !! x) * (new_b2 !! y) | x <- [0..llen-1], y <- (reverse [0..x]) ]
CustomList (a1) (map (`mod` (a1)) ans)
else do
0
instance Show CustomList where
show (CustomList a b) = "output: " ++ (show b) ++ "\nlength: " ++ (show a)
Output:
*Custom> let a = CustomList 31 [3,2,4]
*Custom> let b = CustomList 31 [7,9,7,2]
Incorrect (What I get)
*Custom> a * b
output: [21,18,14,28,5,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
length: 31
Correct (What I should get)
output: [21, 10, 5, 25, 1, 8]
length: 6
I realize issues in my logic:
The x counter, I need to start from a[0] and end at a[k] for all c[k] calculations but I am starting at a[x].
Answers are not being summed together. For instance, instead of obtaining c[1] = a[0] * b[1] + a[1] * b[0], I obtain c[1] = a[0] * b[1] & c[2] = a[1] * b[0]
I am not sure how to fix it, I have been trying and end up just creating new problems by trying to do.
I am a newbie at Haskell so I would prefer a simple readable way of solving this problem over the more "Haskell" way of doing it.
But any help is appreciated, thanks in advance.

Nice and simple:
data CustomList = CustomList Int [Int] deriving(Show)
instance Num CustomList where
CustomList a1 b1 * CustomList a2 b2 = CustomList a1 (map (`mod` a1) ans)
where ans = map getAnsElem [1..length b1 + length b2 - 1]
getAnsElem k = sum $ zipWith (*) (withLength k b1) (reverse $ withLength k b2)
withLength n xs = take n (xs ++ repeat 0)
Testing it:
λ> CustomList 31 [3,2,4] * CustomList 31 [7,9,7,2]
CustomList 31 [21,10,5,25,1,8]
Explanation:
withLength takes a list and makes it a given length, either by truncating it if it's too long, or padding with zeros if it's too short
zipWith takes 2 lists and goes over them in parallel, using the given function to combine the elements
One reason your approach with a list comprehension failed is because [f x y | x <- xs, y <- ys] takes the Cartesian product of xs and ys instead of zipping them. If you wanted to use a list comprehension instead, you could, but you'd need the ParallelListComp extension, in which case you'd have this:
getAnsElem k = sum [x * y | x <- withLength k b1 | y <- reverse $ withLength k b2]
Note the second | instead of a ,: this is what denotes zipping.

Related

How to code a function in Haskell which takes every other digit from an Int and adds it to a result Int?

I want to create a function as mentioned in the title. The specific is that it adds the digits in reversed order, you can see that in the test cases: 12 -> 1; 852369 -> 628; 1714 -> 11; 12345 -> 42; 891 -> 9; 448575 -> 784; 4214 -> 14
The main idea is that when the number is bigger than 99 it enters the helper function which has i - indicator if the the digit is on an even position, and res which stores the result. Helper begins to cycle n as it checks whether or not the current digit is on even position and adds it to the result.
So far I've tried the following code:
everyOther :: Int -> Int
everyOther n
| n < 10 = error "n must be bigger than 10 or equal"
| n < 100 = div n 10
| otherwise = helper n 0 0
where
helper :: Int -> Int -> Int -> Int
helper n i res
| n < 100 = res
| i == 1 = helper (div n 10) (i - 1) (res + (mod n 10)*10)
| otherwise = helper (div n 10) i res
Any help would be appreciated!
You can obtain the one but last digit of x with mod (div x 10) 10. You can use this with an accumulator that accumulates the value by each time multiplying with 10, so:
everyOther :: Int -> Int
everyOther = go 0
where go a v
| v < 10 = a
| otherwise = go (10*a + mod (div v 10) 10) (div v 100)
If v is thus less than 10, we can return the accumulator, since there is no "other digit" anymore. If that is not the case, we multiply a with 10, and add mod (div v 10) 10 to add the other digit to it, and recurse with the value divided by 100 to move it two places to the right.
We can improve this, as #Daniel Wagner says, by making use of quotRem :: Integral a => a -> a -> (a, a):
everyOther :: Int -> Int
everyOther = go 0
where go a v
| v < 10 = a
| otherwise = let (q, r) = v `quotRem` 100 in go (10*a + r `quot` 10) q
here we thus work with the remainder of a division by 100, and this thus avoids an extra modulo.

Averaging ages across a list with foldl (Haskell)

I am doing some arbitrary operations in Haskell as I learn, and have been playing with a list of animals with certain properties, including age.
This is my script:
module Animals where
data Animal = CatThing String Int
| DogThing String Int
deriving Show
animalList :: [Animal]
animalList = [CatThing "Spot" 2, DogThing "Rex" 5]
-- write a function that returns the string component given an animal
getName :: Animal -> String
getName (CatThing name _) = name
getName (DogThing name _) = name
-- get the age of an animal (uses "map")
getAge :: Animal -> Int
getAge (CatThing _ age) = age
getAge (DogThing _ age) = age
-- sum age
sumAge :: Int -> [Int] -> Int
sumAge _ [b, c] = foldl (+) 0 [b, c]
-- average age
???
I am stuck on how to sum using foldl'. I know there is a sum function built in, but I am really trying to practice folds, so am trying to do it that way.
Does anyone have suggestions on how to proceed?
The code for your sum looks fine, I'd use foldl' instead of foldl so you don't risk a stack overflow, and also change that [b,c] pattern to a generic variable or even better point free so it looks better and it's also more general:
sumAge :: [Double] -> [Double]
sumAge = foldl' (+) 0
As for the average, you just sum and divide by the length:
averageAge :: [Double] -> Double
averageAge ls = sumAge ls / length ls
PS. In case your ages are integer, then the first function still works, but the average need to change:
averageInt :: [Int] -> Double
averageInt ls = (fromInteger . sum) ls / (fromInteger . length) ls
TL;DR version
Sum: sumAges animals = foldl (\age animal -> age + (getAge animal)) 0 animals
Average:
import Data.Sequence(foldlWithIndex, fromList)
average numbers = foldlWithIndex (\a i x -> let k = fromIntegral i in (k*a + x) / (k + 1)) 0 . fromList $ numbers
Long version
If you have an interest in math, it may help to understand the design of fold functions as equivalent to discovering sequence formulas by induction.
Sum
For sum, since you have s[i+1] = s[i] + x[i+1], you can simply use addition like you did, although you may have to convert before you add:
sumAges :: [Animal] -> Int
sumAges animals = foldl (\age animal -> age + (getAge animal)) 0 animals
sumAgesPointFree :: [Animal] -> Int
sumAgesPointFree = foldl (flip $ (+) . getAge) 0
Average
For example, one way to calculate the average of a list using a single fold function is to use a recursive mathematical version of calculating the rolling average of a sequence: m[i+1] = (i * m[i] + x[i+1]) / (i + 1). You can see this in how you calculate the average of lists of varying sizes:
{-
Not Haskell, just attempting mathematical notation without knowing MathML in Markdown.
m: mean or average
x: an element of a list or sequence
[]: subscript
-}
m[1] = x[1]
m[2] = (x[1] + x[2]) / 2 = (m[1] + x[2]) / 2 -- m[1] = x[1], so substitute
m[3] = (x[1] + x[2] + x[3]) / 3 -- (a+b)/n = a/n + b/n, so distribute
= (x[1] + x[2]) / 3 + x[3] / 3 -- a = n/n * a, n not in {0, Infinity}
= 2/2 * (x[1] + x[2]) / 3 + x[3] / 3 -- n/n * 1/a = n/a * 1/n
= 2/3 * (x[1] + x[2]) / 2 + x[3] / 3 -- m[2] = (x[1] + x[2])/2, so substitute
= 2/3 * m[2] + x[3] / 3
= 2*m[2] / 3 + x[3] / 3
= (2*m[2] + x[3]) / 3
...
m[i+1] = (i * m[i] + x[i+1]) / (i+1)
However, since this function would require the element index as a parameter, due to the List structure's lack of (convenient) indexing, the Sequence type from the Data.Sequence module may work out better than a List, especially considering the Data.Sequence module has this really nice foldlWithIndex function:
module Average(average) where
import Data.Sequence(foldlWithIndex, fromList)
average :: Fractional a => [a] -> a
average = foldlWithIndex averageByPrevious 0 . fromList
where averageByPrevious previous index current = (coefficient*previous + current) / (coefficient + 1)
where coefficient = fromIntegral index
Then you can simply run average list where list is some list you want to find the rolling average of. This is one way to calculate the average of a list using a single fold without adding a large performance overhead as you would by running multiple O(n) functions over the same list, even considering laziness as a benefit to the performance of multiple calls.
NOTE: I will admit, this is not easy to read, so average xs = (sum xs) / (length xs) as #Lorenzo said will work much better if legibility is more important than performance here.

Emulating non-rectangular arrays

Often times you want the performance of arrays over linked lists while having not conforming to the requirement of having rectangular arrays.
As an example consider an hexagonal grid, here shown with the 1-distance neighbors of cell (3, 3) in medium gray and the 2-distance neighbors in light gray.
Say we want an array that contains, for each cell, the indices of every 1- and 2-distance neighbor for that cell. One slight issue is that cells have a different amount of X-distance neighbors -- cells on the grid border will have fewer neighbors than cells closer to the grid center.
(We want an array of neighbor indices --- instead of a function from cell coordinates to neighbor indices --- for performance reasons.)
We can work around this problem by keeping track of how many neighbors each cell has. Say you have an array
neighbors2 of size R x C x N x 2, where R is the number of grid rows, C for columns, and N is the maximum number of 2-distance neighbors for any cell in the grid.
Then, by keeping an additional array n_neighbors2 of size R x C, we can keep track of which indices in neighbors2 are populated and which are just zero padding. For example, to retrieve the the 2-distance neighbors of cell (2, 5), we simply index into the array as such:
someNeigh = neighbors2[2, 5, 0..n_neighbors2[2, 5], ..]
someNeigh will be a n_neighbors2[2, 5] x 2 array (or view) of indicies, where someNeigh[0, 0] yields the row of the first neighbor, and someNeigh[0, 1] yields the column of the first neighbor and so forth.
Note that the elements at the positions
neighbors2[2, 5, n_neighbors2[2, 5]+1.., ..]
are irrelevant; this space is just padding to keep the matrix rectangular.
Provided we have a function for finding the d-distance neighbors for any cell:
import Data.Bits (shift)
rows, cols = (7, 7)
type Cell = (Int, Int)
generateNeighs :: Int -> Cell -> [Cell]
generateNeighs d cell1 = [ (row2, col2)
| row2 <- [0..rows-1]
, col2 <- [0..cols-1]
, hexDistance cell1 (row2, col2) == d]
hexDistance :: Cell -> Cell -> Int
hexDistance (r1, c1) (r2, c2) = shift (abs rd + abs (rd + cd) + abs cd) (-1)
where
rd = r1 - r2
cd = c1 - c2
How can we create the aforementioned arrays neighbors2 and n_neighbors2? Assume we know the maximum amount of 2-distance neighbors N beforehand. Then it is possible to modify generateNeighs to always return lists of the same size, as we can fill up remaining entries with (0, 0). That leaves, as I see it, two problems:
We need a function to populate neighbors2 which operates not every individual index but on a slice, in our case it should fill one cell at a time.
n_neighbors2 should be populated simultaneously as neighbors2
A solution is welcome with either repa or accelerate arrays.
Here's you picture skewed 30 degrees to the right:
As you can see your array is actually perfectly rectangular.
The indices of a neighborhood's periphery are easily found as six straight pieces around the chosen center cell, e.g. (imagine n == 2 is the distance of the periphery from the center (i,j) == (3,3) in the picture):
periphery n (i,j) =
-- 2 (3,3)
let
((i1,j1):ps1) = reverse . take (n+1) . iterate (\(i,j)->(i,j+1)) $ (i-n,j)
-- ( 1, 3)
((i2,j2):ps2) = reverse . take (n+1) . iterate (\(i,j)->(i+1,j)) $ (i1,j1)
-- ( 1, 5)
.....
ps6 = ....... $ (i5,j5)
in filter isValid (ps6 ++ ... ++ ps2 ++ ps1)
The whole neighborhood is simply
neighborhood n (i,j) = (i,j) : concat [ periphery k (i,j) | k <- [1..n] ]
For each cell/distance combination, simply generate the neighborhood indices on the fly and access your array in O(1) time for each index pair.
Writing out the answer from #WillNess in full, and incorporating the proposal from #leftroundabout to store indecies in a 1D vector instead, and we get this:
import qualified Data.Array.Accelerate as A
import Data.Array.Accelerate (Acc, Array, DIM1, DIM2, DIM3, Z(..), (:.)(..), (!), fromList, use)
rows = 7
cols = 7
type Cell = (Int, Int)
(neighs, nNeighs) = generateNeighs
-- Return a vector of indices of cells at distance 'd' or less from the given cell
getNeighs :: Int -> Cell -> Acc (Array DIM1 Cell)
getNeighs d (r,c) = A.take n $ A.drop start neighs
where
start = nNeighs ! A.constant (Z :. r :. c :. 0)
n = nNeighs ! A.constant (Z :. r :. c :. d)
generateNeighs :: (Acc (Array DIM1 Cell), Acc (Array DIM3 Int))
generateNeighs = (neighsArr, nNeighsArr)
where
idxs = concat [[(r, c) | c <- [0..cols-1]] | r <- [0..rows-1]]
(neighsLi, nNeighsLi, n) = foldl inner ([], [], 0) idxs
neighsArr = use $ fromList (Z :. n) neighsLi
nNeighsArr = use $ fromList (Z :. rows :. cols :. 5) nNeighsLi
inner (neighs', nNeighs', n') idx = (neighs' ++ cellNeighs, nNeighs'', n'')
where
(cellNeighs, cellNNeighs) = neighborhood idx
n'' = n' + length cellNeighs
nNeighs'' = nNeighs' ++ n' : cellNNeighs
neighborhood :: Cell -> ([Cell], [Int])
neighborhood (r,c) = (neighs, nNeighs)
where
neighsO = [ periphery d (r,c) | d <- [1..4] ]
neighs = (r,c) : concat neighsO
nNeighs = tail $ scanl (+) 1 $ map length neighsO
periphery d (r,c) =
-- The set of d-distance neighbors form a hexagon shape. Traverse each of
-- the sides of this hexagon and gather up the cell indices.
let
ps1 = take d . iterate (\(r,c)->(r,c+1)) $ (r-d,c)
ps2 = take d . iterate (\(r,c)->(r+1,c)) $ (r-d,c+d)
ps3 = take d . iterate (\(r,c)->(r+1,c-1)) $ (r,c+d)
ps4 = take d . iterate (\(r,c)->(r,c-1)) $ (r+d,c)
ps5 = take d . iterate (\(r,c)->(r-1,c)) $ (r+d,c-d)
ps6 = take d . iterate (\(r,c)->(r-1,c+1)) $ (r,c-d)
in filter isValid (ps6 ++ ps5 ++ ps4 ++ ps3 ++ ps2 ++ ps1)
isValid :: Cell -> Bool
isValid (r, c)
| r < 0 || r >= rows = False
| c < 0 || c >= cols = False
| otherwise = True
This can be by using the permute function to fill the neighbors for 1 cell at a time.
import Data.Bits (shift)
import Data.Array.Accelerate as A
import qualified Prelude as P
import Prelude hiding ((++), (==))
rows = 7
cols = 7
channels = 70
type Cell = (Int, Int)
(neighs, nNeighs) = fillNeighs
getNeighs :: Cell -> Acc (Array DIM1 Cell)
getNeighs (r, c) = A.take (nNeighs ! sh1) $ slice neighs sh2
where
sh1 = constant (Z :. r :. c)
sh2 = constant (Z :. r :. c :. All)
fillNeighs :: (Acc (Array DIM3 Cell), Acc (Array DIM2 Int))
fillNeighs = (neighs2, nNeighs2)
where
sh = constant (Z :. rows :. cols :. 18) :: Exp DIM3
neighZeros = fill sh (lift (0 :: Int, 0 :: Int)) :: Acc (Array DIM3 Cell)
-- nNeighZeros = fill (constant (Z :. rows :. cols)) 0 :: Acc (Array DIM2 Int)
(neighs2, nNeighs2li) = foldr inner (neighZeros, []) indices
nNeighs2 = use $ fromList (Z :. rows :. cols) nNeighs2li
-- Generate indices by varying column fastest. This assures that fromList, which fills
-- the array in row-major order, gets nNeighs in the correct order.
indices = foldr (\r acc -> foldr (\c acc2 -> (r, c):acc2 ) acc [0..cols-1]) [] [0..rows-1]
inner :: Cell
-> (Acc (Array DIM3 Cell), [Int])
-> (Acc (Array DIM3 Cell), [Int])
inner cell (neighs, nNeighs) = (newNeighs, n : nNeighs)
where
(newNeighs, n) = fillCell cell neighs
-- Given an cell and a 3D array to contain cell neighbors,
-- fill in the neighbors for the given cell
-- and return the number of neighbors filled in
fillCell :: Cell -> Acc (Array DIM3 Cell) -> (Acc (Array DIM3 Cell), Int)
fillCell (r, c) arr = (permute const arr indcomb neighs2arr, nNeighs)
where
(ra, ca) = (lift r, lift c) :: (Exp Int, Exp Int)
neighs2li = generateNeighs 2 (r, c)
nNeighs = P.length neighs2li
neighs2arr = use $ fromList (Z :. nNeighs) neighs2li
-- Traverse the 3rd dimension of the given cell
indcomb :: Exp DIM1 -> Exp DIM3
indcomb nsh = index3 ra ca (unindex1 nsh)
generateNeighs :: Int -> Cell -> [Cell]
generateNeighs d cell1 = [ (row2, col2)
| row2 <- [0..rows]
, col2 <- [0..cols]
, hexDistance cell1 (row2, col2) P.== d]
-- Manhattan distance between two cells in an hexagonal grid with an axial coordinate system
hexDistance :: Cell -> Cell -> Int
hexDistance (r1, c1) (r2, c2) = shift (abs rd + abs (rd + cd) + abs cd) (-1)
where
rd = r1 - r2
cd = c1 - c2

Is it possible to store a removed value in haskell

Hi I am new to haskell and I was just wondering whether it was possible to store a value that has already been removed:
This is my code
input :: Integer -> String
input x = checklength $ intolist x
intolist 0 = []
intolist x = intolist (x `div` 10) ++ [x `mod` 10]
checklength x = if length(x) >= 13 && length(x) <= 16 then doubleall
(init(x)) else "Not valid length of credit card number"
doubleall x = finalcheck $ final $ double (reverse (x))
double x = case x of
[] -> []
[x] -> if (x*2 < 10) then [x*2] else [x*2 `div` 10 + x*2 `mod` 10]
x:y:xs -> (if (x*2 < 10) then [x*2] else [x*2 `div` 10 + x*2 `mod` 10]) ++
y:double xs
final x = (sum x) * 9
finalcheck x = if (x `mod` 10 == ...... ) then "True" else "False"
My code basically takes an input as an integer such as 987564736264535. then makes this integer into a list of number such as [9,8,7..5]. Then it checks the length has to between 13 to 16 digits. If not you get an error statement. If the digits are between the required amount it will go into the doubeall function and remove the last number using (init). the number removed is 5 in which it will double the numbers and reverse the list order. It will then sum the numbers together and multiple by 9. The final step that I have done part of is taking the last digit of the number that has already been summed together and multiplied by 9. So lets give and example lets say I get 456 then I use mod 10 to take the last number which is 6. **Now here is where I am having a problem in which I want to check whether this 6 is equal to the same number that was removed originally in the checklength function when I used init. So in the checklength function I removed the number 5 **
Thanks
Once you remove data, you can't access it again. You need a function that preserves the final checkdigit that you're stripping off.
Since order is (mostly) irrelevant, consider:
validate :: Integer -> Bool
validate x = let digits = toDigits x
in if checkLength digits
then doesMatch . splitCheckdigit $ digits
else False
where
toDigits 0 = [0]
toDigits x = go x
where
go 0 = []
go x = let (d, m) = x `divMod` 10
in m : toDigits d
-- reverses order
checkLength x = let l = length x
in 13 <= l && l <= 16
splitCheckdigit (checkdigit:rest) = (checkdigit, rest)
-- remember we reversed in toDigits, so the *first* digit is the checkdigit!
doesMatch (checkdigit, rest) = let total = (*9) . sum . reduce $ rest
shouldBe = total `mod` 10
in checkdigit == shouldBe
where
reduce (x:y:xs) = (sum . toDigits $ x) : y : reduce xs
reduce [x] = [sum . toDigits $ x]
reduce [] = []
-- note how #toDigits# is reused here rather than redefined.
If you prefer Arrows, validate can be written as:
toDigits >>> ((doesMatch <<< splitCheckdigit) &&& checkLength) >>> uncurry (&&)

How to do a triangular array in Haskell

I want to do something like
array ((0,0), (25, 25)) [((i,j), 1) | i <- [0..25], j <- [i..25]]
which you can see by the array index, is only defined when i <= j. However, when I try to print this out in ghci I get an error because it tries to print things like (1,0) due to the array bounds.
((1,0),*** Exception: (Array.!): undefined array element
I could just have the array be square and put something like 0's in those entries, but I think that would be suboptimal. Is there a way I can set up the bounds of this array to be "triangular"?
A simple upper triangular index can be defined as:
import Data.Ix (Ix, range, index, inRange)
data UpperTriagIndex = Int :. Int
deriving (Show, Ord, Eq)
instance Ix UpperTriagIndex where
range (a :. b, c :. d) = concatMap (\i -> (i :.) <$> [max i b..d]) [a..c]
inRange (a :. b, c :. d) (i :. j) = a <= i && i <= c && b <= j && j <= d
index pr#(a :. b, c :. d) ix#(i :. j)
| inRange pr ix = f a - f i + j - i
| otherwise = error "out of range!"
where f x = let s = d + 1 - max x b in s * (s + 1) `div` 2
One can verify that range and index round trip even if the array is not square. For example:
\> let pr = (0 :. 0, 3 :. 5) in index pr <$> range pr
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] -- [0..17]
and:
\> import Data.Array (array, (!))
\> let f i j = (i :. j, "row: " ++ show i ++ ", col: " ++ show j)
\> let a = array ((0 :. 0), (3 :. 3)) [f i j | i <- [0..3], j <- [i..3]]
\> a ! (2 :. 3)
"row: 2, col: 3"

Resources