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 have a list of lists, for example,
[[1, 1, 1, 1],
[0, 0, 0, 0],
[1, 1, 0, 0],
[0, 0, 1, 1]]
with an even length. Like a square of pixels where black is 1 and white is 0, like a chessboard.
And I want a function that will return 4 lists:
The first list is 2x2 lower right corner would be a list with [1,1,0,0]
The second list is 2x2 upper right corner would be a list with [1,1,0,0]
The third list is 2x2 lower left corner would be a list with [0,0,1,1]
The forth list is 2x2 upper left corner would be a list with [1,1,0,0]
I don't quite yet know how to do this. I expect to receive the 4 lists described above.
The following is working for me, assuming I have now understood your requirements. There may be more sophisticated ways to do this, but this is a simple one which isn't too painful - the key is to write general functions which can take the first/second half of a list of even length. Then the functions you want are built simply from them:
firstHalf :: [a] -> [a]
firstHalf xs
| odd n = error "list needs to have even length"
| otherwise = take h xs
where n = length xs
h = n `div` 2
secondHalf :: [a] -> [a]
secondHalf xs
| odd n = error "list needs to have even length"
| otherwise = drop h xs
where n = length xs
h = n `div` 2
topLeftCorner :: [[a]] -> [a]
topLeftCorner = concatMap firstHalf . firstHalf
topRightCorner :: [[a]] -> [a]
topRightCorner = concatMap secondHalf . firstHalf
bottomLeftCorner :: [[a]] -> [a]
bottomLeftCorner = concat . reverse . map firstHalf . secondHalf
bottomRightCorner :: [[a]] -> [a]
bottomRightCorner = concat . reverse . map secondHalf . secondHalf
allCorners :: [[a]] -> [[a]]
allCorners board = [bottomRightCorner, topRightCorner, bottomLeftCorner, topLeftCorner] <*> [board]
examples of using it, first for your input and then a 6x6 example:
*Main>let board = [[1,1,1,1], [0,0,0,0], [1 ,1, 0,0] , [0, 0, 1,1]]
*Main> allCorners board
[[1,1,0,0],[1,1,0,0],[0,0,1,1],[1,1,0,0]]
*Main> let board = [[1,1,1,1,1,1], [0,0,0,0,0,0], [1 ,1, 0,0,1,1] , [0, 0, 1,1,0,0], [1,1,1,1,1,1], [0,0,0,0,0,0]]
*Main>allCorners board
[[0,0,0,1,1,1,1,0,0],[1,1,1,0,0,0,0,1,1],[0,0,0,1,1,1,0,0,1],[1,1,1,0,0,0,1,1,0]]
As often in functional programming (and indeed in programming in general), the best way to approach a more complex problem is to break it down into smaller ones.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have these exercises
Define a function to count the total negative numbers in a list. ##
I've tried this
negative :: [Int] -> Int
negative list = [ x | x <- list, if list<0 then x=1 else x=0]
And also
Define the function
choose :: Int -> [Int] -> [Int]
that chooses all occurrences of an integer n in a list. For example
chooses 1 [1, 2, 1, 4, 5, 1] results in [1, 1, 1] choosing 1 [2, 3, 4, 6] results []
I've tried this
choose :: Int->[Int]->[Int]
choose xs ys s [rep-rep<-xs,z<-ys,rep-z]
Or
rep ::Int->[Int]->[Int]
rep _ [][]
rep a (b:bs)-a-b-a:rep a []
|otherwise-rep a (bs)
rp :: [Int] -> [Int] -> [Int]
rp [] (ys)[]
rp (x:xs) (ys)-k++rp (xs) (ys)
where k'rep x (ys)
My teacher never explained this to us that's why I have these doubts, I'm new to haskell
The expression:
negative :: [Int] -> Int
negative list = [ x | x <- list, if list<0 then x=1 else x=0]
Makes no sense for several reasons:
the result type is an Int, so by using list comprehension as outer expression, you are generating a list;
x is an element of the list x <- list, if list < 0 then … else … makes no sense since list is a list, and can not be compared with a single element; and
variables can not be assigned a new value. Variables are defined once, here by x <- list. You can make a more locally scoped variable with the same name, but that is not a good idea here.
You can just use filter :: (a -> Bool) -> [a] -> [a] here to filter the list and only retain the elements less than 0 and then calculate the length :: Foldable f => f a -> Int:
negative :: [Int] -> Int
negative list = length (filter (< 0) list)
we can make these point-free, and let this work with any Num type:
negative :: (Num a, Ord a) => [a] -> Int
negative = length . filter (< 0)
I'm interested in writing an efficient Haskell function triangularize :: [a] -> [[a]] that takes a (perhaps infinite) list and "triangularizes" it into a list of lists. For example, triangularize [1..19] should return
[[1, 3, 6, 10, 15]
,[2, 5, 9, 14]
,[4, 8, 13, 19]
,[7, 12, 18]
,[11, 17]
,[16]]
By efficient, I mean that I want it to run in O(n) time where n is the length of the list.
Note that this is quite easy to do in a language like Python, because appending to the end of a list (array) is a constant time operation. A very imperative Python function which accomplishes this is:
def triangularize(elements):
row_index = 0
column_index = 0
diagonal_array = []
for a in elements:
if row_index == len(diagonal_array):
diagonal_array.append([a])
else:
diagonal_array[row_index].append(a)
if row_index == 0:
(row_index, column_index) = (column_index + 1, 0)
else:
row_index -= 1
column_index += 1
return diagonal_array
This came up because I have been using Haskell to write some "tabl" sequences in the On-Line Encyclopedia of Integer Sequences (OEIS), and I want to be able to transform an ordinary (1-dimensional) sequence into a (2-dimensional) sequence of sequences in exactly this way.
Perhaps there's some clever (or not-so-clever) way to foldr over the input list, but I haven't been able to sort it out.
Make increasing size chunks:
chunks :: [a] -> [[a]]
chunks = go 0 where
go n [] = []
go n as = b : go (n+1) e where (b,e) = splitAt n as
Then just transpose twice:
diagonalize :: [a] -> [[a]]
diagonalize = transpose . transpose . chunks
Try it in ghci:
> diagonalize [1..19]
[[1,3,6,10,15],[2,5,9,14],[4,8,13,19],[7,12,18],[11,17],[16]]
This appears to be directly related to the set theory argument proving that the set of integer pairs are in one-to-one correspondence with the set of integers (denumerable). The argument involves a so-called Cantor pairing function.
So, out of curiosity, let's see if we can get a diagonalize function that way.
Define the infinite list of Cantor pairs recursively in Haskell:
auxCantorPairList :: (Integer, Integer) -> [(Integer, Integer)]
auxCantorPairList (x,y) =
let nextPair = if (x > 0) then (x-1,y+1) else (x+y+1, 0)
in (x,y) : auxCantorPairList nextPair
cantorPairList :: [(Integer, Integer)]
cantorPairList = auxCantorPairList (0,0)
And try that inside ghci:
λ> take 15 cantorPairList
[(0,0),(1,0),(0,1),(2,0),(1,1),(0,2),(3,0),(2,1),(1,2),(0,3),(4,0),(3,1),(2,2),(1,3),(0,4)]
λ>
We can number the pairs, and for example extract the numbers for those pairs which have a zero x coordinate:
λ>
λ> xs = [1..]
λ> take 5 $ map fst $ filter (\(n,(x,y)) -> (x==0)) $ zip xs cantorPairList
[1,3,6,10,15]
λ>
We recognize this is the top row from the OP's result in the text of the question.
Similarly for the next two rows:
λ>
λ> makeRow xs row = map fst $ filter (\(n,(x,y)) -> (x==row)) $ zip xs cantorPairList
λ> take 5 $ makeRow xs 1
[2,5,9,14,20]
λ>
λ> take 5 $ makeRow xs 2
[4,8,13,19,26]
λ>
From there, we can write our first draft of a diagonalize function:
λ>
λ> printAsLines xs = mapM_ (putStrLn . show) xs
λ> diagonalize xs = takeWhile (not . null) $ map (makeRow xs) [0..]
λ>
λ> printAsLines $ diagonalize [1..19]
[1,3,6,10,15]
[2,5,9,14]
[4,8,13,19]
[7,12,18]
[11,17]
[16]
λ>
EDIT: performance update
For a list of 1 million items, the runtime is 18 sec, and 145 seconds for 4 millions items. As mentioned by Redu, this seems like O(n√n) complexity.
Distributing the pairs among the various target sublists is inefficient, as most filter operations fail.
To improve performance, we can use a Data.Map structure for the target sublists.
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE ScopedTypeVariables #-}
import qualified Data.List as L
import qualified Data.Map as M
type MIL a = M.Map Integer [a]
buildCantorMap :: forall a. [a] -> MIL a
buildCantorMap xs =
let ts = zip xs cantorPairList -- triplets (a,(x,y))
m0 = (M.fromList [])::MIL a
redOp m (n,(x,y)) = let afn as = case as of
Nothing -> Just [n]
Just jas -> Just (n:jas)
in M.alter afn x m
m1r = L.foldl' redOp m0 ts
in
fmap reverse m1r
diagonalize :: [a] -> [[a]]
diagonalize xs = let cm = buildCantorMap xs
in map snd $ M.toAscList cm
With that second version, performance appears to be much better: 568 msec for the 1 million items list, 2669 msec for the 4 millions item list. So it is close to the O(n*Log(n)) complexity we could have hoped for.
It might be a good idea to craete a comb filter.
So what does comb filter do..? It's like splitAt but instead of splitting at a single index it sort of zips the given infinite list with the given comb to separate the items coressponding to True and False in the comb. Such that;
comb :: [Bool] -- yields [True,False,True,False,False,True,False,False,False,True...]
comb = iterate (False:) [True] >>= id
combWith :: [Bool] -> [a] -> ([a],[a])
combWith _ [] = ([],[])
combWith (c:cs) (x:xs) = let (f,s) = combWith cs xs
in if c then (x:f,s) else (f,x:s)
λ> combWith comb [1..19]
([1,3,6,10,15],[2,4,5,7,8,9,11,12,13,14,16,17,18,19])
Now all we need to do is to comb our infinite list and take the fst as the first row and carry on combing the snd with the same comb.
Lets do it;
diags :: [a] -> [[a]]
diags [] = []
diags xs = let (h,t) = combWith comb xs
in h : diags t
λ> diags [1..19]
[ [1,3,6,10,15]
, [2,5,9,14]
, [4,8,13,19]
, [7,12,18]
, [11,17]
, [16]
]
also seems to be lazy too :)
λ> take 5 . map (take 5) $ diags [1..]
[ [1,3,6,10,15]
, [2,5,9,14,20]
, [4,8,13,19,26]
, [7,12,18,25,33]
, [11,17,24,32,41]
]
I think the complexity could be like O(n√n) but i can not make sure. Any ideas..?
In Haskell I'm trying to create a function with the typing Int -> [a] -> [[a]], that generates a list such as: [[0, 0], [0, 1], [1, 0], [1, 1]] where each element in the smaller lists can take the value of either 1 or 0. Each of the smaller lists has the same size, which in this case is 2. If the size of the smaller lists was 3, I would expect to get the output [[0,0,0], [0,0,1], [0,1,0], [1,0,0], [1,1,0], [0,1,1], [1,0,1], [1,1,1]]
I've looked in to the permutations function, but this does not achieve exactly what I want. I believe there is also a variate function, but I cannot access this library.
Rather than the exact function (which would also be useful), what would be the process to generate such a list?
As oisdk mentions in a comment, a more general version of this exact function is already defined, with the name Control.Monad.replicateM:
Prelude> import Control.Monad (replicateM)
Prelude Control.Monad> replicateM 3 [0,1]
[[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
We can use the list monad for this:
example :: [[Int]]
example = do
x <- [0,1]
y <- [0,1]
pure [x,y]
ghci> example
[[0,0],[0,1],[1,0],[1,1]]
Play with this. Then you should be able to combine it with recursion on n to create the function you need.
I'm not sure I understood the specification, but from the examples, one possible definition is
lists :: Int -> [[Int]]
lists 0 = [[]]
lists n = map (0:) xss ++ map (1:) xss
where xss = lists (n-1)
-- λ> lists 2
-- [[0,0],[0,1],[1,0],[1,1]]
-- λ> lists 3
-- [[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
Another definition, using comprehension instead of map, is
lists :: Int -> [[Int]]
lists 0 = [[]]
lists n = [x:xs | x <- [0,1], xs <- lists (n-1)]
-- λ> lists 2
-- [[0,0],[0,1],[1,0],[1,1]]
-- λ> lists 3
-- [[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
You can use the sequence function.
Like this:
λ>
λ> :t sequence
sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
λ>
λ> let { allLists :: Int -> [a] -> [[a]] ; allLists n xs = sequence $ replicate n xs ; }
λ>
λ> allLists 3 [0,1]
[[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]
λ>
I have a list of 9 integers with values 1, -1, 0 such as:
[-1, 0, 0, 1, -1, -1, 1, 1, 0]
What I am trying to do is that from this one list create list of lists where each one of them contain only one change and all the time different. For each -1 I want to change it into 0.
Example:
From the list:
[-1,0,0,1,-1,-1,1,1,0],
I want to get the result:
[ [ 0, 0, 0, 1, -1, -1, 1, 1, 0]
, [-1, 0, 0, 1, 0, -1, 1, 1, 0]
, [-1, 0, 0, 1, -1, 0, 1, 1, 0]
]
So each list has only one value changed and each has a different one. I have no idea how to even start.
First thing you always need is to figure out the type signature of your function. In your case you want
lister :: [Int] -> [[Int]]
Then, as you want to loop through the list but keeping track of the indexes you have changed, an easy way would be to list a list of your list (hard to follow, just look at the code) and then zip it with its index. Then for each list you switch the element in that position. This is you code
lister :: [Int] -> [[Int]]
lister ls = [switch i l | (i,l) <- zip [0..9] (repeat ls)]
You then need a switch function, to switch the element in the ith position accordingly to your rule:
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
Note that this returns 9 lists, one for each element in your original list. Therefore it contains some duplicates. You can eliminate them using nub from Data.List, watch out because it is O(n^2)
This is your complete code:
import Data.List
lister :: [Int] -> [[Int]]
lister ls = nub [switch i l | (i,l) <- zip [0..9] (repeat ls)]
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
Clearly this is a very specific problem. It is often useful to look at the bigger picture: what more general problem is this a special case of? Clearly, here, we are looking through a list, and may see an element that we wish to replace, in zero or more ways. Further, we wish to see how many ways it is possible to make a limited number of such replacements. So, let us implement the general case before thinking about how to specialize to our original problem:
import Control.Applicative (Alternative, empty, (<|>))
replaceNTimes :: Alternative f => (a -> f a) -> Int -> [a] -> f [a]
replaceNTimes _ 0 xs = pure xs
replaceNTimes _ _ [] = empty
replaceNTimes f n (x:xs) = replaceHere <|> keepLooking
where replaceHere = (:) <$> f x <*> replaceNTimes f (n - 1) xs
keepLooking = (x:) <$> replaceNTimes f n xs
If we have a "budget" of zero replacements remaining, we simply return the remainder of the list. If we have budget remaining but the list is empty, we abort, because we failed to make the expected number of replacements. Otherwise, we consult our replacement-suggester function to see which replacements are legal at the current position, and choose to either make one of them and recurse with a smaller N, or to make none and recurse with the same N.
With this tool at our disposal, the original problem is easy: we just specialize N to 1 (make exactly one replacement), and supply a replacing function that only suggests replacing -1 with 0:
replaceSingleNegativeOneWithZero :: [Int] -> [[Int]]
replaceSingleNegativeOneWithZero = replaceNTimes go 1
where go (-1) = [0]
go _ = []
And test to ensure that we get the expected output:
*Main> replaceSingleNegativeOneWithZero [-1,0,0,1,-1,-1,1,1,0]
[ [0,0,0,1,-1,-1,1,1,0]
, [-1,0,0,1,0,-1,1,1,0]
, [-1,0,0,1,-1,0,1,1,0]]
Another try:
zeros :: [Int] -> [Int] -> [[Int]]
zeros _ [] = []
zeros h (x:xs) = [h ++ newX:xs] ++ zeros nextH xs
where newX = if x == (-1) then 0 else x
nextH = h ++ [x]
switch xs = ((filter (/= xs)) . (zeros [])) xs
Usage:
main = print $ switch [-1, 0, 0, 1, -1, -1, 1, 1, 0]
I have a list, lets say [1, 2, 3, 4, 5] and I have to rotate the list at an index.
For example:
rotate 2 [1, 2, 3, 4, 5] gives [3, 4, 5, 1, 2]
Through researching online, I came across the cycle function which gets around the problem of losing the list when you drop it, but I feel as if I would benefit far more from producing my own working solution in terms of understanding, even if it is less efficient than a library function. The working solution I have is below:
rotate :: Int -> [a] -> [a]
rotate _ [] = []
rotate n l = take (length l) $ drop n (cycle l)
Could you suggest, without code, alternative ways of achieving this solution so I can have a crack at those? As I'm stuck without ideas now I have seen this way of doing it!
Cheers
You can simply do:
rotate n l = drop n l ++ take n l
to achieve the same without cycle.
Since here already exists a solution with code, I'll post another version:
rotate :: Int -> [a] -> [a]
rotate n [] = []
rotate n xs = xs2 ++ xs1
where (xs1, xs2) = splitAt (n `rem` length xs) xs
Some tests:
main = do
print $ rotate 0 [1..5] -- [1,2,3,4,5]
print $ rotate 2 [1..5] -- [3,4,5,1,2]
print $ rotate 5 [1..5] -- [1,2,3,4,5]
print $ rotate 7 [1..5] -- [3,4,5,1,2]
...what about straightforward solution?
rotate :: Int -> [a] -> [a]
rotate 0 xs = xs
rotate _ [] = []
rotate n (x:xs) = rotate (pred n) (xs ++ [x])