Pretty Printing list of lists - haskell

I have a list of lists:
[[5,1,0,0,5,5,0,0],[0,0,1,4,2,0,6,1],[1,1,6,3,0,1,0,0],[1,5,0,0,0,1,1,6]]
and a string "wxyz"
I would like to have:
1)
w: 5 1 0 0 5 5 0 0
x: 0 0 1 4 2 0 6 1
y: 1 1 6 3 0 1 0 0
z: 1 5 0 0 0 1 1 6
I wrote:
f c xs = putStrLn (c : ':' : ' ' : concat (intersperse " " $ map show xs))
to write one line
and 2)
g xxs c = mapM_ (f c) xxs
How can I modify 2) to loop through string "wxyz" in order to have 1) ?

Instead of mapM_, you can use zipWithM_ from Control.Monad:
g xss cs = zipWithM_ f cs xss
or, if you change the order of arguments in either f or g to match, you can do it with less "points":
g = zipWithM_ f
Also, concat (intersperse " " ...) is otherwise known as unwords ....

You can use zip and uncurry:
g xxs c = mapM_ (uncurry f) (zip xxs c)

Related

generate a list of numbers with increasing digit order

Hi I am trying to generate a list with
All possible n digit numbers
And their digits are in decreasing order
For example, if n = 3 the output will be [111 .. 321 .. 543 ..999].
My initial attempt was
--attempt1
digits n = map (\x -> read [x] :: Int) (show n)
sorted [] = True
sorted [x] = True
sorted (x:y:xs) = if x <= y then sorted (y:xs) else False
[ x | x <- [ 10^(n-1) .. 10^n ] , sorted $ digits $ x]
However this approach got slower exponentially as the variable n got bigger.
My second approach was (if n == 3)
joiner :: [Integer] -> Integer
joiner = read . concatMap show
[ joiner [z,y,x] |
x <- [1..9],
y <- [9,8..x],
z <- [9,8..y]]
However now the problem is how I can generalise this code to an arbitrary n
joiner :: [Integer] -> Integer
joiner = read . concatMap show
[ joiner [a_n,...,a_1] |
a_1 <- [1..9],
a_2 <- [9,8..x],
.
.
.
a_n <- [9,8..a_n-1]
]
Thank you!
Every time you need to combine N of something (where N is unknown upfront), the answer is always recursion. After all, that's the only way to iterate in Haskell.
First, we'll need a way to append another digit to a given number. Simple enough:
appendDigit x = [ x*10 + d | d <- [0..9] ]
Let's test it out:
λ appendDigit 2
[20,21,22,23,24,25,26,27,28,29]
λ appendDigit 3
[30,31,32,33,34,35,36,37,38,39]
But not good enough: we only need to append digits that are less than the last one. Well, easy to modify:
appendDigit x = [ x*10 + d | d <- [0..(lastDigit-1)] ]
where lastDigit = x `mod` 10
Try it out:
λ appendDigit 2
[20,21]
*Main Lib
λ appendDigit 3
[30,31,32]
*Main Lib
λ appendDigit 8
[80,81,82,83,84,85,86,87]
And now all that remains is just to do it N times, concatenating resulting lists along the way:
decDigits 0 = [] -- degenerate case: when N = 0, there are no such numbers
decDigits 1 = [0..9] -- base case: N = 1
decDigits n = concatMap appendDigit $ decDigits (n-1)

Suggestion on the hackerRank solution about alphabets and weight

