Haskell: create different representations for same data - haskell

Suppose I have some data that is organized in a grid like this (dimensions may vary, but side of a grid is always n**2):
0 1 2 3
4 5 6 7
8 9 A B
C D E F
What I would like to achieve is to have a list with the same data represented in different ways, i.e. split into column, rows, or (most importantly) cells which is
0 1 | 2 3
4 5 | 6 7
----+----
8 9 | A B
C D | E F
So that if I do some action I will be able to get data as a following list:
[[0, 1, 4, 5],
[2, 3, 6, 7],
[8, 9, C, D],
[A, B, E, F]]
Where ordering does not matter.
I would like to use this to later construct a lens, that will be able to set values considering different kinds of representations. This is something that could have been acheived with use of pointers or references in imperative languages (where applicable).
Besides specifics, I would like to know if there is a general approach to having same internal data represented differently.
Here's what I got so far, using [Int] as internal representation, and conversion function to get specific "views":
import Data.List (transpose)
data Access = Rows | Columns | Cells
isqrt :: Int -> Int
isqrt = floor . sqrt . fromIntegral
group :: Int -> [a] -> [[a]]
group _ [] = []
group n l
| n > 0 = (take n l) : (group n (drop n l))
| otherwise = error "inappropriate n"
representAs :: [Int] -> Access -> [[Int]]
representAs list Rows = group (isqrt . length $ list) list
representAs list Columns = transpose $ list `representAs` Rows
representAs list Cells = let row_width = isqrt . length $ list
cell_width = isqrt row_width
drops = map (\x -> cell_width
* row_width
* (x `quot` cell_width)
+ cell_width
* (x `rem` cell_width)
) [0..row_width-1]
in (map ( (map snd)
. (filter ( (==0)
. (`quot` cell_width)
. (`rem` row_width)
. fst)
)
. (zip [0..])
. (take (row_width * cell_width))
. (`drop` list)
) drops
)
main = mapM_ (putStrLn . show) ([1..16] `representAs` Cells)
My question is based on the same idea as this one, but the answer there regards only memory issues, rather than construction. Besides, if I am to store same data differently in a few representations, I will have to update all of them up setting new value, as far as I understand.

First of all, as user2407038 has mentioned in the comments, List is not a very efficient data structure, especially for what you are trying to do. So I will provide an implementation using a boxed Vector from vector package, which obviously has an advantage of a constant time lookup.
Secondly, you cannot think while programming in a functional language the same way you would in imperative language. In Haskell you should choose a data structure that is most efficient in how you will handle the data, and the actual representation delegate to functions that operate on that data. What I mean is (because there is no mutation, unless you really really need it) you cannot set a value and expect it to change in all representations of the data, but rather should have data stored in a single data structure and all of the functions that operate on that data, take in account it's representation.
In implementation below it always stores data as a flat Vector and lets all the functions that operate on MyGrid take in account it's current representation Access. You probably would rather pass Access around to functions, instead of making it part of MyGrid data type, but I made that choice just for simplicity.
import qualified Data.Vector as V
data Access = Rows | Columns | Cells
data MyGrid a = MyGrid { side :: Int -- square grid with each side = N
, view :: Access
, vect :: V.Vector a }
This approach allows you to create proper constructors, that do all the sanity checks, for instance:
-- | Constructs a grid from a list, while making sure no elements are lost.
fromList :: [a] -> Access -> MyGrid a
fromList ls a = MyGrid { side = if side'*side' == length ls
then if even side'
then side'
else error "grid cannot be split in the middle"
else error "list cannot be represented as a square grid"
, view = a
, vect = V.fromList ls } where
side' = floor . sqrt . fromIntegral . length $ ls
another constructor could possibly be the one that uses a function to generate elements by using indexes of the grid and current representation:
fromFunction :: Int -> Access -> ((Int, Int) -> a) -> MyGrid a
Now, here is the most important part that takes care of the representation, which is retrieving an element from the grid:
index :: MyGrid a -> (Int, Int) -> a
index grid (i, j) =
case view grid of
Rows -> vect grid V.! (i * side grid + j)
Columns -> vect grid V.! (j * side grid + i)
Cells -> vect grid V.! if even i then k else k - d where
n = side grid
d = n `div` 2
k = (i + j `div` d) * n + j `mod` d
And now you can use that function to deal with representation of your data, for instance converting it to a list of lists, describe how it is printed, or mapped over, etc.:
toLists :: MyGrid a -> [[a]]
toLists grid = map (map (index grid)) [[(j, i) | i <- [0..n]] | j <- [0..n]]
where n = side grid - 1
instance Show a => Show (MyGrid a) where
show grid = unlines . map show $ toLists grid
instance Functor MyGrid where
fmap f grid = grid { vect = V.map f $ vect grid}
Which now allows you to deal with MyGrid's current representation (through using show, fmap, etc.):
λ> fromList [0..15] Rows
[0,1,2,3]
[4,5,6,7]
[8,9,10,11]
[12,13,14,15]
λ> succ <$> fromList [0..15] Columns
[1,5,9,13]
[2,6,10,14]
[3,7,11,15]
[4,8,12,16]
λ> fromList [0..15] Cells
[0,1,4,5]
[2,3,6,7]
[8,9,12,13]
[10,11,14,15]
Here is the assumption I made about how to split the cells for a grid with side bigger than 4. Maybe the grid should have a side with powers of 2, maybe cells should be 2 by 2, I couldn't infer. Just adjust the math to what you need, but I chose to split larger grids for Cells in this way:
0 1 2 | 3 4 5
6 7 8 | 9 10 11
---------+---------
12 13 14 | 15 16 17
18 19 20 | 21 22 23
---------+---------
24 25 26 | 27 28 29
30 31 32 | 33 34 35
If you need further help with proper cell splitting, edit the question with some examples how it should be done and I'll adjust the implementation.

