Prime factorizacion in haskell - list

I'm making a program that, for a given integer n, returns a list of a pair of integers, where the first element is a prime from the prime factorization of n, and the second element is the corresponding exponent of that prime. For example for n = 50, it would output [(2,1),(5,2)], since 50 =(2^1)*(5^2).
So anyway, this is my code:
--returns all numbers that divide x
divis :: Integer -> [Integer]
divis 1 = []
divis x = [n | n<-[2..(x-1)], mod x n == 0]
--checks if a number is prime
isprime :: Integer -> Bool
isprime 1 = False
isprime n = if divis n == [] then True else False
--list of prime numbers that divide x
facto :: Integer -> [Integer]
facto 1 = []
facto x = [n | n <- (divis x), isprime n == True]
--finds the biggest exponent of a number m that divides another number n
potencia :: Integer -> Integer -> Integer
potencia _ 0 = error "error"
potencia _ 1 = error "error"
potencia n m = (head [x | x <- [0..], not(mod n (m^x) == 0)]) - 1
The next step would be that, for a number n, I can put togheter in a pair for each number in facto n its corresponding exponent, and output that.
I have tried with this:
factorizar :: Integer -> [(Integer, Integer)]
factorizar 0 = error "nope"
factorizar 1 = [(1,1)] --This isn't accurate but I'll change it later
factorizar n = [(x,y) | x<-(facto n), y == potencia n x, mod n (x^y) == 0] --THIS
I know, the y part in the set comprehension is ugly everywhere. The thing is I dont know what to use since for defining y I need to use x as well, but it is part of the set comprehension. I have tried changing it, or using 'where' but it always has a problem with 'y', telling me it's not in the scope or something. What could be an elegant solution for this?

The simple answer is
y == potencia n x
should really read
let y = potencia n x
and you don't need to check that mod n (x^y) == 0 - I think it is going to be true by definition of potencia.
There are other things you could do differently, but they are tidy-ups.

Related

Haskell code to compute sum of squares of negative integers using foldr function

I am new to haskell code. I tried to compute the sum of squares of negative integer in a list using foldr high order.
sumsq :: Int -> Int
sumsq n = foldr op 0 [1..n]
where op x y = x*x + y
Please help to explain each line of code and give any solution if error in this code
When using "where", important to follow the indentation rule.
Here lambda will be appropriate
sumsq n = foldr (\x y -> x*x + y) 0 [1..n]

How to round up a real number to nth decimal in SML?