I have solved the designer pdf question with haskell. The code works. I am posting the code here to know how I could have done it better.
First line contains the weight of each alphabet
Second line contains the word.
Sample input
1 3 1 3 1 4 1 3 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 7
zaba
Output
28
explanation each character would take 1 space and multiply it with the max weight
4 characters * 1 space * 7 weight = 28
'z' has the max weight of 7.
Code
import Data.List
import Data.Maybe
getintval::(Maybe Int) -> Int
getintval Nothing = 1
getintval (Just x) = x
solve'::[Char]->[(Char, Int)] -> Int
solve' ch lst = k $ map getintval $ map (\x -> finder' x) ch
where
k::[Int] -> Int
k fb = (*) (length ch) $ foldl (\acc x -> max acc x) 1 fb
finder'::Char -> Maybe Int
finder' g = case i of
Just(x1,x2) -> Just x2
Nothing -> Just 1
where i = find(\(val1, val2) -> val1 == g) lst
solve::[Char] -> [Char] -> Int
solve wght val = solve' val rec
where
rec::[(Char, Int)]
rec = zipWith (\x y -> (x, y)) ['a'..'z'] word1
word1::[Int]
word1 = map(read::String->Int) $ words wght
main::IO()
main = do
weight <- getLine
pdfstr <- getLine
putStr . show $ solve weight pdfstr
All the test on HackerRank are success

Numbering some integer partitions

