Smallest number divisible by 10^n with digits totaling n -- Haskell - haskell

I need to do this program:
minor :: Integer -> Integer
such that (minor n) is the smallest number divisible by 10^n whose digits add up to n. For example,
minor 5 == 500000
minor 20 == 29900000000000000000000
length (show (minor 67^35+3)) == a
I have tried this
minor :: Integer -> Integer
minor n = minimum [x | x <- [n*10^n..], rem x 10^n == 0, sum (digits x) == n]
digits :: Integer -> [Integer]
digits n = [read[d] | d <- show n]
But it's very inefficient, because the computer gets stuck. How would they do that? Thanks.

There are 2 key observations which can be made for this problem:
The number always ends with n zeros.
The rest of the digits are all 9 (except maybe the first digit).
This means you can find the number of nines by dividing by 9, and you can find the left-most digit by using the remainder from that division.
20 = 2 + (2 * 9) = 2 + 9 + 9 ⇒ 299
35 = 8 + (3 * 9) = 8 + 9 + 9 + 9 ⇒ 8999
In Haskell, you can use quotRem to divide by 9 and get both the quotient and remainder at the same time. You can then use these numbers to construct the output number.
minor :: Integer -> Integer
minor n = ((r + 1) * (10 ^ q) - 1) * (10 ^ n)
where (q, r) = n `quotRem` 9
If you're only interested in calculating the number of digits in the output, you can find that out by observing the parts of minor that serve as exponents to 10, namely q and n. If r isn't 0, you can add 1 more digit.
minorLength :: Integer -> Integer
minorLength n = signum r + q + n
where (q, r) = n `quotRem` 9

You can compute the number of digits in the minor of a number without ever computing the number's minor directly, and this is important if you want to know the number of digits in the minors of large inputs.
Willem describes the main first trick: the minor of a number is a single digit, followed by a bunch of 9s, followed by a bunch of 0s. Since we only care how many there are, we can compute those things directly.
numLeadingDigits n = signum (n `mod` 9)
num9s n = n `div` 9
num0s n = n
Now the complete length is just the sum of these.
numDigitsInMinor n = numLeadingDigits n + num9s n + num0s n
This can indeed be run on enormous inputs:
> numDigitsInMinor (67^35 + 3)
9086059680492581695084814449385436459012675694436486492711692052
Computing this minor explicitly would have required 10^63 bytes of memory, many orders of magnitude over the total amount of storage ever produced by the human race in all of history.

Calculating the smallest number
Instead of using a brute force algorithm, we first better think how we can find such number.
A number that is dividably by 10n has n tailing zeros. For example for n=3, then the numbers are 1000, 2000, 3000, etc.
Next we want to find the smallest this means that the digits we have control over (the ones before the last n should be as large as possible at the tail, in order to be small at the lead). The digits are limited between zero and nine.
So we can look for the smallest number where the sum of the digits is n with:
smallest_sum :: (Num n, Ord n) => n -> n
smallest_sum 0 = 0
smallest_sum x = d + 10 * smallest_sum (x - d)
where d = min 9 x
So here d = min 9 x is the digit we calculate, and the digits before are calculated with recursion.
So now the smallest number that satisfies these constraints is:
minor :: Integral i => i -> i
minor n = smallest_sum n * 10 ^ n
So this works in linear time with the value of n.
Examples:
Prelude> minor 5
500000
Prelude> minor 20
29900000000000000000000
Prelude> minor 0
0
Prelude> minor 1
10
Prelude> minor 2
200
Prelude> minor 3
3000
Prelude> minor 4
40000
Prelude> minor 5
500000
Prelude> minor 6
6000000
Prelude> minor 7
70000000
Prelude> minor 8
800000000
Prelude> minor 9
9000000000
Prelude> minor 10
190000000000
The length of that number
But this will, like #DanielWagner says, not suffice to calculate the length, since that number will be gigantic: for 67^35+3 it will contain approximately 10^64 digits, this can not be stored in memory. The point is that we do not have to calculate the number itself in order to calculate the length, we can derive the length with:
length_minor :: Integral i => i -> i
length_minor n = length_smallest_sum n + n
where length_smallest_sum n = div (n+8) 9
So a very compact function that calculates it is:
length_minor :: Integral i => i -> i
length_minor n = div (n+8) 9 + n
or even more compact (but if we use a small integer representation, a bit dangerous for overflow):
length_minor :: Integral i => i -> i
length_minor n = div (10*n+8) 9

Related

Sum of digits of non-negative number using list comprehension

