Numbering some integer partitions - haskell
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]
Related
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
Convert a list of position,value tuples into a single list
I am writing some code to work with arbitrary radix numbers in haskell. They will be stored as lists of integers representing the digits. I almost managed to get it working, but I have run into the problem of converting a list of tuples [(a_1,b_1),...,(a_n,b_n)] into a single list which is defined as follows: for all i, L(a_i) = b_i. if there is no i such that a_i = k, a(k)=0 In other words, this is a list of (position,value) pairs for values in an array. If a position does not have a corresponding value, it should be set to zero. I have read this (https://wiki.haskell.org/How_to_work_on_lists) but I don't think any of these methods are suitable for this task. baseN :: Integer -> Integer -> [Integer] baseN n b = convert_digits (baseN_digits n b) chunk :: (Integer, Integer) -> [Integer] chunk (e,m) = m : (take (fromIntegral e) (repeat 0)) -- This is broken because the exponents don't count for each other's zeroes convert_digits :: [(Integer,Integer)] -> [Integer] convert_digits ((e,m):rest) = m : (take (fromIntegral (e)) (repeat 0)) convert_digits [] = [] -- Converts n to base b array form, where a tuple represents (exponent,digit). -- This works, except it ignores digits which are zero. thus, I converted it to return (exponent, digit) pairs. baseN_digits :: Integer -> Integer -> [(Integer,Integer)] baseN_digits n b | n <= 0 = [] -- we're done. | b <= 0 = [] -- garbage input. | True = (e,m) : (baseN_digits (n-((b^e)*m)) b) where e = (greedy n b 0) -- Exponent of highest digit m = (get_coef n b e 1) -- the highest digit -- Returns the exponent of the highest digit. greedy :: Integer -> Integer -> Integer -> Integer greedy n b e | n-(b^e) < 0 = (e-1) -- We have overshot so decrement. | n-(b^e) == 0 = e -- We nailed it. No need to decrement. | n-(b^e) > 0 = (greedy n b (e+1)) -- Not there yet. -- Finds the multiplicity of the highest digit get_coef :: Integer -> Integer -> Integer -> Integer -> Integer get_coef n b e m | n - ((b^e)*m) < 0 = (m-1) -- We overshot so decrement. | n - ((b^e)*m) == 0 = m -- Nailed it, no need to decrement. | n - ((b^e)*m) > 0 = get_coef n b e (m+1) -- Not there yet. You can call "baseN_digits n base" and it will give you the corresponding array of tuples which needs to be converted to the correct output
Here's something I threw together. f = snd . foldr (\(e,n) (i,l') -> ( e , (n : replicate (e-i-1) 0) ++ l')) (-1,[]) f . map (fromIntegral *** fromIntegral) $ baseN_digits 50301020 10 = [5,0,3,0,1,0,2,0] I think I understood your requirements (?) EDIT: Perhaps more naturally, f xs = foldr (\(e,n) fl' i -> (replicate (i-e) 0) ++ (n : fl' (e-1))) (\i -> replicate (i+1) 0) xs 0
I/O how can i put somehing in screen withouth being string?
So im doing this function and i need her to display on the screen the result of (premio ap x) , the problem is that (premio ap x)::Maybe Int , so its not a string. joga :: Aposta -> IO () joga x= do ap <- leAposta; let arroz = (premio ap x) putStr ^^^^^^^^^^ return () How can i convert this to a string? Or there is another way to display on the screen things that are not strings. update :full code comuns :: Aposta -> Aposta -> (Int,Int) comuns (Ap a (b,c)) (Ap k (l,ç)) = (cnum a k, cnum [b,c] [l,ç]) cnum::[Int]->[Int]->Int cnum [] l2 = 0 cnum (x:xs) l2 | elem x l2 = 1 + cnum xs l2 |otherwise = cnum xs l2 premio :: Aposta -> Aposta -> Maybe Int premio l1 l2 | x == (5,2)= Just 1 | x == (5,1)= Just 2 | x == (5,0)= Just 3 | x == (4,2)= Just 4 | x == (4,1)= Just 5 | x == (4,0)= Just 6 | x == (3,2)= Just 7 | x == (2,2)= Just 8 | x == (3,1)= Just 9 | x == (3,0)= Just 10 | x == (1,2)= Just 11 | x == (2,1)= Just 12 | x == (2,0)= Just 13 |otherwise = Nothing where x = comuns l1 l2 leAposta :: IO Aposta leAposta = do putStrLn "Insira como lista as 5 estrelas" num <-getLine putStrLn "Insira em par as 2 estrelas" es<-getLine let ap = (Ap (read num) (read es)) if (valida ap) then return ap else do putStrLn "Aposta invalida" leAposta
Since arroz is premio ap x which has type Maybe Int, you can simply print arroz. print works on any type that can be printed, i.e. on those types in class Show. (You probably don't want to use print on values that are already strings, though, since that will print the escaped string, with quotes around. Use putStr and putStrLn for strings.)
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
An haskell "exp" function returns a wrong result
the following code: Module Main where main :: IO () main = do putStrLn "hello" putStrLn $ "2 exp 6 = " ++ show (2 `exp1` 6) exp1 :: Integer -> Integer -> Integer exp1 x n | n == 0 = 1 | n == 1 = x | even n = exp1 (x*x) m | odd n = x * exp1 (x*x) (m-1) where m = n `div` 2 produces the output 4 for 2 `exp1` 6, which is obviously wrong. thanks
The odd case is wrong. You end up evaluating exp1 4 3 to be 4 * (exp1 16 0).