Is there a better way to check n and c in this code, maybe with pattern matching or something more Haskell-like?
toBin :: Int -> Int -> [Int]
toBin n c
| n < 0 = []
| c <= 0 = []
toBin n c = toBin (n `div` 2) (c - 1) ++ [n `mod` 2]
Well, they're both boolean expressions, so you can combine them with ||
toBin n c | n < 0 || c <= 0 = []
It is better here to work with an accumulator, which prevents making O(n) appends that result in an O(n2) algorithm in your code:
toBin :: Int -> Int -> [Int]
toBin = go []
where go rs n c
| n < 0 || c <= 0 = rs
| otherwise = go (r:rs) q (c-1)
where (q,r) = quotRem n 2
We here thus start with an empty list, and each time prepend the list with the next remainder until the number is zero, or the number of bits is 0.
Related
I have this function which takes an integer n and returns a list of type Maybe Int, containing the unique prime factors. I don't understand why it returns them with Just inside every element of the list.
I expect an output like this:
primeFactors 75 = Just [3,5]
But I have one that looks like this:
primeFactor 75 = [Just 5,Just 3,Just 1]
Here is my code:
divides :: Int -> Int -> Bool
divides m n = rem m n == 0
transform :: Int -> Int
transform n = (n*2) + 1
isComposite :: Int -> Bool
isComposite n = foldl (||) (divides n 2) (map (divides n) (map (transform) [1..(div n 4)]))
isPrime :: Int -> Bool
isPrime n
| n <= 0 = error "Makes no sense"
| n < 4 = True
| otherwise = not (isComposite n)
primeFactors :: Int -> [Maybe Int]
primeFactors 0 = [Nothing]
primeFactors n = primeFactors2 n ((div n 2)+1)
primeFactors2 :: Int -> Int -> [Maybe Int]
primeFactors2 n 0 = []
primeFactors2 n x
| divides n x && isPrime x = Just x:primeFactors2 n (x-1)
| otherwise = primeFactors2 n (x-1)
Here is a version of your code that I think will do what you want:
primeFactors :: Int -> Maybe [Int]
primeFactors n
| n <= 0 = Nothing
| otherwise = Just $ primeFactors2 n n
primeFactors2 :: Int -> Int -> [Int]
primeFactors2 n p
| n <= 1 || p <= 1 = []
| divides n p && isPrime p = p : primeFactors2 (n `div` p) p
| otherwise = primeFactors2 n (p-1)
isPrime :: Int -> Bool
isPrime n
| n <= 1 = False
| otherwise = not (isComposite n)
isComposite :: Int -> Bool
isComposite n =
any (divides n) [2..n-1]
divides :: Int -> Int -> Bool
divides m n =
rem m n == 0
Please note that (for clarity's sake I hope) I did remove some of your optimizations and made a major change: this one will report Just [2,2] as prime-factors for 4
(IMO you want product <$> primeFactors n == Just n).
If not (as your example indicates) it shouldn't be too hard to fix this (just take your version).
Anyway the only really interesting contribution is how primeFactor handles primeFactors2 to get you the Maybe result.
I'm trying to create a code in Haskell that does n^k = (n * n)^(k/2) when k is even, and n^k = n * (n^(k−1)) if k is odd.
I'm doing something wrong, but I can't figure out how to solve it.
power2 :: Integer -> Integer -> Integer
power2 n 0 = 1
power2 n k
| k < 0 = error "negative argument"
| k `mod` 2 == 0 = even -- Am I supposed to write = even here?
| otherwise = odd
if k even = (n 2) ( div k 2) -- (n^2)^(k/2) ???
if k odd = n * (n) (k-1)) -- Is this n^(k-1) ???
even and odd are functions in Haskell and you may use them directly inside guards conditions to test if a number is even/odd.
Below is one option:
power2 :: Integer -> Integer -> Integer
power2 n 0 = 1
power2 n k
| k < 0 = error "negative argument"
| even k = power2 (n * n) (div k 2)
| odd k = n * ( power2 n (k-1) )
http://zvon.org/other/haskell/Outputprelude/odd_f.html
http://zvon.org/other/haskell/Outputprelude/even_f.html
EDIT:
Of course you may write your own version of even/odd functions and use them as an alternative.
Example:
myEven :: Integer -> Bool
myEven n = n `mod` 2 == 0
myOdd :: Integer -> Bool
myOdd n = n `mod` 2 == 1
power2 :: Integer -> Integer -> Integer
power2 n 0 = 1
power2 n k
| k < 0 = error "negative argument"
| myEven k = power2 (n * n) (div k 2)
| myOdd k = n * ( power2 n (k-1) )
I have implemented the following two functions for establishing if n is a fermat prime number (will return n if its true, -1 if not), but it returns always -1, can't figure out why (gc is a funct taht calculates gcd)
fermatPT :: Int -> Int
fermatPT n = fermatPT' n list
where
list = [a | a <- [1..n-1]]
-- | heper function
fermatPT' :: Int -> [Int] -> Int
fermatPT' n l | gc (n, head l) == 1 && fermatTest n (head l) = fermatPT' n (tail l)
| null l = n
| otherwise = -1
where
fermatTest n a = mod (a^(n-1)) n == 1
Your function should return a boolean indicating if the given number is a prime. If you do that, you can use the all function to define this simply as
fermatPT :: Integer -> Bool
fermatPT n = all (fermatTest n) (filter (\a -> gcd n a == 1) [1..n-1])
where fermatTest n a = mod (a^(n-1)) n == 1
gcd is defined in the Prelude.
all avoids the explicit recursion that requires you to apply the test to one element of [1..n-1] at a time; its definition is effectively
all _ [] = True
all p (x:xs) = p x && all p xs
Note that mod (a ^ (n - 1)) n is inefficient, since it may require computing an absurdly large number before ultimately reducing it to the range [0..n-1]. Instead, take advantage of the fact that ab mod n == (a mod n * b mod n) mod n, and reduce the value after each multiplication. One way to implement this (not the fastest, but it's simple):
modN :: Integer -> Integer -> Integer -> Integer
modN a 0 _ = 1
modN a b n = ((a `mod` n) * (modN a (b - 1) n)) `mod` n
Then use
fermatTest n a = modN a (n-1) n == 1
Note that you could use this (with Int instead of Integer) to correctly implement fermatPT :: Int -> Bool; although the input would still be restricted to smaller integers, it won't suffer from overflow.
I'm trying to write a procedure that returns a list of all primes below a given number.
For example:
Prelude>primes 8
[2,3,5,7]
When I try to load the file I get Parse error in pattern Failed, modules loaded: none. If someone could point me in the right direction I would be grateful.
primes :: Int -> [Int]
primes x < 2 = []
primes x | isPrime x == True = primes (x - 1) ++ x
| otherwise = primes (x - 1)
isPrime :: Int -> Bool
isPrime x | x < 2 = False
| x == 2 || x == 3 = True
| divEven x == True = False
| divOdd x 3 == True = False
| otherwise = True
divEven :: Int -> Bool
divEven x | mod x 2 == 0 = True
| otherwise = False
divOdd :: Int Int -> Bool
divOdd x num | mod x num == 0 == True
| num <= x/2 = divOdd x (num + 2)
| otherwise = False
A collection of small mistakes.
Your syntax is incorrect.
primes x < 2 = []
Probably you meant
primes x | x < 2 = []
Similarly, where you write
divOdd x num | mod x num == 0 == True
you probably meant
divOdd x num | mod x num == 0 = True
The type signature
divOdd :: Int Int -> Bool
is not valid. You probably meant
divOdd :: Int -> Int -> Bool
x is of type Int, and (/) :: Fractional a => a -> a -> a cannot be applied to it. You probably mean num <= x `div` 2 or 2 * num <= x.
divOdd :: Int Int -> Bool
divOdd x num | mod x num == 0 == True
| num <= x/2 = divOdd x (num + 2)
| otherwise = False
x is of type Int, not [Int]. (++) :: [a] -> [a] -> [a] will not apply to it.
primes x | isPrime x == True = primes (x - 1) ++ x
Perhaps you meant
primes x | isPrime x == True = primes (x - 1) ++ [x]
Finally, this is a fairly inefficient way of generating primes. Have you considered a sieve? Prime numbers - HaskellWiki may be a bit difficult for you right now, but shows many different strategies.
Here's a re-write of your functions using list comprehensions (also in Wikipedia), perhaps this is more visually apparent:
primes :: Int -> [Int]
primes x | x<2 = []
| x<4 = [2..x]
| True = primes (x-1) ++ [x | isPrime x]
your isPrime is
isPrime x = x > 1 &&
( x < 4 ||
and [ rem x n /= 0 | n <- 2 : [3,5..(div x 2)+2] ] )
and is a function defined in standard Prelude. It will test entries in a list, left to right, to see if all are True. It will stop on the first False entry encountered, so the rest of them won't get explored.
Sometimes when the code is more visually apparent it is easier to see how to improve it.
import Data.Char
blockCode :: S
lett2num :: Char -> Int
lett2num y
| (or
num2bin :: Int -> [Int]
num2bin n: negative number"
where n2b 0 = []
n2b n = n `mod` 2 : n2b (n `div` 2)
You can use concatMap show to transform a list into a string:
Main> num2bin 8
[0,0,0,1]
Main> concatMap show $ num2bin 8
"0001"
but note that your function's output is reversed.
To do everything in one go, do
num2bin :: Int -> String
num2bin n
| n >= 0 = concatMap show $ reverse $ n2b n
| otherwise = error "num2bin: negative number"
where n2b 0 = []
n2b n = n `mod` 2 : n2b (n `div` 2)
Function converts integer to binary:
num2bin :: (Integral a, Show a) => a -> String
num2bin 0 = "0"
num2bin 1 = "1"
num2bin n
| n < 0 = error "Negative number"
| otherwise = num2bin (n `div` 2) ++ show (n `mod` 2)