I've been looking into perfect numbers, and I found this interesting bit of code on rosettacode:
perfect n = n == sum [i | i <- [1..n-1], n `mod` i == 0]
Now, I understand what a perfect number is, and I know which numbers are considered perfect, however I'm struggling to work out which parts of this code do what.
I understand that it's working out the factors of the inputted number, and combining them together to see if it matches the input itself, but I'm not sure how it's doing this.
If anyone could possibly break down this bit of code in a beginner-friendly manner I'd be very appreciative.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^^^^^^
For i from 1 to n-1 (that is, [1, 2, 3, 4 ... n-1])
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^^^
And only for those values where i evenly divides n. Discarding values that do not match this requirement.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^
Include i in the result list.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^
Add the elements of this list together.
n == sum [i | i <- [1..n-1], n `mod` i == 0]
^^^^
And return True iff the total equals n.
[i | i <- [1..n-1], n `mod` i == 0]
Starting from the middle, you can read it like this: for each element i of the [1..n-1] list, check if n `mod` i equals 0. If it does, include i in the result list (that's the part to the left of the |. Without using the list comprehension syntax, that might be written using the filter function:
filter (\i -> n `mod` i == 0)
The elements of the resulting list are then added with sum, and, finally, the sum is tested for equality with n.
Related
Define the sequence (bn)n=1,2,… such that bn=3 when n is divisible by 3, and bn=4(n+1)^2 in other cases.
Define a function that for an argument n creates the list of n initial numbers of the sequence (bn)n=1,2,… .
so far I have two lists with condition 1 and condition 2:
divisible3 n = [x | x <- [1..n], x `mod` 3 == 0]
notdivisible3 n = [x*x*4+8*x+4 | x <- [1..n], x `mod` 3 /= 0]
I want it to be one list like:
list n = [x | x <- [1..n], condition1, condition 2]
You should write an if ... then ... else ... in the "yield" part of the list comprehension, not a filter. So something like:
list n = [ if n `mod` 3 == 0 then … else … | x <- [1..n]]
where I leave the … parts as an exercise.
I am trying to teach myself Haskell and I am doing random exercises.
I was supposed to write a code that will do this 6 = [1*1 + 3*3 + 5*5]= 35
So I had to filter out all odd numbers and then calculate the sum if I multiply every single one with itself.
sumquad n = (potenzsum(filter odd (ones n)))
where
potenzsum [x] = x*x
potenzsum [x,y] = x*x + y*y
potenzsum (x:xs) = x + potenzsum xs
ones 0 = []
ones x = [ 1 .. x]
This code works ;)
Now I am supposed to do the same thing but with list comprehension (I am allowed to use this list [1...n]
I could only think of this... Could someone help me?
power1 xs = [x*x | x <- xs]
Actually, you did half the job by [x * x | x <- xs], just replace xs by odd numbers from the previous example:
[x * x | x <- filter odd (ones 6))]
And you'll receive a list of squares: [1, 9, 25], which can be summed by function sum:
f n = sum [x * x | x <- filter odd (ones n))]
it evaluates to 35
One more note regarding list comprehension: the iterated elements can be filtered out by specifying conditions, which are called guards. Thus, the code above can be refactored into:
f n = sum [x * x | x <- [1..n], odd x]
isqrt :: Integer -> Integer
isqrt = floor . sqrt . fromIntegral
primes :: [Integer]
primes = sieve [2..] where
sieve (p:ps) = p : sieve [x | x <- ps, x `mod` p > 0]
primeFactors :: Integer -> [Integer]
primeFactors n = takeWhile (< n) [x | x <- primes, n `mod` x == 0]
Here is my code. I think you guessed what I am trying to do: A list of prime factors of a given number using infinite list of prime numbers. But this code does not evaluate lazily.
When I use ghci and :l mycode.hs and enter primeFactors 24, the result is [2, 3 ( and the cursor constantly flashing there) there isn't a further Prelude> prompt. I think there is a problem there. What am I doing wrong?
Thanks.
takeWhile never terminates for composite arguments. If n is composite, it has no prime factors >= n, so takeWhile will just sit there.
Apply takeWhile to the primes list and then filter the result with n mod x, like this:
primeFactors n = [x | x <- takeWhile (<= n) primes, n `mod` x == 0]
(<= is used instead of < for maximum correctness, so that prime factors of a prime number would consist of that number).
Have an illustration of what happens:
http://sketchtoy.com/67338195
Your problem isn't directly takeWhile, but rather the list comprehension.
[x | x <- primes, n `mod` x == 0]
For n = 24, we get 24 `mod` 2 == 0 and 24 `mod` 3 == 0, so the value of this list comprehension starts with 2 : 3 : .... But consider the ... part.
The list comprehension has to keep pulling values from primes and checking 24 `mod` x == 0. Since there are no more prime factors of 24 nothing will ever pass that test and get emitted as the third value of the list comprehension. But since there's always another prime to test, it will never stop and conclude that the remaining tail of the list is empty.
Because this is lazily evaluated, if you only ever ask for the first two elements of this list then you're fine. But if your program ever needs the third one (or even just to know whether or not there is a third element), then the list comprehension will just spin forever trying to come up with one.
takeWhile (< 24) keeps pulling elements from its argument until it finds one that is not < 24. 2 and 3 both pass that test, so takeWhile (< 24) does need to know what the third element of the list comprehension is.
But it's not really a problem with takeWhile; the problem is that you've written a list comprehension to find all of the prime factors (and nothing else), and then trying to use a filter on the results of that to cut off the infinite exploration of all the higher primes that can't possibly be factors. That doesn't really make sense if you stop to think about it; by definition anything that isn't a prime factor can't be an element of that list, so you can't filter out the non-factors larger than n from that list. Instead you need to filter the input to that list comprehension so that it doesn't try to explore an infinite space, as #n.m's answer shows.
Here is the code I am trying to use: This should generate all primes up to 100
sieve_primes = [x | x<-[2..100], y<-[2..50], z <-[2..25], (x*z) `mod` y /= 0]
The code
isPrime n = length [x | x<-[2..n], n `mod` x == 0] == 1
computes all the factors just to count them. You don't need to count them: as soon as the second factor is found you can stop your search without checking for further ones.
So, either replace length ... == 1 with a custom predicate, or take 2 elements from the list comprehension before checking its length.
What you had in mind was probably
Prelude> [x| x<-[2..100], not $ elem x [y*z| y<-[2..50], z<-[2..25]]]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
This is very slow. At least we can rearrange the pieces,
Prelude> [x| let sieve=[y*z| y<-[2..50], z<-[2..25]],
x<-[2..100], not $ elem x sieve]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
This is still very slow, for any number much above even 1000 (where you'd use 500 and 250). Then again, why the 25 (250) limit? Your code follows the
primes = [x| x<-[2..], not $ elem x
[y*z| y<-[2..x`div`2], z<-[2..min y (x`div`y)]]]
idea, i.e. y*z = 2*y .. min (y*y) x, so with the known top limit (x <= n) it should be
primesTo n = [x| let sieve=[y*z| y<-[2..n`div`2], z<-[2..min y (n`div`y)]],
x<-[2..n], not $ elem x sieve]
(incidentally, max (min y (n/y)) {y=2..n/2} = sqrt n, so we could've used 10 instead of 25, (and 31 instead of 250, for the 1000)).
Now 1000 is not a problem, only above ~ 10,000 we again begin to see that it's slow (still), running at n2.05..2.10 empirical orders of growth (quick testing interpreted code in GHCi at n = 5000, 10000, 15000).
As for your second (now deleted) function, it can be rewritten, step by step improving its speed, as
isPrime n = length [x | x<-[2..n], n `mod` x == 0] == 1
= take 1 [x | x<-[2..n], n `mod` x == 0] == [n]
= [x | x<- takeWhile ((<=n).(^2)) [2..n], n `mod` x == 0] == []
= and [n `mod` x > 0 | x<- takeWhile ((<=n).(^2)) (2:[3,5..n])]
now, compiled, it can get first 10,000 primes in few tenths of a second.
In my test-exam a question was, what this method does.
dos a = ([x | x <- [2..div a 2], mod a x == 0] == [])
I am new to Haskell but as far as I can say, it checks if the result of dos a = ([x | x <- [2..div a 2], mod a x == 0]) is an empty list. Also x are all numbers of a divided by 2 which have %number == 0. Thus this are all even numbers? It seems like it checks if the number is dividable through 2, if yes -> false, else otherwise. Could anyone explain to me the semantic in detail?
You are close to what is going on. There are several components to understand.
First, [2 .. div a 2] generates a list of numbers from 2 to floor(a / 2).
Next, mod a x == 0 filters out the values from 2 to floor(a / 2) which
divide a (e.g. it finds all the factors of a).
Thus, the list generated by
[x | x <- [2 .. div a 2], mod a x == 0]
contains all the numbers that divide a.
Finally, the == [] checks that
this list is empty (e.g. a has no factors). So, what this function actually
does is to determine whether or not a number is prime by attempting to
generate its factors, which is easy to see when you use dos as the predicate
for filter:
Prelude> let dos a = ([x | x <- [2..div a 2], mod a x == 0] == [])
Prelude> :t dos
dos :: Integral t => t -> Bool
Prelude> filter dos [2 .. 100]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97] -- Prime goodness
It is the basic algorithm to check if a number is prime or not. It traverses over all the numbers from 2 to a/2 and checks if any of it divides a, if the list is empty then it means it has no factors between 2 and a/2 which implies the number is prime.