New to SML, trying to round up a real number to nth decimal, by declaring a function round(n,L), where L is a list of real numbers and n decide the nth decimal that can round up to.
My approach is to convert the real number to a string first, and then get the substring to the nth decimal and then parse the substring back to real number, this works fine if I only want to get the real number to nth decimal, but if I have a number like 0.3456 which I want to round to 0.35, my method won't really achieve that.
fun rd(_,[]) = []
|rd(a:int, x::y:real list) =
if x>0.0
then Option.getOpt(Real.fromString(String.substring(Real.toString(x),0,a+2)),0.0) :: rd(a,y)
else Option.getOpt(Real.fromString(String.substring(Real.toString(x),0,a+3)),0.0) :: rd(a,y)
The expected result is like this:
- rd (2, [0.1234, 0.2345, ~0.3456]);
val it = [0.12,0.23,~0.35] : real list`
But the actual output I got is
val it = [0.12,0.23,~0.34] : real list
If I want to round up the number, is there any good approach?
I've also tried this:
fun rd(_,[]) = []
|rd(a:int, x::y:real list) =
let
val n = real(round(x*Math.pow(10.0,real(a)))) / Math.pow(10.0,real(a))
in n::rd(a,y)
end;
but this solution will give me an uncaught exception overflow...
trying to round up a real number to nth decimal
declaring a function round(n,L), where L is a list of real numbers and n decide the nth decimal
Judging by your use of Math.pow(10.0,real(a)) in your second attempted solution, you seem to be on track. I don't understand where a list comes in; as Yawar points out, try and solve this for rounding a single real, and then apply that recursively (using map) to a list of reals.
So a function
fun roundN (x, n) = ...
fun roundManyN (xs, n) = map (fn x => roundN (x, n)) xs
Start by making some examples and encode them as tests. Since you can't compare real for equality in those tests, start by making (or copying) a custom equality operator.
fun nearlyEqual (a, b, eps) =
let val absA = Real.abs a
val absB = Real.abs b
val diff = Real.abs (a - b)
in Real.== (a, b) orelse
( if Real.== (a, 0.0) orelse
Real.== (b, 0.0) orelse
diff < Real.minNormalPos
then diff < eps * Real.minNormalPos
else diff / Real.min (absA + absB, Real.maxFinite) < eps )
end
val test_roundN_1 =
let val got = roundN (3.14159, 1)
val expected = 3.1
in nearlyEqual (got, expected, 0.1) end
val test_roundN_2 =
let val got = roundN (3.14159, 2)
val expected = 3.14
in nearlyEqual (got, expected, 0.01) end
(* rounding point *)
val test_roundN_3 =
let val got = roundN (3.14159, 3)
val expected = 3.142
in nearlyEqual (got, expected, 0.001) end
(* rounding point *)
val test_roundN_4 =
let val got = roundN (3.14159, 4)
val expected = 3.1416
in nearlyEqual (got, expected, 0.0001) end
val test_roundN_5 =
let val got = roundN (3.14159, 5)
val expected = 3.14159
in nearlyEqual (got, expected, 0.00001) end
You also have some edge cases that you eventually want to deal with:
When n is zero or negative, or when n is greater than the number of digits in the fraction.
When x is close to a rounding point, e.g. roundN (3.1451, 2) ~> 3.15.
When x·10ⁿ has a magnitude that exceeds the size of an int.
When n is so large that a magnitude change may affect the precision of a real.
For a better testing library, check out testlib.sml (and its use in test.sml) in this exercism exercise.
Extracting your second solution into a function, and giving Math.pow (10.0, real n) a temporary binding, you get the solution:
fun roundN (x, n) =
let val m = Math.pow(10.0, real n)
in real (round (x * m)) / m end
this solution will give me an uncaught exception overflow
On what input, I might ask.
One source could be that round : real -> int is a partial function: There are real values that cannot be expressed as int, such as Real.posInf, Real.negInf, 1e10 (on 32-bit SML) and 1e19 (on 64-bit SML). To avoid this, consider using Real.realRound : real -> real to avoid the int conversion.
One way to avoid errors related to x * Math.pow(10.0, real n) causing imprecision because the number grows too big, could be to strip the integer part before multiplying, and adding the integer part back after dividing.

Strange result of List generation in Haskell

From Ranges in Haskell (GHCi) it's pretty much clear why the [2, 2..20] generate infinity list.
The next value is the same, that why this code produces infinity list.
And looks like it doesn't care about limit because of [2, 2..2] generate also infinity list.
Question:
Why the following code [2, 2..(-20)] generate empty list instead?
In short: This is intended behavior.
The [x, y..z] expression is syntactical sugar for enumFromThenTo x y z with enumFromThenTo :: a -> a -> a -> [a].
For Integers it is implemented like:
instance Enum Integer where
# ...
enumFromThenTo x y lim = enumDeltaToInteger x (y-x) lim
So it will call enumDeltaToInteger 2 0 (-20). The enumDeltaToInteger is implemented with [src]:
enumDeltaToInteger :: Integer -> Integer -> Integer -> [Integer]
enumDeltaToInteger x delta lim
| delta >= 0 = up_list x delta lim
| otherwise = dn_list x delta lim
Soo it is considered to be an up_list, and the up_list will increase until it has reached a value larger than lim:
up_list :: Integer -> Integer -> Integer -> [Integer]
up_list x0 delta lim = go (x0 :: Integer)
where
go x | x > lim = []
| otherwise = x : go (x+delta)
This is how it has been described in the Haskell'10 report on the Enum class:
The sequence enumFromThenTo e1 e2 e3 is the list [e1,e1 + i,e1 + 2i,…e3], where the increment, i, is e2 − e1. If the increment is positive or zero, the list terminates when the next element would be greater than e3; the list is empty if e1 > e3. If the increment is negative, the list terminates when the next element would be less than e3; the list is empty if e1 < e3.
So the document says that if the "step" is zero or more, and e1 > e3, then the result is the empty list.
It is indeed a "tricky" case however. I personally agree that using a special case for 0 as "step" would make sense (although I'm not per se saying this is more favorable than using the up_list implementation). It is however how things are defined.

How to get integers from list where sum of them is less than X?

Sorry for the mess that was here.
I wanted a classic greedy algorithm for knapsack problem in haskell for integers.
But there was other question - how to refer to list in list comprehension?
There are several approaches to this:
Generate all lists which are smaller. Take the longest
For every n <= X, generate [1..n] and check whether its sum is lesser x. Take the longest of those sets:
allLists x = takeWhile ( (<=x) . sum) $ inits [1..]
theList = last . allLists
where inits is from Data.List
Alternatively, we remember mathematics
We know that the sum of [1..n] is n*(n+1)/2. We want x >= n * (n+1)/2. We solve for n and get that n should be 0.5 * (sqrt (8 * x + 1) - 1). Since that's not a natural number, we floor it:
theList x = [1..n]
where n = floor $ 0.5 * (sqrt (8 * (fromIntegral x) + 1) - 1)
This will give all the lists that its sum is not greater than 100:
takeWhile (\l -> sum l <= 100) $ inits [1..]

Sieve of Eratosthenes with Wheel Factorization

I'm implementing a reasonably fast prime number generator and I obtained some nice results with a few optimizations on the sieve of Eratosthenes. In particular, during the preliminary part of the algorithm, I skip all multiples of 2 and 3 in this way:
template<class Sieve, class SizeT>
void PrimeGenerator<Sieve, SizeT>::factorize()
{
SizeT c = 2;
m_sieve[2] = 1;
m_sieve[3] = 1;
for (SizeT i=5; i<m_size; i += c, c = 6 - c)
m_sieve[i] = 1;
}
Here m_sieve is a boolean array according to the sieve of Eratosthenes.
I think this is a sort of Wheel factorization only considering primes 2 and 3, incrementing following the pattern 2, 4, 2, 4,..
What I would like to do is to implement a greater wheel, maybe considering primes 2,3 and 5.
I already read a lot of documentation about it, but I didn't see any implementation with the sieve of Eratosthenes... a sample code could help a lot, but also some hints would be nice :)
Thanks.
You can go even further. Here is some OCaml code I wrote a few years ago:
let eratosthene borne =
let remove_multiples a lst =
let rec remmult multa li accu = function
[] -> rev accu
| head::tail ->
if multa = head
then remmult (a*(hd li)) (tl li) accu tail
else remmult multa li (head::accu) tail
in
remmult (a * a) lst [] lst
in
let rec first_primes accu ll =
let a = hd ll in
if a * a > borne then (rev accu) # ll
else first_primes (a::accu) (remove_multiples a (tl ll))
in
let start_list =
(* Hard code of the differences of consecutive numbers that are prime*)
(* with 2 3 5 7 starting with 11... *)
let rec lrec = 2 :: 4 :: 2 :: 4 :: 6 :: 2 :: 6 :: 4 :: 2 :: 4 :: 6
:: 6 :: 2 :: 6 :: 4 :: 2 :: 6 :: 4 :: 6 :: 8 :: 4 :: 2 :: 4 :: 2
:: 4 :: 8 :: 6 :: 4 :: 6 :: 2 :: 4 :: 6 :: 2 :: 6 :: 6 :: 4 :: 2
:: 4 :: 6 :: 2 :: 6 :: 4 :: 2 :: 4 :: 2 :: 10 :: 2 :: 10 :: lrec
and listPrime2357 a llrec accu =
if a > borne then rev accu
else listPrime2357 (a + (num (hd llrec))) (tl llrec) (a::accu)
in
listPrime2357 (num 11) lrec []
in
first_primes [(num 7);(num 5);(num 3);(num 2)] start_list;;
Note the nice trick that OCaml allows for cyclic linked list.
Paul Pritchard, an Australian mathematician working for IBM, developed a series of wheel sieves in the 1980s. I discuss one of them at my blog, including examples worked by hand and an implementation in Scheme. It's too big to discuss here. You should be aware that though the asymptotic complexity is less than the Sieve of Eratosthenes, implementation details typically make it slower in practice.
2*3*5 = 30
spokes = 2,3,4,5,6,8,9,10,12,15,16,18,20,24,30
numbers between spokes: 1,7,11,13,17,19,23,25,29
int[] gaps = [6,4,2,4,2,4,2,4];
int[] primes = [2,3,5];
int max = 9001;
int counter, max_visited;
while(max_visited < max) {
int jump = gaps[counter];
counter = counter + 1 % gaps.length;
max_visited += jump;
}
Does that help?
Alternatively, this might have been what you wanted instead, pseudo-code:
primes = [2,3,5];
product = multiply(primes);//imaginary function that returns 30
wheel = new int[product];
foreach(prime in primes)
for(int x = 1; x <= product/prime; x++)
wheel[prime*x] = 1;
return wheel
There's a much better optimisation of it (it takes O(n) operations instead of O(n log log n) for your variant): https://stackoverflow.com/a/17550147/2559094 , but it takes more memory (uses n + n/log n memory instead of n).
If you still want to go on with your optimisation and consider primes p1, p2, ..., pn, you should write all numbers from 0 to p1*p2*...*pn (use lcm in case you decide to use not only prime numbers) and check which of them satisfy the following system:
x != 0 (mod p1)
x != 0 (mod p2)
...
x != 0 (mod pn)
Then you should find all the gaps between these numbers and make an array of those gaps to use them.