I want to take five consecutive primes generated as an infinite list by primes and check them if they summed make another prime. I want to have something like this:
consecutivePrimes = [ a+b+c+d+e | a:b:c:d:e <- primes, prime a+b+c+d+e]
This a:b:c:d:e <- primes however doesn't work and I can't find any way as to get multiple elements at once in a list comprehension.
Since a list comprehension can be thought of as a map combined with a filter (at least for lists), you can only get one element at a time inside of it.
But you can still do this by making primes into a list of lists using tails, then taking 5 elements from each of the lists. The single element you map over (ps) in this case is a list.
import Data.List (tails)
consecutivePrimes = [ a+b+c+d+e | ps <- tails primes, let [a,b,c,d,e] = take 5 ps, prime a+b+c+d+e]
Pattern matching on the list of 5 elements will always succeed if your input list is infinite.
This is my solution which works but I find it quite ugly:
consecutivePrimes = [x | x <- consecutivePrimes' primes, prime x]
consecutivePrimes' (a:b:c:d:e:xs) | prime (a+b+c+d+e) = (a+b+c+d+e) : consecutivePrimes' (b:c:d:e:xs)
| otherwise = consecutivePrimes' (b:c:d:e:xs))
Related
Entering a list comprehension into GHCi does not generate a list, the final square brackets are missing, and the console freezes. This is what I have come up with:
[13*x + 3 | x <- [1..], rem (13*x + 3) 12 == 5, mod (13*x + 3) 11 == 0, 13*x + 3 <= 1000]
I believe the problem lies either with x <- [1..], or 13*x + 3 <= 1000. By 13*x + 3 <= 1000 I meant to determine the upper limit of the values x in x <- [1..] can take.
I'm given back a result [341, but it does the second square bracket is missing, and the console freezes.
Your program enters an infinite loop.
The first number is 341, but in order to produce the next number, your program keeps looking through all the subsequent values of x, evaluates all the guards for those values, and checks if all the guards are true. The very last guard, 13*x + 3 <= 1000 never becomes true again, so the program just keeps enumerating values of x forever. It's looking for the next such x for which all guards are true, and as soon as it finds one, it's going to print it. But such x never comes.
If you want the list to end once x*13 + 3 > 1000, you have to use takeWhile:
... | x <- takeWhile (\y -> y*13 + 3 <= 1000) [1..], ...
That way the list will actually stop when it reaches 1000. No more values of x would be produced.
You're giving the compiler way too much credit. It isn't going to carefully analyse your list comprehension in order to deduce that past a certain point there will be no more results, and it should call the list complete. It only does what you tell it to do.
In this case what you told it to do is:
[ 13*x + 3 -- produce numbers of the form 13*x + 3
| x <- [1..] -- by searching all x from [1..]
, rem (13*x + 3) 12 == 5 -- allowing only x that meet this condition
, mod (13*x + 3) 11 == 0 -- and this condition
, 13*x + 3 <= 1000 -- and this condition
]
So it prints [341 and "freezes" because it's still trying to compute the rest of that list. You don't see anything happening, but internally it's drawing ever bigger x from [1..] and diligently checking those conditions to realise that the number shouldn't be included. But it never hits the end of [1..] in order to stop, so it never gets up to printing the ] and waiting for more input.
With your code you are explicitly telling the compiler that you want to search every number in the infinite1 list [1..]. You are then expecting it to notice that 13*x + 3 <= 1000 can only be true for x drawn from a finite prefix of [1..] and thus actually not search the entire list [1..] as you instructed2.
That is a perfectly reasonable thing to want, and I can imagine a system capable of pulling that off (at least with simple conditions like this). So testing it out like this to see if it works is a good idea! However unless someone actually told you that figuring out enumeration upper bounds from conditions in list comprehensions is a feature that GHC can provide, it shouldn't be surprising that it never completes when you tell it to search an infinite list.
For this style of list comprehension (getting all numbers in a range meeting certain conditions) you normally shouldn't use [1..] and then try to impose a stopping condition. Just figure out that the last number that will pass 13*x + 3 <= 1000 and use [1..76] as your generator instead. You can even have Haskell figure it out for you with [1 .. (1000 - 3) div 13].
You use a generator like [1..] when you want to get all numbers of the right form. Then you can use functions like take or takeWhile to get a finite section at the point where you want to use it for something. e.g.
Prelude> let xs = [13*x + 3 | x <- [1..], rem (13*x + 3) 12 == 5, mod (13*x + 3) 11 == 0]
Prelude> takeWhile (<= 1000) xs
[341]
Prelude> take 5 xs
[341,2057,3773,5489,7205]
In fact the simplest and most direct way to express what you want in a single expression is this:
takeWhile (<= 1000) [13*x + 3 | x <- [1..], rem (13*x + 3) 12 == 5, mod (13*x + 3) 11 == 0]
Everything in a list comprehension (except the generator expression) is only talking about a single element at a time. There's just no way to express concepts that are talking about the returned list as a whole, like "stop searching once the returned numbers go out of this range". But that concept is trivial to express outside of list comprehension as a normal function (takeWhile (<= 1000)). Don't feel like you have to shoehorn your entire computation into a single list comprehension.
1 Strictly speaking it's infinite if you're using a type like Integer (which is the type Haskell will pick without any other code using the result to impose other constraints on the type). If you're using Int then it's technically finite, and your list comprehension will eventually end when it "runs out of numbers". [1..] as a list of Int is still impractically vast for an exhaustive search, however.
But if you use a smaller type, like Word16 (needs to be imported from Data.Word) then you can in fact finish your original list comprehension in a practical amount of time. (Though I had to tweak it a little to make sure the 13*x stuff was computed in a larger type so it doesn't overflow)
Prelude> import Data.Word
Prelude Data.Word> [13*x + 3 | x <- [1 :: Word16 ..], let x' = fromIntegral x, rem (13*x' + 3) 12 == 5, mod (13*x' + 3) 11 == 0, 13*x' + 3 <= 1000]
[341]
2 While I'm being pedantic in the footnotes, if your original list comprehension is being evaluated as a list of Int it wouldn't even be valid to just stop after x grows high enough that 13*x + 3 <= 1000 fails for the first time. Try this:
Prelude Data.Word> let x = 768614336404564650 :: Int
Prelude Data.Word> 13*x + 3 <= 1000
True
This happens because Int does in fact have an upper bound, so a large enough Int will overflow back to negative when you multiply it by 13. So when searching [1..] as [Int] the compiler is in fact right to keep looking past x = 77; there are almost certainly more numbers in your original list comprehension if it's [Int], they just take a long time to reach.
Again a good way to demonstrate is to use a smaller finite type, like Word16. If I use your original list comprehension as [Word16] without modifying it to avoid overflow in the conditions, you get this:
Prelude Data.Word> [13*x + 3 | x <- [1..], rem (13*x + 3) 12 == 5, mod (13*x + 3) 11 == 0, 13*x + 3 <= 1000] :: [Word16]
[341,605,209,869,473,77,737]
Even if the compiler was smart enough to know the regions of [1..] that could possibly pass 13*x + 3 <= 1000 condition, it's never going to be able to read your mind and know whether the overflow-produced numbers are solutions you intended or are the result of a bug in your code. It just does what you tell it to do.
I would like to create a function that swaps the first two elements of every list in a lists of lists
So for example:
swapElems [[1], [1,3]] == [[1],[3,1]]
or
swapElems ["apple", "pear", "banana"] == ["paple","epar","abnana"]
So far I have tried:
swapElems [(x:y:xs),(z:u:zs),(t:i:ts)] = [(y:x:xs),(u:z:zs),(i:t:ts)]
swapElems [(x:y:xs),(z:u:zs)] = [(y:x:xs),(u:z:zs)]
swapElems [(x:y:xs)] =[(y:x:xs)]
swapElems [] = []
But this only works when I input a list of lists that contains exactly 1 or 2 or 3 lists.
I would need a solution that works for any number of lists.
How could I rewrite it in a way so it works regardless of how many lists I include.
I'd start with writing a function that swaps two first elements of a single list, e.g:
swapTwoFirst (x:y:xs) = (y:x:xs)
swapTwoFirst xs = xs
and then:
swapElems = map swapTwoFirst
I just started to learn Haskell today and is completely overwhelmed by its syntax.
I am trying to apply math calculation to a list of items.
For example, lets say I want to square every item in the list using list comprehension.
My attempt
myfunc (n:lis) = [ k | k <-lis, k == k^k]
result_list = myfunc[1..]
take 10 result_list
My understand of my myfunc code: take a list and loop through elements that is stored in variable k and set k equals to its square.
after i execute the take command, and hit enter, apparently the process is running but does not do anything.
Note that i want to use list comprehension as a way to do it. I can use map do achieve my goal already.
You misunderstand the list comprehension.
[ k | k <- lis, k == k^k ]
The k == k^k clause is a filter –– it only keeps elements of the list that satisfy this equation. (== is a comparison operator that returns a bool, which is one hint). The reason you see no output is that there are no numbers in [1..] that satisfy this equation. But we get an infinite loop because we keep checking ever higher numbers to see if they satisfy it.
Something to experiment with
[ k | k <- lis, k < 100 ]
As for how to get a list of squares, use a comprehension like this
[ k^2 | k <- lis ]
If you want something more like your original phrasing, you can make let bindings within a list comprehension:
[ r | k <- lis, let r = k^2 ]
There are other issues with your code, but one baby step at a time! Good luck!
I am trying to build a list of 0's using list comprehension. But i also want to make an index 1 where i choose in the list. For example myList 5 2 = [0,1,0,0,0] where 5 is the number of elements and 2 is the index.
myList el index = [0 | n <- [1..el], if n == index then 1 else 0]
but this results in an error.
The smallest change that fixes that is
myList el index = [if n == index then 1 else 0 | n <- [1..el]]
Note that what's at the left of | is what generates the list elements. A list comprehension of the form [ 0 | ...] will only generate zeros, and the ... part only decides how long is the resulting list.
Further, in your code the compiler complains because at the right of | we allow only generators (e.g. n <- someList), conditions (e.g. x > 23), or new definitions (let y = ...). In your code the if ... is interpreted to be a condition, and for that it should evaluate to a boolean, but then 1 makes the result a number, triggering a type error.
Another solution could be
myList el index = replicate (index-1) 0 ++ [1] ++ replicate (el-index) 0
where replicate m 0 generates a list with m zeros, and ++ concatenates.
Finally, note that your index is 1-based. In many programming languages, that's unconventional, since 0-based indexing is more frequently used.
all_nat x = [ls| sum ls == x]
I'd like to write a function that given an integer x it returns all the lists that the result of their elements when summed is the integer x but I always get the error "not in scope: 'ls' " for both times it apperas. I'm new to haskell. What's the syntax error here?
The problem is that you need to define all used variables somewhere, but ls is undefined. Moreover, it can't be defined automatically, because the compiler doesn't know about the task — how the list should be generated? Ho long can it be? Are terms positive or not, integral or not? Unfortunately your code definition of the problem is quite vague for modern non-AI languages.
Let's help the compiler. To solve such problems, it's often useful to involve some math and infer the algorithm inductively. For example, let's write an algorithm with ordered lists (where [2,1] and [1,2] are different solutions):
Start with a basis, where you know the output for some given input. For example, for 0 there is only an empty list of terms (if 0 could be a term, any number could be decomposed as a sum in infinitely many ways). So, let's define that:
allNats 0 = [[]] --One empty list
An inductive step. Assuming we can decompose a number n, we can decompose any number n+k for any positive k, by adding k as a term to all decompositions of n. In other words: for numbers greater than 0, we can take any number k from 1 to n, and make it the first term of all decompositions of (n-k):
allNats n = [ k:rest --Add k as a head to the rest, where
| k <- [1 .. n] --k is taken from 1 to n, and
, rest <- allNats (n - k)] --rest is taken from solutions for (n—k)
That's all! Let's test it:
ghci> allNat 4
[[1,1,1,1],[1,1,2],[1,2,1],[1,3],[2,1,1],[2,2],[3,1],[4]]
Let's break this up into two parts. If I've understood your question correctly, the first step is to generate all possible (sub)lists from a list. There's a function to do this, called subsequences.
The second step is to evaluate the sum of each subsequence, and keep the subsequences with the sum you want. So your list comprehension looks like this:
all_nat x = [ls| ls <- subsequences [1..x], sum ls == x]
What about
getAllSums x = [(l,r)| l <- partial_nat, r <- partial_nat, l + r == x ]
where partial_nat = [1..x]