0

I'm new to Haskell and I'm wondering if it's possible to provide a range of the first 51 prime numbers as input rather than typing the prime numbers, see line 2 ?

If so, please modify the code and post the solution.

  1 perfect_nums n = (2^(n-1)) * ((2^n)-1)
  2 fperfect_nums = [perfect_nums x | x <- [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,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233]]
  3 main = print $ fperfect_nums

Will Ness
  • 70,110
  • 9
  • 98
  • 181
Tom
  • 39
  • 1
  • 6
  • You can create a function to [generate the first n prime numbers](https://stackoverflow.com/questions/35754806/generate-first-n-primes-haskell) and use those to populate your list. – f4him Sep 01 '21 at 02:51
  • There are various ways in Haskell to produce the list of prime numbers, as detailed in the [relevant page of the Haskell wiki](https://wiki.haskell.org/Prime_numbers). – jpmarinier Sep 01 '21 at 12:17

2 Answers2

1

You can write a function to generate primes or use a library. I like to use arithmoi for this purpose:

import Math.NumberTheory.Primes (nextPrime, unPrime)

perfectNums :: Integer -> Integer
perfectNums n = (2^(n-1)) * ((2^n)-1)

fperfectNums :: [Integer]
fperfectNums = [perfectNums (unPrime x) | x <- take 51 [nextPrime 0 ..]]

main :: IO ()
main = print fperfectNums
Noughtmare
  • 9,410
  • 1
  • 12
  • 38
  • I'm getting the error shown below. I import it the same way. Is there any other module that needs to be imported? Could not find module ‘Math.NumberTheory.Primes’ Use -v to see a list of the files searched for. | 1 | import Math.NumberTheory.Primes (nextPrime, unPrime) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Failed, no modules loaded. – Tom Sep 01 '21 at 13:22
  • 2
    @Tom: you need to install the `arithmoi` package first. – Willem Van Onsem Sep 01 '21 at 16:33
0

Well you already have

fperfect_nums = [perfect_nums x | x <- [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,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233]]
              = [perfect_nums x | x <- primes51]

primes51 = [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,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233]

and that is

 = take 51 $ [2 .. 288] `minus`
      [4, 6 .. 288] `minus`       -- all the multiples of 2 in the range
       [9, 12 .. 288] `minus`      -- all the multiples of 3 in the range
        [25, 30 .. 288] `minus`     -- and of 5, 7, 11, ...
         [49, 56 .. 288] `minus`     -- until we see that
          [121, 132 .. 288] `minus`   -- 13*13 = 169  whereas
           [169, 182 .. 288]           -- 17*17 = 289   which is above 233

 = take 51 $ [2 .. 288] `minus`
      (let {p=2} in [p*p, p*p+p .. 288]) `minus` 
       (let {p=3} in [p*p, p*p+p .. 288]) `minus` 
        (let {p=5} in [p*p, p*p+p .. 288]) `minus` 
         (let {p=7} in [p*p, p*p+p .. 288]) `minus` 
          (let {p=11} in [p*p, p*p+p .. 288]) `minus`  -- 13*13 = 169
           (let {p=13} in [p*p, p*p+p .. 288])          -- 17*17 = 289

 = take 51 $ [2 .. 288] `minus` (
      (let {p=2} in [p*p, p*p+p .. 288]) `union` 
       (let {p=3} in [p*p, p*p+p .. 288]) `union` 
        (let {p=5} in [p*p, p*p+p .. 288]) `union` 
         (let {p=7} in [p*p, p*p+p .. 288]) `union` 
          (let {p=11} in [p*p, p*p+p .. 288]) `union`
           (let {p=13} in [p*p, p*p+p .. 288]) )

 = take 51 $ [2 .. 288] `minus` ( foldr1 union
      [[p*p, p*p+p .. 288] | p <- [2,3,5,7,11,13]] )

minus xs ys = [ x | x <- xs, not (elem x ys)]
union xs ys = xs ++ ys

So yes, it is indeed possible to provide a range of the first 51 prime numbers as input rather than typing all the 51 prime numbers yourself. You just need to type the first 6 prime numbers yourself, for that.

And you actually have 61 of them there,

primesTo288 = 2 : [3 .. 288] `minus` ( foldr1 union
      [[p*p, p*p+p .. 288] | p <- [2,3,5,7,11,13]] )
 = 2 : 3 : [5,7 .. 288] `minus` ( foldr1 union
      [[p*p, p*p+2*p .. 288] | p <- [3,5,7,11,13]] )

Now to make it unbounded ....

Will Ness
  • 70,110
  • 9
  • 98
  • 181