Printing a matrix with Haskell - haskell
I need to print out a matrix in haskell so it looks like this:
main> putStr (showMat [[1,-500,-4], [100,15043,6], [5,3,10]])
1 -500 -4
100 15043 6
5 3 10
So far I have come up with this:
type Matrix a = [[a]]
type IntMat = Matrix Integer
showMat :: IntMat -> String
showMat [] = ""
showMat ((y:ys):xs) = (printRow (rowmaxs) (elements) (y:ys)) ++ "\n" ++ showMat xs
where rowmaxs = rowMaxs ((y:ys):xs) ; elements = elementLengths (y:ys)
rowMaxs :: IntMat -> [Int]
rowMaxs [] = []
rowMaxs (x:xs) = [length (show (maximum (x)))] ++ (rowMaxs xs)
elementLengths :: [Integer] -> [Int]
elementLengths [] = []
elementLengths (y:ys) = [length (show y)] ++ (elementLengths ys)
printRow :: [Int] -> [Int] -> [Integer] -> String
printRow [] (a:as) (y:ys) = ""
printRow (z:zs) (a:as) [] = ""
printRow [] [] (y:ys) = ""
printRow [] [] [] = ""
printRow (z:zs) (a:as) (y:ys) = addSpaces (z-a) ++ show y ++ [' '] ++ printRow zs as ys
addSpaces :: Int -> String
addSpaces 0 = ""
addSpaces n = " " ++ addSpaces (n-1)
Which returns this:
Main> putStr (showMat [[1,23,1],[23,56,789],[1234,0,1]])
1 23 1
23 56
1234
I can see the loss of the elements at the end of rows is due to the cases in the printRow function, but I don't know how to fix it. Also the characters don't take into account the ones printed before them. Any help on how I can fix this would be appreciated.
I've written a small script some time ago that takes a tab-separated table (CSV style) and prettyprints it to the console. I've extracted the relevant parts and uploaded the source code here. For example, given your input
m = [[1,23,456],[78,-90,123],[4567,8,9]]
putStrLn $ showMat m will make it into
1 -500 -4
100 15043 6
5 3 10
There's also a function (commented out) at the very bottom if you want left alignment.
In showMat you calculate rowmaxs and elements anew for each row. In particular, rowmaxs has an element for each row left in the matrix, but printRow uses it as meaning something for each column of the matrix.
Edit: Here's a slightly better version of showMat:
showMat :: IntMat -> String
showMat rows = concat (map perRow rows)
where rowmaxs = rowMaxs rows
perRow cols = printRow rowmaxs elements cols ++ "\n"
where elements = elementLengths cols
It's still buggy --- rowMaxs (tries to) calculate the maximum length of the numbers in each row, but you really want the maximum length of the numbers in each column. One consequence of that is that you occasionally pass negative numbers to addSpaces, which doesn't cope terribly well, so here's a version of addSpaces that behaves more gracefully:
addSpaces :: Int -> String
addSpaces n = replicate n ' '
So now we get this:
*Main> putStr (showMat [[1,23,1],[23,56,789],[1234,0,1]])
1 23 1
23 56 789
1234 0 1
Better, but not yet working properly.
I have not fixed all the bugs in your code because I sense you are still learning and need the experience of finding them for yourself.
I advise using map/zipWith/zipWith3 instead of explicitly writing the recursion, as it makes code easier to understand.
Related
making permutation from two list but not using full number [closed]
Closed. This question needs debugging details. It is not currently accepting answers. Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question. Closed 3 years ago. Improve this question I want to create a list of all possible permutation from two list. However, I do not want to make with full length. For example, first list is ["a", "e", "i", "o" "u"] and second is [1, 2, 3, 4, 5] then one of the outcome would be like [["a",1,"i",2],["u",4,"e",s].....] listsOfPossibilitiesN ::[a] -> [a] -> [[a]] listsOfPossibilitiesN a b = case a of _ -> (listMakerN [] a b (length a) (length b) 0) -- | list = storage, and show at the end of loop, p1h = first list, p2h = second list, -- | count(x) = count to stop loop when the thing is fully rotated, depthCount = count to stop all loop when the depth reached 10 listMakerN :: [a] -> [a] -> [a] -> Integer -> Integer -> Integer -> [[a]] listMakerN list p1h p2h count1 count2 depthCount | depthCount == 10 = [list] | count1 == 0 = [] | otherwise = case p1h of ((x:xs)) -> (listMaker2N (list ++ [x]) xs p2h (count2 - 1) count2 (depthCount + 1)) ++ listMakerN list (xs ++ [x]) p2h (count1 - 1) count2 depthCount listMaker2N :: [a] -> [a] -> [a] -> Integer -> Integer -> Integer -> [[a]] listMaker2N list p1h p2h count1 count2 depthCount | depthCount == 10 = [list] | count2 == 0 = [] | otherwise = case p2h of ((x:xs)) -> (listMakerN (list ++ [x]) p1h xs count1 (count1 ) (depthCount + 1)) ++ listMaker2N list p1h (xs ++ [x]) count1 (count2 - 1) depthCount I made this function above (I am sorry for bad image. I finally could figure out how t put code in question), but it takes too long to get result. How do i do better?(Just to remind you, I am a beginner of programming) and, the output is: > listsOfPossibilitiesN [1,2,3,4,5,6,7,8,9,10] [100,200,300,400,500,600,700,800,900,1000] [[1,100,2,200,3,300,4,400,5,500],[1,100,2,200,3,300,4,400,5,600],[1,100,2,200,3,300,4,400,5,700],[1,100,2,200,3,300,4,400,5,800],[1,100,2,200,3,300,4,400,5,900],[1,100,2,200,3,300,4,400,5,1000],[1,100, 2,200,3,300,4,400,6,500],[1,100,2,200,3,300,4,400,6,600],[1,100,2,200,3,300,4,400,6,700],[1,100,2,200,3,300,4,400,6,800],[1,100,2,200,3,300,4,400,6,900],[1,100,2,200,3,300,4,400,6,1000],[1,100,2,200,3, 300,4,400,7,500],[1,100,2,200,3,300,4,400,7,600],..]
Making a guess at what your current code does, here's a proposal for an algorithm: nondeterministically pick a permutation of the vowels assign indices to the permutation use the standard tails trick to nondeterministically choose the appropriate number of elements from this list In code: import Data.List choose :: Int -> [a] -> [[a]] choose 0 xs = [[]] choose n xs = do x:xs' <- tails xs (x:) <$> choose (n-1) xs' assignments :: Int -> [a] -> [[(Int, a)]] assignments n xs = do xs' <- permutations xs choose n (zip [1..] xs') In ghci: > mapM_ print (assignments 2 "abc") [(1,'a'),(2,'b')] [(1,'a'),(3,'c')] [(2,'b'),(3,'c')] [(1,'b'),(2,'a')] [(1,'b'),(3,'c')] [(2,'a'),(3,'c')] [(1,'c'),(2,'b')] [(1,'c'),(3,'a')] [(2,'b'),(3,'a')] [(1,'b'),(2,'c')] [(1,'b'),(3,'a')] [(2,'c'),(3,'a')] [(1,'c'),(2,'a')] [(1,'c'),(3,'b')] [(2,'a'),(3,'b')] [(1,'a'),(2,'c')] [(1,'a'),(3,'b')] [(2,'c'),(3,'b')]
Haskell: Given a list of numbers and a number k, return whether any two numbers from the list add up to k
Given a list of numbers and a number k, return whether any two numbers from the list add up to k. For example, given [10, 15, 3, 7] and k of 17, return true since 10 + 7 is 17. The program must prompt the user for input. The program must accept the list as a collection of comma separated values. The values should all be integers. The input list can be between 1 and 42 number long. What I have done I have been able to input the list of integer as a list and seperated by commas but am not able to return true when 2 numbers add to k toList :: String -> [Integer] toList input = read ("[" ++ input ++ "]") main = do putStrLn "Enter a list of numbers (separated by comma):" input <- getLine print $ k (toList input)
There are following approaches. 1) Create a list pf pairs which are all combinations [(10,10),(10,15),..,(15,10),(15,3)..]. Now you can use simple any function on this list to check if any pair add up to given number. getCoupleList :: [a]->[(a,a)] getCoupleList [] = [] getCoupleList [x] = [] getCoupleList (x:xs) = map (\y->(x,y)) xs ++ getCoupleList xs getSumOfCoupleList :: Num a => [(a,a)]->[a] getSumOfCoupleList xs = map (\x -> fst x + snd x) xs isSum :: [Int]->Int->Bool isSum xs k = any (==k) $ (getSumOfCoupleList.getCoupleList) xs or directly check wuthout getSumOfCoupleList isSum xs k = any (\(a,b)-> a + b == k) $ (getSumOfCoupleList.getCoupleList) xs If you check creating the couple list and finding the sum in not needed. We can directly get the list of sum with simple changes. getSumList :: Num a=>[a]->[a] getSumList [] = [] getSumList [x] = [] getSumList (x:xs) = map (+x) xs ++ getSumList xs isSum1 :: [Int]->Int->Bool isSum1 xs k = any (==k) $ getSumList xs 2) Create another list from given list by subtracting every element from 17. Now just check if any number from first list is present in second. isSum2 :: [Int]->Int->Bool isSum2 xs k = let newList = map (k-) xs intersectList = xs `intersect` newList in not (null intersectList)
It's a naive method, not optimized and just show an example. toList :: String -> [Integer] toList input = read ("[" ++ input ++ "]") check :: Integer -> [Integer] -> Bool check k (x:xs) = if ((k-x) `elem` xs) then True else (check k xs) check k x = False main = do let k = 12 putStrLn "Enter a list of numbers (separated by comma):" input <- getLine print $ (check k (toList input))
I was recently asked the same exact question in an interview, here's one of my answer import util arr = [10, 15, 3, 8] k = 17 for i in range(0, len(arr)): arr_new.append(abs(arr[i] -17)) res= list(set(arr).intersection(arr_new)) if (len(res)>0): print(str(res[0]) + " + " + str(res[1]) +"= "+ str(k )) else: print("No numbers add up to k")
How to check if you are in the first iteration of a loop in Haskell?
I could understand if the question doesn't really clarify my problem, so here is some more explanation: I am trying to add the string "+" at the start of my string, which I get like this: printLine :: [Int] -> String --Type of the function printLine [] = "" --Base case printLine (x:xs) = "+" ++ foldr (++) "+" f ++ printLine xs where f = replicate x "-" The result I get from the above: +-----++------++------++------+ The result I would like to get: +-----+------+------+------+ Basically my question is: How do I add "+" only at the start? I can understand that this might be a silly question, but I am stuck for a while now and I can't find the answer on SO or elsewhere.
Proposal: don't detect when you're in the first iteration, which is hard; instead detect when you're in the last iteration, which is easy because it's the [] case in the first line. printLine :: [Int] -> String -- final iteration; add an extra + at the end printLine [] = "+" -- not the final iteration; don't include a + at the end of the -s printLine (x:xs) = "+" ++ replicate x '-' ++ printLine xs
If an empty list must map to an empty string, one option is to fold with a special case for an empty list. printLine :: [Int] -> String printLine [] = "" printLine xs = foldr (\x res -> '+' : replicate x '-' ++ res) "+" xs So that λ> map printLine [[], [1..4], [5]] ["","+-+--+---+----+","+-----+"] Alternatively, since the original question asked for control during the first iteration, one option is to use a helper function. Here are two alternatives. printLine' :: [Int] -> String printLine' [] = "" printLine' xs = '+' : go xs where go :: [Int] -> String go [] = "" go (n:ns) = replicate n '-' ++ "+" ++ go ns printLine'' :: [Int] -> String printLine'' xs = go True xs where go :: Bool -> [Int] -> String go _ [] = "" go isFirst (n:ns) = (if isFirst then "+" else "") ++ replicate n '-' ++ "+" ++ go False ns With these definitions λ> map printLine' [[], [1..4], [5]] ["","+-+--+---+----+","+-----+"] λ> map printLine'' [[], [1..4], [5]] ["","+-+--+---+----+","+-----+"]
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 Printing a List with some formatting
Just started learning Haskell a few days ago and I've come across a few issues. The first issue deals with printing a list of numbers. The desired behavior is as follows: input: [1,2,3,4,5,6] output: 1 2 3 | 4 5 6 So its a simple concept, I just need to output the elements of a list with the "|" symbol inserted between every three numbers, but I can't for the life of me figure it out. It seems like most of the stuff I've tried involves strings and even if I were able to get the list to strings such as ["1", "2", "3", ...] all the methods I've tried print the numbers each on their own line which is not what I need. Any help would be greatly appreciated.
Using the split package (recently added to the Haskell Platform): > import Data.List -- for intercalate > import Data.List.Split -- for chunksOf > intercalate " | " . map unwords . chunksOf 3 $ map show [1..7] "1 2 3 | 4 5 6 | 7" Relevant documentation: chunksOf, unwords, intercalate.
Here's one way. import Data.List (cycle) format :: Show a => [a] -> String format = concat . zipWith (++) ("" : cycle [" ", " ", " | "]) . map show This does has the drawback that the grouping into groups of three is hard-coded, but it is not too difficult to generalise.
You could do threes [] = "" threes xs = let (front,rest) = splitAt 3 xs in unwords (map show front) ++ if null rest then "" else " | " ++ threes rest giving *Main> threes [1..10] "1 2 3 | 4 5 6 | 7 8 9 | 10" Functions I used: splitAt :: Int -> [a] -> ([a], [a]) -- splitAt 2 "Hello Mum" = ("He","llo Mum") unwords :: [String] -> String -- unwords ["Hello","there","everyone"] -- = "Hello there everyone" null :: [a] -> Bool null [] = True null _ = False
The first part is the easiest, you need to convert the numbers to Strings, format :: (Num a, Show a) => [a] -> String format xs = result where strings = map show xs does that. Then we need to split any list into chunks of three (more general, n) elements. splitAt splits a list into a front part of the desired number of elements - if the list is long enough - and a remainder. Iterating the procedure on the remainder, while that is not empty leads to the desired result. chunk :: Int -> [a] -> [[a]] chunk _ [] = [] chunk n xs = ys : chunk n zs where (ys, zs) = splitAt n xs That is a recurring pattern, so there is a combinator for that, and we could also write import Data.List (unfoldr) chunk :: Int -> [a] -> [[a]] chunk n = unfoldr split where split [] = Nothing split xs = Just $ splitAt n xs So we can continue our format, format :: (Num a, Show a) => [a] -> String format xs = result where strings = map show xs chunks = chunk 3 strings Then we need to insert a "|" between all chunks, that is done by intercalate from Data.List, and finally, concatenate all strings with spaces between them, that's what unwords does, so format :: (Num a, Show a) => [a] -> String format xs = result where strings = map show xs chunks = chunk 3 strings result = unwords $ intercalate "|" chunks Or format = unwords . intercalate "|" . chunk 3 . map show