estaLivre lg pls = head [s | (l,s) <- pls, l==lg] == 0
This function receives two lists as parameters. The first one is the coordinates of a chair in a theater. Like (1, 1) row 1, column 1. pls is the description of the chairs in the theater. pls consists of the coordinates of the chair and 1 or 0, wich tells if the chair is taken (1) or if its not (0). Something like this: pls = [((1, 1), 1), ((1, 2), 0)] the chair (1, 1) is taken. The chair (1, 2) is not.
I didn't understand how this woks. head takes the first element of the list and sees if it equals to 0 (is that right?) but s is not the first element. So how does this work?
I've done some tests to see how this works and apparently, head takes the element that's before the '|'. In this case, 's'. One of my tests was to take the head of [y | (x, y) <- xs, x == y^1/2]. It returned the value of y. I did the same thing with [x | (x, y) <- xs, y == x^2] and it returned x. But it's still confusing to me because I was taught that head takes the first element of a list. Can someone explain this to me?
Let's start with the parameters: lg is the position that you want to test to be free and pls is the list of positions, where each position is a tuple (coords,if coords are free then 0 else 1).
The list comprehension is used to pick from the list pls the positions that have the same coords given in input, i.e. lg, and then select only the second part of the tuple, that is if the position is free:
[s | (l,s) <- pls, l==lg]
Because pls is a list, it is possible that more than one element in it satisfies l==lg, for example when pls = [((1,1),0),((1,1),0)] the expression above will return [0,0], and thus you have to use head to extract the first occurrence that satisfies the predicate:
head [s | (l,s) <- pls, l==lg]
This will tell you if that position is free, by returning 0, or taken, by returning 1, and the final test == 0 will convert 0 or 1 into a boolean value.
As side note I would like to say that this function is terrible and unsafe, in particular because it uses head to extract one possible occurrence of the given coordinates. It should be rewritten to use maps and not lists and to use bool instead of int to say if the position is taken or not.
The head function is defined as
head :: [a] -> a
head (x:xs) = x
head [] = error "Prelude.head: empty list"
All it does is grab the first element from the list.
What you're confused about is the list comprehension syntax. This is a syntax that lets you write list operations very cleanly without having to resort to functions like map, filter, or list monadic syntax (that's a topic for another day). In short, if you see something like
[function x | x <- someList, condition x]
This is broadly equivalent to
map function (filter condition someList)
Think of <- as iterating over each element in someList and assigning that value to x, then it checks it against a condition function condition, the builds a list out of it, applying function to each element. This syntax is also useful if you want to iterate over multiple lists, but I'll let you play with it yourself (try out things like [(x, y) | x <- [1..5], y <- [6..10]] in GHCi to see what happens).
So in your case, you have
estaLivre lg pls = head [s | (l,s) <- pls, l==lg] == 0
If we use the rules from above, we can convert this into
estaLivre lg pls = head (map snd $ filter (\(l, s) -> l == lg) pls) == 0
This might be more obvious if the tuple wasn't pattern matched on, you could write your original function as
estaLivre lg pls = head [snd x | x <- pls, fst x == lg] == 0
So the list [s | (l,s) <- pls, l==lg] is going to return a list of all seat occupancies s for the given row/column coordinate lg, then head gets the first element out of that list, and then it's compared to 0.
Related
I need a little help understanding a comprehension method function.
compdivides :: Integer -> [Integer]
compdivides x
| x > 0 = [a | a <-[1..div x 2], mod x a == 0] ++ [x]
| otherwise = compdivides (abs x)
I understand that if x is positive we do the 3rd line otherwise the 4th line.
In the third line we check whether mod x a == 0 only then do we do everything else.
However, I cannot seem to understand this part a <-[1..div x 2] What exactly happens here?
Also, why do we do this at the end ++ [x] ? What exactly are we doing here anyways?
itemTotal :: [(String, Float)] -> [(String, Float)]
itemTotal [] = []
itemTotal [x] = [x]
I am having some trouble with this as well.
I understand that if the list is empty we simply return an empty list.
However, what are we saying here? itemTotal [x] = [x] That if the list only has one thing we simply return that one thing?
Thank you so much for the help!
However, I cannot seem to understand this part a <-[1..div x 2] What exactly happens here?
This is a generator of the list comprehension. The list comprehension:
[ a | a <- [1 .. div x 2 ], mod x a == 0 ]
will evaluate such that a takes each item in the list (so 1, 2, …, x/2), and in case mod x a == 0 (x is dividable by a), it will add a to the list.
Also, why do we do this at the end ++ [x] ? What exactly are we doing here anyways?
It appends x at the end of the list. This is done because a number x is always dividable by itself (x), since the a <- [1 .. div x 2] stops at div x 2, it will never check if x divides x.
The function will get stuck in an infinite loop for compdivides 0, so you might want to rewrite the function to cover this case as well.
However, what are we saying here? itemTotal [x] = [x] That if the list only has one thing we simply return that one thing?
Yes. Usually a pattern like itemTotal (x : xs) = x : itemTotal xs is used where we thus return a list where x is the first item, and we recurse on the tail of the list xs.
Your itemTotal function however only makes a copy of the list for the first two clauses. You thus can simply define itemTotal = id. Likely you will need to rewrite the function to determine the total of the items in the list.
Consider the following:
list = [1,3..]
generate n = [compute y | y <- list , (compute y) < n ]
compute a = ... whatever ...
Is it possible to exit the generator before getting to the last element of my list
(e.g. if (compute y > 20)?
I want to save computing power. I only need the elements smaller than n.
I'm new to Haskell. A simple answer might be the best answer.
The wonderful thing about Haskell is that it's lazy. If you said
> let x = generate 100000
then Haskell doesn't immediately calculate generate 100000, it just creates a promise to start calculating it (we normally call this a thunk).
If you want only elements only until compute y > 20, then you can do
> takeWhile (<= 20) (generate 100000)
This is the same semantics that let you do something like
> let nums = [1..] :: [Integer]
This makes a lazy reference to all Integer values from 1 to infinity. You can then do things like
> take 10 $ map (* 10) $ drop 12345 $ map (\x -> x ^ 2 + x ^ 3 + x ^ 4) $ filter even nums
[3717428823832552480,3718633373599415160,3719838216073150080,3721043351301172120,3722248779330900000,3723454500209756280,3724660513985167360,3725866820704563480,3727073420415378720,3728280313165051000]
And while tihs seems like a lot of work, it only calculates the bare minimum necessary to return the 10 elements you requested. The argument to take 10 in this example is still an infinite list, where we first grabbed all the evens, then mapped an algebraic expression to it, then dropped the first 12345 elements, then multiplied all remaining (infinite) elements by 10. Working with infinite structures in Haskell is very common and often advantageous.
As a side note, your current definition of generate will do extra work, you'd want something more like
generate n = [compute_y | y <- list, let compute_y = compute y, compute_y < n]
This way compute y is only calculated once and the value is shared between your filter compute_y < n and the left hand side of the | in the comprehension. Also be aware that when you have a condition in a comprehension, this gets translated to a filter, not a takeWhile:
> -- filter applies the predicate to all elements in the list
> filter (\x -> x `mod` 5 == 0) [5,10,15,21,25]
[5,10,15,20]
> -- takeWhile pulls values until the predicate returns False
> takeWhile (\x -> x `mod` 5 == 0) [5,10,15,21,25]
[5,10,15]
I am new to Haskell and am trying to learn the basics. I am having a hard time understanding how to manipulate the contents of a list.
Assume I have the following list and I would like to create a function to subtract 1 from every element in the list, where I can simply pass x to the function, how would this be done?
Prelude>let x = 1:2:3:4:5:[]
Something like:
Prelude>subtractOne(x)
(You can write 1:2:3:4:5:[] more simply as [1,2,3,4,5] or even [1..5].)
Comprehensions
You'd like to use list comprehensions, so here it is:
subtractOne xs = [ x-1 | x <- xs ]
Here I'm using xs to stand for the list I'm subtracting one from.
The first thing to notice is x <- xs which you can read as "x is taken from xs". This means we're going to take each of the numbers in xs in turn, and each time we'll call the number x.
x-1 is the value we're calculating and returning for each x.
For more examples, here's one that adds one to each element [x+1|x<-xs] or squares each element [x*x|x<-xs].
More than one list
Let's take list comprehension a little further, to write a function that finds the squares then the cubes of the numbers we give it, so
> squaresAndCubes [1..5]
[1,4,9,16,25,1,8,27,64,125]
We need
squaresAndCubes xs = [x^p | p <- [2,3], x <- xs]
This means we take the powers p to be 2 then 3, and for each power we take all the xs from xs, and calculate x to the power p (x^p).
What happens if we do that the other way around?
squaresAndCubesTogether xs = = [x^p | x <- xs, p <- [2,3]]
We get
> squaresAndCubesTogether [1..5]
[1,1,4,8,9,27,16,64,25,125]
Which takes each x and then gives you the two powers of it straight after each other.
Conclusion - the order of the <- bits tells you the order of the output.
Filtering
What if we wanted to only allow some answers?
Which numbers between 2 and 100 can be written as x^y?
> [x^y|x<-[2..100],y<-[2..100],x^y<100]
[4,8,16,32,64,9,27,81,16,64,25,36,49,64,81]
Here we allowed all x and all y as long as x^y<100.
Since we're doing exactly the same to each element, I'd write this in practice using map:
takeOne xs = map (subtract 1) xs
or shorter as
takeOne = map (subtract 1)
(I have to call it subtract 1 because - 1 would be parsed as negative 1.)
You can do this with the map function:
subtractOne = map (subtract 1)
The alternative solution with List Comprehensions is a little more verbose:
subtractOne xs = [ x - 1 | x <- xs ]
You may also want to add type annotations for clarity.
You can do this quite easily with the map function, but I suspect you want to roll something yourself as a learning exercise. One way to do this in Haskell is to use recursion. This means you need to break the function into two cases. The first case is usually the base case for the simplest kind of input. For a list, this is an empty list []. The result of subtracting one from all the elements of the empty list is clearly an empty list. In Haskell:
subtractOne [] = []
Now we need to consider the slightly more complex recursive case. For any list other than an empty list, we can look at the head and tail of the input list. We will subtract one from the head and then apply subtractOne to the rest of the list. Then we need to concatenate the results together to form a new list. In code, this looks like this:
subtractOne (x:xs) = (x - 1) : subtractOne xs
As I mentioned earlier, you can also do this with map. In fact, it is only one line and the preferred Haskellism. On the other hand, I think it is a very good idea to write your own functions which use explicit recursion in order to understand how it works. Eventually, you may even want to write your own map function for further practice.
map (subtract 1) x will work.
subtractOne = map (subtract 1)
The map function allows you to apply a function to each element of a list.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Split list and make sum from sublist?
Im trying to solve this problem.
I need to do a sum of elements from a list which are separated from each other only with "0".
So for example I can have something like this as input: [1,2,3,0,3,4,0,2,1]
and the output should be [6,7,3].
So far I managed to do something like this:
cut (x:xs) | x > 0 = x : (cut xs)
| otherwise = []
first (xs) = ( (foldl (+) 0 (cut (xs))) ) : []
second (xs) = ( (foldl (+) 0 (cut (reverse (xs)))) ) : []
test (xs) = first(xs) ++ second(xs)
Problem is that this only works with only 1 instance of "0" in my list.
I was trying to solve this by editing my cut function:
cut [] = []
cut (x:xs) | x > 0 = foldl (+) 0 ( x : cut xs) : []
| x == 0 = (cut xs)
But I cant figure out how to adjust it, so it will separate the sums. Right now it just throws the sum of all the elements as the output.
You can divide your problem into two tasks
Split a list into parts on zeros.
Sum parts.
For the first task we have Data.List.Split module which exports splitOn function.
It does precisely what we need:
> splitOn [1] [0,0,0,1,0,0,0,1,0]
[[0,0,0],[0,0,0],[0]]
For the second task there is well-known map-function which applies a function to the each element of the list.
In our case this function is sum:
> map sum [[1,2,3],[4,5,6],[7,8,9]]
[6,15,24]
So:
> :m +Data.List.Split
> map sum . splitOn [0] $ [1,2,3,0,3,4,0,2,1]
[6,7,3]
For homework you should definitely follow dave's answer. However, here is a more advanced solution, employing groupBy as poor man's split:
import Data.List (groupBy)
map sum $ groupBy (const (/=0)) list
This might look cute, but note that there are still the zeros at the beginning of the sub-lists present, so you can't use this solution without changes if that matters (e.g if you need products instead of sums)
[Explanation]
groupBy looks if the first element of the current group "fits together" with the current element of the list. In that case the current element will be added to the group, else a new group starts. E.g.
groupBy (\x y -> x `mod` y == 0) [81,3,9,25,5]
--[[81,3,9],[25,5]]
Here the test ist successful for 81 'mod' 3 and 81 'mod' 9, but not for 81 'mod' 25, which starts a new group. Again, 25 'mod' 5 is successful.
But in our case all elements "fit" in the current group as long as they are not 0, so we don't even have to look at the first element. And if a 0 is found, a new group is started.
const (/=0) means just \_ y -> y /= 0, so regardless what the first argument is, it just tests that the second element isn't 0. To see why, look at the definition:
const :: a -> b -> a
const a _ = a
Now our lambda can be written as
\x y -> const (/= 0) x y
As from the const call only the first of the two arguments "survives", we have
\x y -> (/= 0) y
... or...
\_ y -> y /= 0
Even if you're unable to install to install the split package and use Data.List.Split as Matvey suggests, you can still use the general approach:
Split the weird list with 0 separators into a more conventional list of lists.
Sum each list.
So
yourFunction = map sum . split
Now we have to write split.
split :: [Int] -> [[Int]]
In general, when we want to pull a list apart to synthesise something new, we need to use a fold.
split = foldr cons nil where
nil here should be whatever you want split [] to be.
nil = --TODO: exercise for you; clue: NOT []
cons meanwhile combines one of your numbers, with the answer from the previous step of the fold. Obviously, you'll need to do different things depending on whether or not the number is 0.
cons 0 xss = --TODO
cons x (xs : xss) = --TODO; why will this pattern match never fail?
I can remove all occurences of element in the list:
*Main> let d = [1, 2, 3, 4, 5, 6]
*Main> d
[1,2,3,4,5,6]
*Main> [x | x <- d, not(x == 2)]
[1,3,4,5,6]
I just wondering if there is any possibility to remove only FIRST occurence of element in the list, but using list comprehension?
No, there isn't. The list comprehension
[ x | x <- d, GUARD ]
is equivalent by definition to the following:
let ok x = if GUARD then [x] else []
ok _ = []
in concatMap ok d
By the definition of 'if', GUARD must be a pure boolean expression (i.e. evaluate to True of False alone), so it cannot keep track of state as you map over the list (assuming you're going to play by the rules).
Having said that, there is one way around this that uses comprehensions: zip state into your input list and run a list comprehension on that composite list. This composite list might have a type of something like [(Int, Bool)] where the Bool indicates whether this is the first item in the list. You then do something like:
[ x | (x, isFirst) <- zip d (findFirsts d), not (x == 2 && isFirst)]
where the implementation of findFirsts d is left as an exercise to the reader.
But you wouldn't want to do this in this particular case. It's a bad solution here because it basically means you're going to go through the list at least twice, once to figure out which items are the Firsts, and once to actually filter out the item(s) you don't want. If you implemented findFirsts naively, you might be looking at a bunch more work than even that. Not the right tool for the job!
For certain problems, though, like checking for the head or incorporating the specific position of an item into your results (as hvr has demonstrated), this can be a very effective technique.
Two other ways:
Use monadic computations to carry state as you sequentially iterate through the list. Might be OK for cases where you want to traverse arbitrary or complicated structures, or where your computation is going to be complicated, but in this case, you're better off if you:
Just use a simple recursive function solution, which is what Data.List.delete and deleteBy do.
For the record I wanted to point out that the delete function in the Data.List module provides exactly the behaviour you describe.
So you could cheat a bit and just use delete in your list comprehension:
> let l = [1,2,3,2,1]
> [x | x <- delete 2 l]
[1,3,2,1]
I guess this doesn't count.
...so, I was curious how to do this and here's a solution which doesn't use delete:
-- Removes the first occurrence of '2' in 'l', if any.
[x | (x,y) <- zip l [0..], let idx = elemIndex 2 l, idx == Nothing || y /= fromJust idx]
The idea is to first turn the list into a list of tuples where the second element of each tuple is the index of the element, e.g. "abcba" becomes [('a',0),('b',1),('c',2),('b',3),('a',4)]. Then we take each first element of all tuples for which the second tuple element does not equal the value returned by 'elemIndex' (which returns the position of the first occurance of the given element). For instance, elemIndex 'b' "abca" yields 2, so we take the first elements of all tuples where the second element is not 2. And that yields "acba".
The following removes the element only if occuring in head position:
[ x | (i, x) <- zip [0..] d, if i == 0 then x /= 2 else True ]
(which wasn't the question)
Not directly. List comprehensions are equivalent to using concat and map only. They map elements uniformly - if a is changed to b (or removed, or changed into several elements) then all occurences of a will do the same.
An ugly way would be to tag elements with numbers and search for the first one:
f r x = let x' = zip x [0..]
(_,n) = head [v | v <- x', fst v == r]
in [y | (y,m) <- x', y /= r || m /= n]
First zip can be expressed with LC if you use extension "parallel list comprehensions". This is extremely nonidiomatic, better use explicit recursion or Data.List.delete.