Related
I'm implementing a function that takes a [[Int]], and return a [String], it needs to fill the empty place in each sublist with _s, which index is the complement of the input list, and generate a string from the list, the length of each string is the same and is the (maximum of the input number + 1).
For example, if the input is [[1, 2] [0, 1, 2, 3] [1, 3] [0, 2, 3]], the output would be ["_12_", "0123", "_1_3", "0_23"]
I tried my best to do this, and don't know how to insert empty space into the missing part.
getString :: [[Int]] -> [String]
getString x = concat. show. x insert _
where insert _ [] ys = ys
Breaking this down, it seems you need to find the minimum and maximum numbers present.
inputs = [[1, 2], [0, 1, 2, 3], [1, 3], [0, 2, 3]]
listMin = foldl1 min
listMax = foldl1 max
minInput = listMin $ map listMin inputs
maxInput = listMax $ map listMax inputs
We can now readily generate a list from the minimum to the maximum.
ghci> [minInput .. maxInput]
[0,1,2,3]
So now we can map over our inputs with a list comprehension:
[... | x <- inputs]
And let's return a list of all of the digits each time, and use Data.Char.intToDigit to make them characters.
ghci> [[intToDigit y | y <- [minInput..maxInput]] | x <- inputs]
["0123","0123","0123","0123"]
This looks closer, but we actually want '_' if y is not in x. Easy enough with elem.
ghci> :{
ghci| [[if y `elem` x then intToDigit y else '_'
ghci| | y <- [minInput..maxInput]]
ghci| | x <- inputs]
ghci| :}
["_12_","0123","_1_3","0_23"]
I would advise to start with a simpler problem: doing this for a sublist, so map [1,2] to "_12" and [1,3] to "_1_3". Later you can then do padding at the right of underscores to draw a rectangular matrix. You can do this with recursion where you use an accumulator that will each time check if the head of the list is less than, greater than or equal to the accumulator, so:
getRow :: [Int] -> String
getRow = go 0
where go _ [] = …
go i (x:xs)
| … = …
| otherwise = …
Here go is thus a helper function. It starts with go 0 [1,2]. We see that 0 is less than 1, so we yield an underscore and advance to go 1 [1,2], since now i is the same as the head of the list, we emit the number as character, etc. I leave implementing the … parts as an exercise.
I have just started learning Haskell and I am trying to write some basic functions in order to get a better understanding of this language.
I want to write a function which takes a list and an Int (N) as argument and returns the element at index N in the list, without using the !! operator or any built-in function.
Here is what I tried :
myHead :: [a] -> a
myHead (x:_) = x
myHead [] = error "head: empty list"
myNth :: [a] -> Int -> a
myNth x i = if i < 0
then error "nth: index can't be negative"
else myNthIterator x i 0
myNthIterator :: [a] -> Int -> Int -> a
myNthIterator [] i n = error "nth: bad index"
myNthIterator (_:x) i n = if i == n
then myHead x
else myNthIterator x i ( n + 1 )
It works but it's shifted to the right. For example myNth [1, 2, 3, 4] 2 would give 4 and not 3.
From what I understand, (_:x) removes the first element of the list and I don't see how to iterate through the list element by element.
Could someone put me on the trail? I find it difficult to find resources for beginners in this language.
We can use Maybe to model whether the index was valid.
nth :: Int -> [a] -> Maybe a
nth 0 (x : _) = Just x
nth n (x : xs) = nth (n - 1) xs
nth _ [] = Nothing
We can pattern match on the index to get our base case, and the list to get the first element and tail.
What you're doing there with (_:x) is called "pattern matching" in case you didn't know. The general pattern for iterating through a list would be (x : xs) where x is head element of the list being matched and xs is the rest of the list. If you use _ you don't remove anything it is still matched to _ which is the convention for saying "I won't use this".
With that you can make a function like this:
myNth :: [a] -> Int -> a
myNth [] _ = error "out of range"
myNth (x : xs) 0 = x
myNth (_ : xs) n = myNth xs (n - 1)
Whenever myNth is called it will go top to bottom over those definitions trying to match the patterns to the input. So when you call myNth [10,11] 1 it won't match the first clause because [10,11] doesn't match an empty list, it won't match the second either because 1 is not 0 and so it will match the third case where it will match the [10,11] on (10 : [11]), therefore _ is 10 and xs is [11] and 1 will be matched as n. Then it calls itself recursively, as myNth [11] 0. Now that will match the second case and it will return x from the match of [11] on (11 : [])
Like 414owen said you can use the Maybe a type to avoid using error.
P.S.: I don't know how beginner you are but I assume you know of the : operator, it prepends an element to a list... If you go more in depth (afaik) every list is actually stored as a sequence of a:(b:(c:(d:(e:[])))) which is equivalent to [a,b,c,d,e] which is equivalent to a:[b,c,d,e] etc.
It works but it's shifted to the right. For example myNth [1, 2, 3, 4] 2 would give 4 and not 3.
myNthIterator (_:x) i n = if i == n
then myHead x
else myNthIterator x i ( n + 1 )
Let us look at myNthIterator [1..4] 1 1
myNthIterator [1..4] 1 1 -- replace [a, b] with (a: (b : []))
== myNthIterator (1 : [2, 3, 4]) 1 1
-- matching with `myNthIterator (_:x) i n` will result in
-- 1 ~ _
-- x ~ [2, 3, 4]
-- i ~ 1
-- n ~ 1
== if 1 == 1 then myHead [2, 3, 4] else myNthIterator [2, 3, 4] 1 (1 + 1)
== myHead [2, 3, 4]
== 2
So (_:x) matching against (1 : [2, 3, 4]) is suspicious. A first step in fixing it is to replace (_:x) by (x:xs).
myNthIterator (x:xs) i n = ...
In our example this would mean x == 1 and xs == [2, 3, 4].
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 the following problem: given a max(max) apacity, and given a list of values(listOfValues) i need to return a list with values from the listOfValues. The sum of the elements must be <= max and i need to prioritize the higher values.
Example: typing solvingProblem 103 [15, 20, 5, 45, 34] i must get: [45, 45, 5, 5]
To solve the problem i create the following code:
solvingProblem max [] = 0
solvingProblem max listOfValues | max == 0 = 0
| otherwise = createList max listOfValues []
createList max [] result = -1
createList max listOfValues result | smaller listOfValues > max = -1
| higher listOfValues > max = createList max (remove (higher listOfValues) listOfValues) result
| otherwise = createList (max - higher listOfValues) listOfValues (insert (higher listOfValues) result)
higher [a] = a
higher (a:b:x) | a > b = higher (a:x)
| otherwise = higher (b:x)
smaller [a] = a
smaller (a:b:x) | a < b = smaller (a:x)
| otherwise = smaller (b:x)
remove x [] = []
remove x (h:t) | x == h = remove x t
| otherwise = h : remove x t
insert x (h:t) = x : h : t
In the two lines where i'll returning "-1" should be the parameter "result", but if i change "-1" to "result" the code don't load on ghci.
Can someone help me?
Thank you and sorry for my bad english.
If I may begin with a bit of a side note, some of your functions already exist in Haskell (now that I come to think of it you might have written them for an exercise, but just in case it wouldn't be the case, let's discuss that): your higher is maximum, your smaller is minimum and your insert is just (:), beacause like you write it yourself insert x list = x:list. Note that your version will fail if you give it the empty list because the pattern matching is non-exhaustive. Also you could write remove in terms of filter: remove x list = filter (== x) list.
Now why doesn't your code load properly? ghci tells you:
• Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
• When checking the inferred type
solvingProblem :: forall a.
(Ord a, Num [a], Num a) =>
a -> [a] -> [a]
Which I agree is pretty cryptic, but what it's saying is that the return type of solvingProblem is a list of a and for some reason it is also an instance of the Num type class. The reason why it says it's an instance of Num is because one of the return value of solvingProblem is 0 which is a number, which is a bit odd because it is also a list. Changing the 0 with [] makes the code compile and work (if you change insert with (:) otherwise you get the non-exhaustive pattern matching I was talking about earlier).
λ> solvingProblem 103 [15,20, 5, 45, 34]
[5,5,45,45]
it :: (Ord t, Num t) => [t]
The problem is with the last guard clause in createList.
The type you intended for createList seems to be:
createList :: Int -> [Int] -> Int -> Int
but if you look at the last guard clause you have:
| otherwise = createList (max - ...) listOfValues (insert ...)
^^^^^^^^^^^ ^^^^^^^^^^^^ ^^^^^^^^^^^^
Int [Int] [Int]
Even though GHC is very good at inferring types, always adding
type signatures to your code is a good way of catching these kinds
of errors early.
I just started learning Haskell about filtering lists.
Suppose I have the following list : [2, 3, 4, 5, 8, 10, 11]
I would like to keep only those numbers in the list, which are not divisible by the other members.
The result of our example would be : [2, 3, 5, 11]
[x | x <- src, all (\y -> x `rem` y /= 0) (filter (<x) src)]
where src = [2,3,4,5,8,10,11]
It should be noted that you actually also mean dividable by other numbers that are below it, and not just any number in that list, which is why there's a filter in the 2nd argument for all.
The result, of course, is the one you expect in your question: [2,3,5,11].
Here's how it works (and if I'm missing anything, let me know and I'll update).
I'll explain the code side-by-side with normal English. I suggest you just read just the English first, and afterwards see how each statement is expressed in code - I think it should be the most friendly for a newcomer.
Also note that I flipped the arguments for filter and all below (it is invalid!) to make the explanation fluid.
[x|: Construct a list made out of x
x <- src: Where x is an element from src
,: But only the elements that satisfy the following predicate/rule:
all of the numbers from
(filter src (<x)): src that are lesser-than the current x
(\y -> x 'rem' y /= 0): must not yield a remainder equal to 0.
]
For the code part to make sense, make sure you've familiarized yourself with all, filter, rem, and the syntax for: list comprehensions, lambda expressions, sections, and backticks.
On GHC,
Prelude> :m + Data.List
Prelude Data.List> nubBy (\a b -> rem a b == 0) [2,3,4,5,8,10,11]
[2,3,5,11]
does the trick. On Haskell98-compatible systems (e.g. Hugs), use nubBy (\b a -> rem a b == 0).
This answer was posted as a comment by Will Ness.
Using filter
filter :: (a -> Bool) -> [a] -> [a]
and from Data.Numbers.Primes the function
isPrime :: Integral int => int -> Bool
may be
filter isPrime [2, 3, 4, 5, 8, 10, 11]
or using list comprehension
[ x | x <- [2, 3, 4, 5, 8, 10, 11], isPrime x]
change filter predicate as you wish, e.g.
-- None `xs` element (different than `x`) divide `x`
noneDiv xs x = and [x `mod` y /= 0 | y <- xs, x /= y]
now
myFilter xs = filter (noneDiv xs) xs
or
myFilter xs = [x | x <- xs, noneDiv xs x]