I'm looking for a non-recursive implementation of sum of digits (a "cross sum") of a non-negative number like this:
cs :: Int -> Int
cs n = sum digits_of_n where digits_of_n = [ . | ... ]
Basically: How does one get a list of digits from a non-negative whole number using list comprehension only?
A cross sum example: The crossum of 157 is 1 + 5 + 7 = 13
The "usual way" would be extracting the digits from a number recursively using modulo and division, and then summing them up like this:
cs :: Int -> Int
cs n = if n == 0 then 0 else n `mod` 10 + cs (n `div` 10)
I have however difficulty expressing this without recursion and with list comprehension, does anyone have ideas regarding this?
sume n = foldr (+) 0 [ digitToInt c | c <- show n, isDigit c ]

Haskell/GHC - Is there a way around Haskell only returning 16 decimal places?

I am trying to write a program in Haskell that returns 'e' (Euler's number) to a given decimal place. Here is my code so far:
factorial 0 = 1
factorial n = n * factorial (n - 1)
calculateE a
| a == 0 = 1
| otherwise = nextLevel
where nextLevel = (1 / (factorial a)) + calculateE (a-1)
Whenever I call calculateE I only get back 16 decimal places. Is this a limitation of Haskell/My computer? Is there a way to get back any number of decimal places?
This code already works to arbitrary precision. You just need to use an arbitrary precision type and not the standard Float/Double. Haskell's standard library has Rational for this purpose, which represents rational numbers as pairs of integers.
ghci> calculateE 100 :: Rational
4299778907798767752801199122242037634663518280784714275131782813346597523870956720660008227544949996496057758175050906671347686438130409774741771022426508339 % 1581800261761765299689817607733333906622304546853925787603270574495213559207286705236295999595873191292435557980122436580528562896896000000000000000000000000
The issue now is getting a sequence of digits out of it. I'm not aware of anything in the standard library that does it, so here's a stupid simple (might still be buggy!) implementation:
import Data.List(unfoldr)
import Data.List.NonEmpty(NonEmpty((:|)))
import Data.Ratio
-- first element is integral part (+ sign), rest are positive and < 10 and are digits
-- after the decimal point (for negative numbers, these digits should be seen as having negative value)
longDivision :: Integral a => Ratio a -> NonEmpty a
longDivision x = hi :| unfoldr go (abs lo)
where (hi, lo) = numerator x `quotRem` denominator x
go 0 = Nothing
go lo = Just $ (lo * 10) `quotRem` denominator x
printDigits :: Show a => NonEmpty a -> String
printDigits (x :| xs) = show x ++ "." ++ concatMap show xs
So
ghci> take 100 $ printDigits $ longDivision $ calculateE 100
"2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642"
This approximation actually seems to be good to ~160 digits after the decimal point.

Finding result of a recursive function

The given question is: "What is the value of f 572 for the following definition of f?"
f :: Int -> Int
f n = g n (n+1)
g :: Int -> Int -> Int
g m i
| (mod i m) == 0 = i
| otherwise = g m (i+1)
To me this looks like a recursive function and the answer should be that the values keep adding up from 572 till 1044 (that's when mod 1044 572 will be 0).
It is a very inefficient way to calculate the double (2*) of a number. Because you feed g n (n+1).
g is given two numbers and as long as (mod i m) == 0 fails (i is not dividable by m) it will increment i. From the moment it succeeds, it returns i. Now the lowest n larger than k that is dividable by k is obviously 2*k.
So f is equivalent to:
-- equivalent to
f' = (2*)
In case negative numbers are also considered, it will always return 0, for the strictly negative numbers since the first such number to satisfy the modulo relation is 0. Finally if 0 is given, it will error. So when considering zero and negative numbers, the full definition is:
-- equivalent (with negative numbers and zero)
f' n | n > 0 = 2*n
| n < 0 = 0
-- n == 0 should error
Since the algorithm increments i each time, the program will run linear with n (given increment and modulo can be checked in constant time) so O(n). The equivalent definition runs of course in constant time (given multiplication and comparisons can be done in constant time, this is not the case for Integer for instance).

Find factor primes in haskell

Write a function called factor that will take an Integer and determine its prime factors (called prime factorization). The function should take an integer and return a list of integers. This list should be the prime factors of the number, not including multiplicity. For example, the prime factors of 56 are 2 and 7 (even though the full multiplication is 56 = 23 × 7 = 2 × 2 × 2 × 7). What are the prime factors of 175561 and 62451532000?
So far, what I got is:
factor :: Int -> [Int]
factor n
| factors == [] = [n]
| otherwise = (factors ++ factor (n `div` (head factors)))
where factors = take 1 $ filter (\x -> (n `mod` x) == 0) [2 .. n-1]
but this print the full multiplication, when plug 56 it gives 2.2.2.7 and I want it with no duplication like 2, 7.
How can I filter?
Use nub :: Eq a => [a] -> [a], which removes duplicate elements from lists.
http://hackage.haskell.org/package/base-4.9.0.0/docs/Data-List.html#v:nub

Sieve of Sundaram - list comprehension

I am trying to write a function that calculates all odd prime numbers from 1..n using the "Sieve of Sundaram" algorithm.
Here is my try:
sSund :: Integer -> [Integer]
sSund n = [ i * 2 + 1 | i <- [1..n], j <- [f i], (i + j + 2 * i * j) > n ]
where f 1 = 1
f y = y + 1 --use function f because i don't know how insert 1 into j's list
But it gives some wrong numbers like 9,15,21,25, etc.
*Main> sSund 30
[7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61]
What am I doing wrong?
How it works
Sundaram's seive works by focussing on the odd numbers 2n+1, and excluding those that are the product of numbers.
If two numbers multiply to make an odd number, they must both be odd, so our number 2n+1 = (2i+1)(2j+1). If we multiply that out we get 2n+1 = 4ij + 2i +2j + 1, which we can simplify to 2n=4ij+2i+2j, which again simplifies to n=2ij+i+j. So we don't want n if we can write it as 2ij+i+j. This is true for any numbers i and j, but it's OK to just get rid of the ones where i<=j, because otherwise you're definitely excluding the same number twice.
Fixing your code
In your code, you generate some numbers i + j + 2 * i * j to be excluded, but you in fact just exclude the i instead of the i + j + 2 * i * j. The j<-[f i] just gives you a single j value in a list instead all the numbers from i up to n, which you should write as [i..n].
It's much simpler to just generate the exclusion list first:
sSundDelete :: Integer -> [Integer]
sSundDelete n = [i+j+2*i*j|i<-[1..n], j<-[i..n]]
Here I've decided to just allow i and j to be between 1 and n, because otherwise 2ij+i+j is definitely bigger than n.
Now we can make a list of numbers x which don't include these numbers, and then make them odd with the formula 2*n+1:
sSund :: Integer -> [Integer]
sSund n = let del = sSundDelete n in
2:[2*x+1 | x <- [1..n], not (x `elem` del)]
Which correctly gives you
> sSund 30
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61]
Speeding things up
It's not as fast as it could be, though, because if you look at
> sSundDelete 10
[4,7,10,13,16,19,22,25,28,31,12,17,22,27,32,37,42,47,52,24,31,38,45,52,59,66,73,40,49,58,67,76,85,94,60,71,82,93,104,115,84,97,110,123,136,112,127,142,157,144,161,178,180,199,220]
it has numbers much bigger than we need - sSund 10 only goes as far as 2*10+1=21. This means we're checking our numbers again and again against numbers that we didn't consider anyway!
The simplest thing to do about this is to rewrite sSundDelete to say
sSundDelete n = [i+j+2*i*j|i<-[1..n], j<-[i..n],i+j+2*i*j<=n]
very much as you did, or
sSundDelete n = filter (<= n) [i+j+2*i*j|i<-[1..n], j<-[i..n]]
Using a bit of maths to speed things up
The problem with these is that they generate too many numbers and then throw them away. It would be faster to generate only the numbers we need.
Actually, I think it's best to calculate how far to go. the smallest j we will ever use is i, so the smallest that 2ij+i+j can be is 2i2+2i. If we don't want that to be over n, we want 2i2+2i<=n, which we can rewrite as 2i(i+1)<=n. Correctness is more important than efficiency, so it's OK to go over n a bit, but it's important not to miss out numbers below n, so we're OK to say 2i2<=n. This can be expressed as i <= floor (sqrt (fromIntegral n / 2)) (floor truncates decimals, so floor 35.7 is 35, and fromIntegral is used here to convert n to a floating point number (allowing non-integers) so we can do division and square roots.
That was a lot of working out, but now we can just calculate once how big i should go:
sSundDelete n = filter (<= n) [i+j+2*i*j|i<-[1..floor (sqrt (fromIntegral n / 2))], j<-[i..n]]
We can do a similar job on j. We want 2ij+i+j<=n, which we can rearrange to say (2i+1)j<=n-i which can be done as j<=floor( (n'-i')/(2*i'+1)) where i'=fromIntegral i and n'=fromIntegral n. This gives us
sSundDelete n = [i+j+2*i*j|let n'=fromIntegral n,
i<-[1..floor (sqrt (n' / 2))],
let i' = fromIntegral i,
j<-[i..floor( (n'-i')/(2*i'+1))]]
This makes it fast enough for me to not give up waiting for sSund 5000 to calculate the second prime number!

Resources