For posterity and future reference, I will post an implementation based on ideas collected. Whole answer is a literate Haskell program, and can be saved as *.lhs and be run (although due to formatting, it will need additional lines to separate code and text).
> {-# LANGUAGE TemplateHaskell, FlexibleContexts #-}
> import Control.Lens (makeLenses, lens, (^.), ix, (.~), (.=), (^?), (%~))
> import qualified Data.Vector as V
> import Data.Vector.Lens (sliced)
> import Data.Maybe (fromJust)
> import Data.Function ((&))
> import Data.List (sortBy)
Data representation accessor:
Cells are non-overlapping squares such that the number of elements
in each is equal to grid side;
Rows are just data split into chunks of grid-side length;
Columns are rows transposed.
> data Access = Rows | Columns | Cells
Data structure itself, an sample representation would be
1 2 3 | 4 5 6 | 7 8 9
10 11 12 | 13 14 15 | 16 17 18
19 20 21 | 22 23 24 | 25 26 27
---------+----------+---------
28 29 30 | 31 32 33 | 34 35 36
37 38 39 | 40 41 42 | 43 44 45
46 47 48 | 49 50 51 | 52 53 54
---------+----------+---------
55 56 57 | 58 59 60 | 61 62 63
64 65 66 | 67 68 69 | 70 71 72
73 74 75 | 76 77 78 | 79 80 81
Where a single cell is, e.g.
1 2 3
10 11 12
19 20 21
A cell always holds same amount of elements as a row or column.
> data MyGrid a = MyGrid { _cell :: Int -- size of cell in grid, whole grid
> -- is a square of width `cell^2`
> , _vect :: V.Vector a -- internal data storage
> }
> makeLenses ''MyGrid
Convert 2D index of given representation and cell size to internal
> reduce_index_dimension :: Access -> Int -> (Int, Int) -> Int
> reduce_index_dimension a s (x,y) =
> case a of
> Cells -> (y`rem`s)
> + (x`rem`s) * s
> + (y`quot`s) * s^2
> + (x`quot`s) * s^3
> Rows -> x * s * s + y
> Columns -> y * s * s + x
Convert internal index for given representation and cell size to 2D
> increase_index_dimension :: Access -> Int -> Int -> (Int, Int)
> increase_index_dimension a s i =
> case a of
> Cells -> ( s * i `quot` s^3
> + (i `rem` s^2) `quot` s
> , s * ((i `quot` s^2) `rem` s)
> + i `rem` s )
> Rows -> ( i `rem` s^2
> , i `quot` s^2)
> Columns -> ( i `quot` s^2
> , i `rem` s^2)
Constructs a grid from a list, while making sure no elements are lost.
> fromList :: [a] -> MyGrid a
> fromList ls = MyGrid { _cell = if side'^2 == length ls
> then if cell'^2 == side'
> then cell'
> else error "can't represent cell as a square"
> else error "can't represent list as a square"
> , _vect = V.fromList ls } where
> side' = floor . sqrt . fromIntegral . length $ ls -- grid width
> cell' = floor . sqrt . fromIntegral $ side' -- cell width
Convert given representation to internal
> convert :: Access -> [[a]] -> [a]
> convert from list = map snd
> . sortBy compare_index
> . map reduce_index
> . concatMap prepend_index
> . zip [0..] $ list
> where
> size = floor . sqrt . fromIntegral . length $ list
> prepend_index (a, xs) = zipWith (\b c -> ((a, b), c)) [0..] xs
> reduce_index (i, x) = (reduce_index_dimension from size i, x)
> compare_index (i, _) (j, _) = compare i j
Constructs a grid from another grid, taking representation into account
> fromListsAs :: Access -> [[a]] -> MyGrid a
> fromListsAs a l = MyGrid { _cell = if allEqualLength l
> then if cell'^2 == side'
> then cell'
> else error "can't represent cell as a square"
> else error "lists have different length or do not fit"
> , _vect = V.fromList . convert a $ l } where
> side' = length l
> cell' = floor . sqrt . fromIntegral $ side' -- cell width
> allEqualLength xs = and $ map ((== side') . length) (tail xs)
combining lenses over same object, see Haskell use first level lenses to create complex lens
> (x ^>>= f) btofb s = f (s ^. x) btofb s
lens to focus at element poited to in given representation with given 2d index
> lens_as a i = cell ^>>= \s -> vect . sliced (reduce_index_dimension a s i) 1 . ix 0
convert to 2d representation
> toListsAs :: MyGrid a -> Access -> [[a]]
> toListsAs g a = [[fromJust $ g^?(lens_as a (x, y)) | y <- [0..n]] | x <- [0..n]]
> where n = (g^.cell)^2 - 1
defaults
> toLists :: MyGrid a -> [[a]]
> toLists g = g `toListsAs` Rows
> instance Show a => Show (MyGrid a) where
> show grid = unlines . map show . toLists $ grid
> instance Functor MyGrid where
> fmap f grid = grid & vect %~ V.map f
sanity check
> main = mapM_ (putStrLn . show) (fromList [0..(+80)0] `toListsAs` Cells)

An inefficient implementation perhaps trigger better ideas
column,row :: Int -> [((Int,Int),a)] -> [a]
column n xs = map snd $ filter (\((_,y),_) -> y==n) xs
row n xs = map snd $ filter (\((x,_),_) -> x==n) xs
cell :: Int -> Int -> [((Int,Int),a)] -> [a]
cell n m xs = map snd $ filter (\((x,y),_) -> (div x 2 == n) && (div y 2==m)) xs
here indexing the elements of 4x4 matrix
> let a = zipWith (\x y -> ((div y 4,mod y 4),x)) [0..15] [0..]
cells are 2x2 blocks
> cell 1 1 a
[10,11,14,15]
> cell 0 0 a
[0,1,4,5]
> column 2 a
[2,6,10,14]
> row 1 a
[4,5,6,7]

Related

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

Can't find error in code (Project Euler #11 (Haskell))

I can't seem to find out why my code isn't working. I think I'm correct and all the examples I've seen do the same thing I do. But when I execute it, I get a different answer. Could someone please help me in finding out what's wrong? (adj4 is my final answer)
type Grid = [[Integer]]
twentyGrid :: [Integer]
twentyGrid = [8,2,22,97,38,15,0,40,0,75,4,5,7,78,52,12,50,77,91,8,49,49,99,40,17,81,18,57,60,87,17,40,98,43,69,48,4,56,62,0,81,49,31,73,55,79,14,29,93,71,40,67,53,88,30,3,49,13,36,65,52,70,95,23,4,60,11,42,69,24,68,56,1,32,56,71,37,2,36,91,22,31,16,71,51,67,63,89,41,92,36,54,22,40,40,28,66,33,13,80,24,47,32,60,99,3,45,2,44,75,33,53,78,36,84,20,35,17,12,50,32,98,81,28,64,23,67,10,26,38,40,67,59,54,70,66,18,38,64,70,67,26,20,68,2,62,12,20,95,63,94,39,63,8,40,91,66,49,94,21,24,55,58,5,66,73,99,26,97,17,78,78,96,83,14,88,34,89,63,72,21,36,23,9,75,0,76,44,20,45,35,14,0,61,33,97,34,31,33,95,78,17,53,28,22,75,31,67,15,94,3,80,4,62,16,14,9,53,56,92,16,39,5,42,96,35,31,47,55,58,88,24,0,17,54,24,36,29,85,57,86,56,0,48,35,71,89,7,5,44,44,37,44,60,21,58,51,54,17,58,19,80,81,68,5,94,47,69,28,73,92,13,86,52,17,77,4,89,55,40,4,52,8,83,97,35,99,16,7,97,57,32,16,26,26,79,33,27,98,66,88,36,68,87,57,62,20,72,3,46,33,67,46,55,12,32,63,93,53,69,4,42,16,73,38,25,39,11,24,94,72,18,8,46,29,32,40,62,76,36,20,69,36,41,72,30,23,88,34,62,99,69,82,67,59,85,74,4,36,16,20,73,35,29,78,31,90,1,74,31,49,71,48,86,81,16,23,57,5,54,1,70,54,71,83,51,54,69,16,92,33,48,61,43,52,1,89,19,67,48]
rows :: Int -> [Integer] -> Grid --split grid into rows of length n
rows n [] = []
rows n xs = (take n xs):(rows n (drop n xs))
cols :: Int -> [Integer] -> Grid
cols n = (transpose.rows n)
rowGrid :: Grid
rowGrid = rows 20 twentyGrid
colGrid :: Grid
colGrid = cols 20 twentyGrid
getDiag :: Grid-> [Integer] --get a diagonal
getDiag [] = []
getDiag xss
| head xss == [] = []
| otherwise = ((head.head) xss) : (getDiag ((map(drop 1).(drop 1)) xss))
adjac :: Int -> [Integer] -> [[Integer]] -- get all possible combinations of n numbers
adjac 0 xs = []
adjac n [] = []
adjac n (x:xs)
| length (x:xs) > n = (take n (x:xs)) : (adjac n xs)
| otherwise = [x:xs]
diags :: Grid -> Grid
diags [] = []
diags (xs:xss)
| (xs == []) = []
| otherwise =(getDiag (xs:xss)): (diags (map (drop 1) (xs:xss)))
upDiag :: Grid --get upper diaonals
upDiag = diags rowGrid
lowDiag :: Grid -- get lower diagonals
lowDiag = diags colGrid
allCells :: Grid --every diagonal column and row merged together
allCells = rowGrid ++ colGrid ++ upDiag ++ lowDiag
adj4 :: Integer --find largest product of 4 adjacent numbers
adj4 = (maximum.map maximum.map (map product).map (adjac 4)) allCells
testAdj :: [[Integer]]
testAdj = (map (map product).map (adjac 4)) allCells
It looks like you are handling the diagonals that go from upper left to lower right, both above the main diagonal (upDiag) and below the main diagnoal (lowDiag). However, you don't seem to be handling diagonals in the other direction. For example, if you look in the top-left corner of the grid:
08 02 22 97
49 49 99 40 ...
81 49 31 73
52 70 95 23
...
you have no code checking diagonals like the bolded one.

Haskell print out 2d array

I'm trying to print out my 2d array in game of life, but i'm not quite sure how to go on with it. So I need some help with my printArray function I'm not quite sure how to proceed. Her is the code below, everything is working.. Except printing it out in the right manner.
module GameOfLife where
import Data.List
import System.IO
import Text.Show
import Data.Array
import System.Random
width :: Int
width = 5
height :: Int
height = 5
data State = Alive | Dead deriving (Eq, Show)
type Pos = (Int,Int)
type Board = Array Pos State
startBoard :: Pos -> Board
startBoard (width,height) =
let bounds = ((0,0),(width - 1,height - 1))
in array bounds $ zip (range bounds) (repeat Dead)
set :: Board -> [(Pos,State)] -> Board
set = (//)
get :: Board -> [Pos] -> [State]
get board pos = map (board!) pos
neighbours :: Board -> Pos -> [Pos]
neighbours board c#(x,y) =
filter (/= c) $ filter (inRange (bounds board)) [(x',y') | x' <- [x -
1..x + 1], y' <- [y - 1..y + 1]]
nextGen :: Board -> Board
nextGen board =(irrelevant code for the question..)
printArray :: Board -> String
printArray arr =
unlines [unwords [show (arr ! (x, y)) | x <- [1..5]] | y <- [1..5]]
My output:
[((0,0),Dead),((0,1),Dead),((0,2),Dead),((0,3),Dead),((1,0),Dead),
((1,1),Dead),((1,2),Dead),((1,3),Dead),((2,0),Dead),((2,1),Dead),
((2,2),Dead)2,3),Dead)]
My preferable output:
1 2 3 4 5
1 . . . . .
2 n n n . .
3 n X n . .
4 n n n . .
5 . . . . .
To start to answer your question, I suggest breaking the problem into several pieces:
Print out the numbers across the top.
Number each row as you print them.
Decide what symbol to print in each cell.
Tackle each of these pieces one at a time. If it helps, rather than think in terms of "printing" just build up a String object. Once you have a String, printing is pretty trivial.

How can you quickly map the indices of a banded matrix to a 1-dimensional array?

This is closely related to a the question: How to map the indexes of a matrix to a 1-dimensional array (C++)?
I need to assign a reversible index to each non-zero element in a banded matrix.
In the normal, full matrix it is easy to do:
|-------- 5 ---------|
Row ______________________ _ _
0 |0 1 2 3 4 | |
1 |5 6 7 8 9 | 4
2 |10 11 12 13 14| |
3 |15 16 17 18 19| _|_
|______________________|
Column 0 1 2 3 4
To find the array index we just use the following bijective formula:
matrix[ i ][ j ] = array[ i*m + j ]
In my case, we have a symmetrically banded matrix with some constraint on distance from the diagonal. For example, the following uses an upper and lower bound of 1:
|-------- 5 ---------|
Row ______________________ _ _
0 |0 1 X X X | |
1 |2 3 4 X X | 4
2 |X 5 6 7 X | |
3 |X X 8 9 10| _|_
|______________________|
Column 0 1 2 3 4
In this case, I want to assign an index position to each element within the bandwidth, and ignore everything outside. There are a couple of ways to do this, one of which is to create a list of all the acceptable indices ix's, and then use map lookups to quickly go back and forth between a (row,col) pair and a singular index:
ix's :: [(Int,Int)] -- List of all valid indices
lkup :: Map (Int,Int) Int
lkup = M.fromList $ zip ix's [0..]
rlkup :: Map Int (Int, Int)
rlkup = M.fromList $ zip [0..] ix's
fromTup :: (Int, Int) -> Int
fromTup tup = fromMaybe 0 $ M.lookup tup lkup
toTup :: Int -> (Int, Int)
toTup i = fromMaybe (0,0) $ M.lookup i rlkup
For large matrices, this leads to a huge number of map lookups, which causes a bottleneck. Is there a more efficient formula to translate between the valid addresses, k, and (row,col) pairs?
You might find it more straightforward to "waste" a few indexes at the beginning and end of the matrix, and so assign:
Row ______________________ _ _
0 (0) |1 2 X X X | |
1 |3 4 5 X X | 4
2 |X 6 7 8 X | |
3 |X X 9 10 11 | _|_
|______________________|
Column 0 1 2 3 4
where (0) is an ignored index.
This is similar to the band matrix representation used by the highly respected LAPACK library.
You just need to take care that the unused elements are properly ignored when performing operations where they might affect used elements. (For example, a fast fill routine can be written without regard to which elements are used or unused; but a matrix multiplication would need to take a little more more care.)
If you take this approach, then the bijections are pretty simple:
import Data.Char
import Data.Maybe
type Index = Int
-- |(row,col) coordinate: (0,0) is top level
type Coord = (Int, Int)
-- |Matrix dimensions: (rows, cols, edges) where edges gives
-- the count of auxiliary diagonals to *each side* of the main
-- diagonal (i.e., what you call the maximum distance), so the
-- total band width is 1+2*edges
type Dims = (Int, Int, Int)
-- |Get index for (row,col)
idx :: Dims -> Coord -> Index
idx (m, n, e) (i, j) = let w = 1+2*e in w*i+(j-i+e)
-- |Get (row,col) for index
ij :: Dims -> Index -> Coord
ij (m, n, e) idx = let w = 1+2*e
(i, j') = idx `quotRem` w
in (i, j'+i-e)
--
-- test code
--
showCoords :: Dims -> [(Coord, Char)] -> String
showCoords (m, n, _) cs =
unlines $
for [0..m-1] $ \i ->
for [0..n-1] $ \j ->
fromMaybe '.' $ lookup (i,j) cs
where for = flip map
test :: Dims -> IO ()
test dm#(m,n,_) = do
putStrLn $ "Testing " ++ show dm
let idxs = [0..]
-- get valid index/coordinates for this matrix
let cs = takeWhile (\(_, (i,j)) -> i<m || j<n)
$ filter (\(_, (i,j)) -> i>=0 && j>=0)
$ map (\ix -> (ix, ij dm ix)) idxs
-- prove the coordinates are right
putStr $ showCoords dm (map (\(ix, (i,j)) -> ((i,j), chr (ord 'A' + ix))) cs)
-- prove getIndex inverts getCoord
print $ all (\(ix, (i,j)) -> idx dm (i,j) == ix) cs
putStrLn ""
main = do test (4, 5, 1) -- your example
test (3, 8, 2) -- another example

Converting list of base 3 digits to corresponding numerical value in Haskell

Below I have defined a function that converts a list of base-3 digits to the corresponding numerical value. For example:
f "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0) = 19
f "12" = 5
f "1202" = 47
f "120221" = 430
Here is a definition using comprehension:
f :: String -> Int
f str = sum (listToFinal (stringToTuples str))
Helper functions:
-- 1) converts "201" to "102"
reverse "str"
-- 2) converts "102" to 102
stringToInt :: String -> Int
stringToInt str = read str :: Int
-- 3) converts 102 to ['1','0','2']
intToList :: Int -> [Int]
intToList 0 = []
intToList x = intToList (x `div` 10) ++ [x `mod` 10]
-- 4) converts "201" to [(1,0),(0,1),(2,2)] using reverse, stringToInt, intToList
stringToTuples :: String -> [(Int,Int)]
stringToTuples str = zip (intToList (stringToInt (reverse str))) [0..]
-- 5) converts [(1,0),(0,1),(2,2)] to [1*3^0, 0*3^1, 2*3^2]
listToFinal :: [(Int,Int)] -> [Int]
listToFinal list = [ x * (3^y) | (x,y) <- list ]
Now I'd like to do it with recursion only (well, using basic & library functions too, of course).
An idea: I was thinking of taking the head of each element in the list and simply multiplying it with 3^(length of string - 1). The only problem is, with each recursive call the power of three would have to decrease by 1, e.g. given:
recursive_version "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0)
How to implement this?
Here is a much simpler approach; note that, through the use of foldl, it's only "implicitly" recursive, though. For information, digitToInt is exported by Data.Char.
import Data.Char
import Data.List ( foldl' )
--- horner x xs : the value of polynomial 'xs' at point 'x'
horner :: Int -> [Int] -> Int
horner x = foldl' (\c1 c0 -> c1 * x + c0) 0
-- f s : the integer whose representation in base 3 is string 's'
f :: String -> Int
f = horner 3 . map digitToInt
When you define it recursively, the natural way to decrement the length is trimming the array from the head. For example:
base3 x = base3' x 0 where
base3' (d:ds) v = base3' ds $ v + d * 3 ^ length ds
base3' [] v = v

Resources