These trees represent the integer partitions of n <= 5 with at most m = 3 parts.
1 2 3 4 5
| / \ / \ |
| / \ / \ |
| / \ / \ |
1,1 2,1 2,2 3,1 3,2 4,1
| | | |
| | | |
| | | |
1,1,1 2,1,1 2,2,1 3,1,1
Let's enumerate them from top to bottom and left to right:
1 2 3 4 5
6 7 8 9 10 11
12 13 14 15
I need a list D such that D!!i is, if P is the partition numbered by i, the number of the partition P ++ [1]. That is, for this example,
D!!1 = 6, because (1,1) has number 6
D!!2 = 7 because (2,1) has number 7.
D!!3 = 9 because (3,1) has number 9.
D!!4 = 11 because (4,1) has number 11.
D!!5 = "nothing" because there's no child (5,1).
D!!6 = 12 because (1,1) has number 6 and (1,1,1) has number 12.
And so on, D!!7 = 13, D!!8 = 14, and D!!9 = 15.
I have absolutely no idea how to start. I know SO is not a code writing service but I'm asking only for any hints.
EDIT
Here is an attempt.
dico' :: Int -> Int -> Seq (Maybe Int)
dico' m n = go 1 S.empty
where
go :: Int -> Seq (Maybe Int) -> Seq (Maybe Int)
go k d'
| k == n-1 = d'
| otherwise = go (k+1) (inner 0 [0] [m] [m] 0 d')
where
inner :: Int -> [Int] -> [Int] -> [Int] -> Int -> Seq (Maybe Int) -> Seq (Maybe Int)
inner i a b c end d
| i >= length a = d -- what is the terminating condition here ?
| otherwise = if b!!i > 0
then let l = min (b!!i) (c!!i) in
let dd = d |> (Just $ end+1) in
inner (i+1) (a ++ [end + 1 .. end + l]) (b ++ map (\x -> b!!i - x) [1 .. l]) (c ++ [1 .. l]) (end + l) dd
else inner (i+1) a b c end (d |> Nothing)
It works except that the result is too long. I don't find the appropriate terminating condition of the inner loop.
> dico' 5 3
fromList [Just 1,Just 6,Just 7,Just 9,Just 11,Nothing,Just 12,Just 13,Just 14,Just 15,Nothing,Nothing,Just 16,Just 17,Nothing,Nothing,Just 18,Nothing,Nothing]
EDIT 2
Ok I get it now. I'm still interested in any improvement.
a008284_tabl :: [[Int]]
a008284_tabl = [1] : f [[1]]
where
f xss = ys : f (ys : xss)
where
ys = map sum (zipWith take [1..] xss) ++ [1]
_P :: Int -> Int -> Int
_P m n = sum (concatMap (take (min m n)) (take m a008284_tabl))
dico' :: Int -> Int -> Seq (Maybe Int)
dico' m n = go 1 S.empty
where
pmn = Just $ Just $ _P m n
go :: Int -> Seq (Maybe Int) -> Seq (Maybe Int)
go k d'
| k == n-1 = d'
| otherwise = go (k+1) (inner 0 [0] [m] [m] 0 d')
where
inner :: Int -> [Int] -> [Int] -> [Int] -> Int -> Seq (Maybe Int)
-> Seq (Maybe Int)
inner i a b c end d
| S.lookup (S.length d - 1) d == pmn = d
| otherwise = let bi = b!!i in
if bi > 0
then let l = min bi (c!!i) in
let dd = d |> (Just $ end+1) in
let range1l = [1 .. l] in
inner (i+1) (a ++ [end + 1 .. end + l])
(b ++ map (\x -> bi - x) range1l)
(c ++ range1l) (end + l) dd
else inner (i+1) a b c end (d |> Nothing)
> dico' 5 3
fromList [Just 1,Just 6,Just 7,Just 9,Just 11,Nothing,Just 12,Just 13,Just 14,Just 15]
> dico' 10 7
fromList [Just 1,Just 11,Just 12,Just 14,Just 17,Just 21,Just 26,Just 30,Just 33,Just 35,Nothing,Just 36,Just 37,Just 38,Just 40,Just 41,Just 43,Just 46,Just 47,Just 49,Just 52,Just 54,Just 55,Just 57,Just 59,Nothing,Just 60,Just 61,Just 63,Nothing,Just 64,Just 65,Nothing,Just 66,Nothing,Nothing,Just 67,Just 68,Just 69,Just 70,Just 72,Just 73,Just 74,Just 76,Just 77,Just 79,Just 80,Just 81,Just 82,Just 84,Just 85,Nothing,Just 86,Nothing,Just 87,Just 88,Just 89,Just 90,Nothing,Nothing,Just 91,Just 92,Nothing,Nothing,Just 93,Nothing,Nothing,Just 94,Just 95,Just 96,Just 97,Just 98,Just 100,Just 101,Just 102,Just 103,Just 104,Just 105,Nothing,Nothing,Just 106,Just 107,Just 108,Nothing,Just 109,Nothing,Nothing,Just 110,Just 111,Nothing,Nothing,Just 112,Nothing,Nothing,Just 113,Just 114,Just 115,Just 116,Just 117,Nothing,Just 118,Just 119,Just 120,Nothing,Just 121,Nothing,Just 122,Just 123,Nothing,Nothing,Just 124,Nothing,Nothing,Just 125,Just 126,Just 127,Just 128,Nothing,Just 129,Just 130,Nothing,Nothing,Just 131]

Implementing the ruler function using `streamInterleave`

I am doing the homework of CIS 194. The problem is to implement the ruler function by using streamInterleave. The code looks like
data Stream a = Cons a (Stream a)
streamRepeat :: a -> Stream a
streamRepeat x = Cons x (streamRepeat x)
streamMap :: (a -> b) -> Stream a -> Stream b
streamMap f (Cons x xs) = Cons (f x) (streamMap f xs)
streamInterleave :: Stream a -> Stream a -> Stream a
streamInterleave (Cons x xs) ys = Cons x (streamInterleave ys xs)
ruler :: Stream Integer
ruler = streamInterleave (streamRepeat 0) (streamMap (+1) ruler)
I am really confused why ruler can be implemented like this. Is this going to give me [0,1,0,1....]?
Any help will be greatly appreciated. Thank you!!
Firstly, we'll represent a Stream like this:
a1 a2 a3 a4 a5 ...
Now, let's take the definition of ruler apart:
ruler :: Stream Integer
ruler = streamInterleave (streamRepeat 0) (streamMap (+1) ruler)
In Haskell, an important point is laziness; that is, stuff doesn't need to be evaluated until it needs to be. This is important here: it's what makes this infinitely recursive definition work. So how do we understand this? We'll start with the streamRepeat 0 bit:
0 0 0 0 0 0 0 0 0 ...
Then this is fed into a streamInterleave, which interleave this the with (as yet unknown) stream from streamMap (+1) ruler (represented with xs):
0 x 0 x 0 x 0 x 0 x 0 x ...
Now we'll start filling in those xs. We know already that every second element of ruler is 0, so every second element of streamMap (+1) ruler must be 1:
1 x 1 x 1 x 1 x 1 x ... <--- the elements of (streamMap (+1) ruler)
0 1 0 x 0 1 0 x 0 1 0 x 0 1 0 x 0 1 0 x ... <--- the elements of ruler
Now we know every second element out of each group of four (so numbers 2,6,10,14,18,...) is 1, so the corresponding elements of streamMap (+1) ruler must be 2:
1 2 1 x 1 2 1 x 1 2 ... <--- the elements of (streamMap (+1) ruler)
0 1 0 2 0 1 0 x 0 1 0 2 0 1 0 x 0 1 0 2 ... <--- the elements of ruler
Now we know that every fourth element out of each group of eight (so numbers 4,12,20,...) is 2 so the corresponding elements of streamMap (+1) ruler must be 3:
1 2 1 3 1 2 1 x 1 2 ... <--- the elements of (streamMap (+1) ruler)
0 1 0 2 0 1 0 3 0 1 0 2 0 1 0 x 0 1 0 2 ... <--- the elements of ruler
And we can continue building ruler like this ad infinitum, by substituting back each n/2, 3n/2, 5n/2, ... numbered value of ruler.
In Haskell notation, with [] in place of Stream (which is isomorphic to infinite lists),
ruler = interleave (repeat 0)
(map (+1) ruler)
[ruler !! i | i <- [0..]] == concat . transpose $
[ repeat 0
, map (+1) ruler]
Splitting the ruler into two alternating sub-sequences to match, we get
[ruler !! 2*i | i <- [0..]] == repeat 0
== [0 | i <- [0..]] -- {0} --
[ruler !! 2*i+1 | i <- [0..]] == map (+1) ruler
== map (+1) $ concat . transpose $
[ [ruler !! 2*i | i <- [0..]]
, [ruler !! 2*i+1 | i <- [0..]]]
concat . transpose $ == concat . transpose $
[[ruler !! 2*i+1 | i <- [0,2..]] [ [1 | i <- [0..]]
,[ruler !! 2*i+1 | i <- [1,3..]]] , [1 + ruler !! 2*i+1 | i <- [0..]]]
Splitting again,
[ruler !! 4*i+1 | i <- [0..]] == [1 | i <- [0..]] -- {1} --
[ruler !! 4*i+3 | i <- [0..]] == concat . transpose $
[ [1 + ruler !! 2*i+1 | i <- [0,2..]]
, [1 + ruler !! 2*i+1 | i <- [1,3..]]]
and again,
[ruler !! 8*i+3 | i <- [0..]] == [2 | i <- [0..]] -- {2} --
[ruler !! 8*i+7 | i <- [0..]] == ....
You should be able to see it through from here:
.... 16*i+7 ..... 3 -- {3} --
.... 32*i+15 ..... 4 -- {4} --
.... 64*i+31 .....
....
Thus,
ruler !! 2^(k+1)*i + 2^k - 1 == k , k <- [0..] , i <- [0..]
0: i => 2i
1: 2i+1 => 4i+1
2: 4i+3 => 8i+3
3: 8i+7 => 16i+7
4: 16i+15 => ....
5:

Matrix Identity in haskell without list

I want to make an Identity matrix without list syntax or list functions for eg something with tuple (x,x) ...and i want to print it like
*> showMatrix (matrixIdentity 4)
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Here is a trick to create an identity matrix
import Data.List.Split(splitEvery)
identity n = splitEvery n $ take (n*n) $ concat $ replicate n (1:replicate n 0)
Now, to get the output in that format you can
putStr $ unlines $ map (unwords . map show) (identity 3)
to package these all
import Data.List.Split(splitEvery)
data IdentityMatrix = I Int
showMatrix :: IdentityMatrix -> IO ()
showMatrix (I n) = putStr $ unlines $ map (unwords . map show) identity
where identity = splitEvery n $ take (n*n) $ concat $ replicate n (1:replicate n 0)
> showMatrix (I 4)
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Resources