How to solve a Digital Root using SML - sml

I am having trouble with writing a function that will calculate a digital root of an integer. Consider the process of taking a number 'n', adding its digits, then adding the digits
of the number derived from it, etc., until the remaining number has only one digit.
The final single-digit number is called the digital root of 'n'. For example, the sequence obtained from the starting number 6381 is (6381, 18, 9), so 6381 has a digital root of 9.
My code:
fun digits(m:int) =
if m < 10 then
[m]
else
let
val smallestDigit = m mod 10
val remainingDigits = m div 10
in
digits remainingDigits # [smallestDigit]
end
fun sum(ints) =
if null ints then 0
else
(hd ints) + sum(tl ints)
fun digitalRoot(i:int) =
let
val results = sum(digits i)
in
results
end
My code only partially works. It gets 18 but I am having trouble with also getting the sum of 18.

Related

find the minimum lucky number that has the sum of digits equal to N

The lucky numbers are the positive integers whose decimal representations contain only the digits 4 or 7 .enter code here`
For example, numbers 47 , 474 , 4 are lucky and 3 , 13 , 567 are not
if there is no such no then output should -1.
input is sum of digits.
i have written this code:
int main(){
long long int s,no=0,minimum=999999999999999999999;
cin>>s;
for(int i=0; i<=s; i++){
for(int j=0; j<=s; j++){
if(i*4+j*7==s){no=0;
for(int k=0; k<i; k++){
no=no*10+4;
}
for(int l=0; l<j; l++){
no=no*10+7;
}if(no<minimum){
minimum=no;}
}
}
}if(minimum==999999999999999999999){cout<<-1;}
else {cout<<minimum;}
}
it is working fine smaller sum values but input is large then no formed is large due to which i am not able to compare them, the constraints for sum is 1<=n<=10^6
This answer shows a process, one of refinement to develop an efficient solution. The most efficient answer can be found in the paragraphs at the bottom, starting with the text "Of course, you can be even more clever ...".
I've left the entire process in so you can understand the sort of thinking that goes into algorithm development. So, let's begin.
First, I wouldn't, in this case, try to compare large numbers, it's totally unnecessary and limits the sort of ranges you want to handle. Instead, you simply have some number of fours and some number of sevens, which you can easily turn into a sum with:
sum = numFours * 4 + numSevens * 7
In addition, realising that the smallest number is, first and foremost, the one with the least number of digits, you want the absolute minimum number of fours and maximum number of sevens. So start with no fours and as many sevens as needed until you're at or just beyond the required sum.
Then, as long as you're not at the sum, perform the following mutually exclusive steps:
If you're over the desired sum, take away a seven if possible. If there are no sevens to take away, you're done, and there's no solution. Log that fact and exit.
Otherwise (i.e., if you're under the sum), add a four.
At this point, you will have a solution (no solution possible means that you would have already performed an exit in the first bullet point above).
Hence you now have a count of the fours and sevens that sum to the desired number, so the lowest number will be the one with all the fours at the left (for example 447 is less than any of {474, 744}). Output that, and you're done.
By doing it this way, the limitation (say, for example, an unsigned 32-bit int) is no longer the number you use (about four billion, so nine digits), instead it is whatever number of fours you can hold in four billion (about a billion digits).
That's an increase of about 11 billion percent, hopefully enough of an improvement for you, well beyond the 106 maximum sum specified.
In reality, you won't get that many fours since any group of seven fours can always be replaced with four sevens, giving a smaller number (a7777b will always be less than a4444444b, where a is zero or more fours and b is zero or more sevens, same counts in both numbers), so the maximum count of fours will always be six.
Here's some pseudo-code (Python code, actually) to show it in action. I've chosen Python, even though you stated C++, for the following reasons:
This is almost certainly an educational question (there's very little call for this sort of program in the real world). That means you're better off doing the heavy lifting of writing the code yourself, to ensure you understand and also to ensure you don't fail for just copying code off the net.
Python is the most awesome pseudo-code language ever. It can easily read like normal English pseudo-code but has the added benefit that a computer can actually run it for testing and validation purposes :-)
The Python code is:
import sys
# Get desired sum from command line, with default.
try:
desiredSum = int(sys.argv[1])
except:
desiredSum = 22
# Init sevens to get at or beyond sum, fours to zero, and the sum.
(numSevens, numFours) = ((desiredSum + 6) // 7, 0)
thisSum = numSevens * 7 + numFours * 4
# Continue until a solution is found.
while thisSum != desiredSum:
if thisSum > desiredSum:
# Too high, remove a seven. If that's not possible, exit.
if numSevens == 0:
print(f"{desiredSum}: no solution")
sys.exit(0)
numSevens -= 1
thisSum -= 7
else:
# Too low, add a four.
numFours += 1
thisSum += 4
# Only get here if solution found, so print lowest
# possible number that matches four/seven count.
print(f"{desiredSum}: answer is {'4' * numFours}{'7' * numSevens}")
And here's a transcript of it in action for a small sample range:
pax:~> for i in {11..20} ; do ./test47.py ${i} ; done
11: answer is 47
12: answer is 444
13: no solution
14: answer is 77
15: answer is 447
16: answer is 4444
17: no solution
18: answer is 477
19: answer is 4447
20: answer is 44444
And here's the (rough) digit count for a desired sum of four billion, well over half a billion digits:
pax:~> export LC_NUMERIC=en_US.UTF8
pax:~> printf "%'.f\n" $(./test47.py 4000000000 | wc -c)
571,428,597
If you really need a C++ solution, see below. I wouldn't advise using this if this is course-work, instead suggesting you convert the algorithm shown above into your own code (for reasons previously mentioned). This is provided just to show the similar approach in C++:
#include <iostream>
int main(int argc, char *argv[]) {
// Get desired sum from command line, defaulting to 22.
int desiredSum = 22;
if (argc >= 2) desiredSum = atoi(argv[1]);
// Init sevens to get at or beyond desired sum, fours to zero,
// and the sum based on that.
int numSevens = (desiredSum + 6) / 7, numFours = 0;
int thisSum = numSevens * 7 + numFours * 4;
// Continue until a solution is found.
while (thisSum != desiredSum) {
if (thisSum > desiredSum) {
// Too high, remove a seven if possible, exit if not.
if (numSevens == 0) {
std::cout << desiredSum << ": no solution\n";
return 0;
}
--numSevens; thisSum -= 7;
} else {
// Too low, add a four.
++numFours; thisSum += 4;
}
}
// Only get here if solution found, so print lowest
// possible number that matches four / seven count.
std::cout << desiredSum << ": answer is ";
while (numFours-- > 0) std::cout << 4;
while (numSevens-- > 0) std::cout << 7;
std::cout << '\n';
}
Of course, you can be even more clever when you realise that the maximum number of fours will be six, and that you can add one to the sum-of-digits by removing one seven and adding two fours.
So simply:
work out the number of sevens required to get at or just below the desired sum;
add a single four if that will still keep you at or below the desired sum;
then adjust by enough actions of "remove one seven and add two fours" until you get to that desired sum (keeping in mind you may already be there). This will be done exactly once for each unit the shortfall in your current sum (how far it is below the desired sum) so, if the shortfall was two, you would remove two sevens and add four fours (- 14 + 16 = 2). That means you can use a simple mathematical formula rather than a loop.
if that formula results in a negative count of sevens, there was no solution, otherwise use the counts as previously mentioned to form the lowest number (fours followed by sevens).
Just Python for this solution, given how easy it is:
import sys
# Get desired number.
desiredNum = int(sys.argv[1])
# Work out seven and four counts as per description in text.
numSevens = int(desiredNum / 7) # Now within six of desired sum.
shortFall = desiredNum - (numSevens * 7)
numFours = int(shortFall / 4) # Now within three of desired sum.
shortFall = shortFall - numFours * 4
# Do enough '+7-4-4's to reach desired sum (none if already there).
numSevens = numSevens - shortFall
numFours = numFours + shortFall * 2
# Done, output solution, if any.
if numSevens < 0:
print(f"{desiredNum}: No solution")
else:
print(f"{desiredNum}: {'4' * numFours}{'7' * numSevens}")
That way, no loop is required at all. It's all mathematical reasoning.
If I understand the question correctly, you are searching for the smallest number x which contains only the numbers 4 and 7 and the sum of its digits N. The smallest number is for sure written as:
4...47...7
and consists of m times 4 and n times 7. So we know that N = n · 4 + m · 7.
Here are a couple of rules that apply:
(n + m) · 7 ≥ N :: This is evident, just replace all 4's by 7's.
(n + m) · 4 ≤ N :: This is evident, just replace all 7's by 4's.
(n + m) · 7 − N = m · (7 − 4) :: in other words (m+n) · 7 − N needs to be divisible by 7 − 4
So with these two conditions, we can now write the pseudo-code very quickly:
# always assume integer division
j = N/7 # j resembles n+m (total digits)
if (N*7 < N) j++ # ensure rule 1
while ( (j*4 <= N) AND ((j*7 - N)%(7-4) != 0) ) j++ # ensure rule 2 and rule 3
m = (j*7 - N)/(7-4) # integer division
n = j-m
if (m>=0 AND n>=0 AND N==m*4 + n*7) result found
Here is a quick bash-awk implementation:
$ for N in {1..30}; do
awk -v N=$N '
BEGIN{ j=int(N/7) + (N%7>0);
while( j*4<=N && (j*7-N)%3) j++;
m=int((j*7-N)/3); n=j-m;
s="no solution";
if (m>=0 && n>=0 && m*4+n*7==N) {
s=""; for(i=1;i<=j;++i) s=s sprintf("%d",(i<=m?4:7))
}
print N,s
}'
done
1 no solution
2 no solution
3 no solution
4 4
5 no solution
6 no solution
7 7
8 44
9 no solution
10 no solution
11 47
12 444
13 no solution
14 77
15 447
16 4444
17 no solution
18 477
19 4447
20 44444
21 777
22 4477
23 44447
24 444444
25 4777
26 44477
27 444447
28 7777
29 44777
30 444477
The constraints for sum are 1 ≤ n ≤ 106
It means that you might have to find and print numbers with more than 105 digits (106 / 7 ≅ 142,857). You can't store those in a fixed-sized integral type like long long, it's better to directly generate them as std::strings composed by only 4 and 7 characters.
Some mathematical properties may help in finding a suitable algorithm.
We know that n = i * 4 + j * 7.
Of all the possible numbers generated by each combination of i digits four and j digits seven, the minimum is the one with all the fours at left of all the sevens. E.g. 44777 < 47477 < 47747 < ... < 77744.
The minimal lucky number has at max six 4 digits, because, even if the sum of their digits is equal, 4444444 > 7777.
Now, let's introduce s = n / 7 (integer division) and r = n % 7 (the remainder).
If n is divisible by 7 (or when r == 0), the lucky number is composed only by exactly s digits (all 7).
If the remainder is not zero, we need to introduce some 4. Note that
If r == 4, we can just put a single 4 at the left of s sevens
Every time we substitute (if we can) a single 7 with two 4s, the sum of the digits increases by 1.
We can calculate exactly how many 4 digits we need (6 at max) without a loop.
This is enough to write an algorithm.
#include <string>
struct lucky_t
{
long fours, sevens;
};
// Find the minimum lucky number (composed by only 4 and 7 digits)
// that has the sum of digits equal to n.
// Returns it as a string, if exists, otherwise return "-1".
std::string minimum_lucky(long n)
{
auto const digits = [multiples = n / 7L, remainder = n % 7L] {
return remainder > 3
? lucky_t{remainder * 2 - 7, multiples - remainder + 4}
: lucky_t{remainder * 2, multiples - remainder};
} ();
if ( digits.fours < 0 || digits.sevens < 0 )
{
return "-1";
}
else
{
std::string result(digits.fours, '4');
result.append(digits.sevens, '7');
return result;
}
}
Tested here.

Cross sum calculation, Can anyone explain the code please?

i'm going to learn C++ at the very beginning and struggling with some challenges from university.
The task was to calculate the cross sum and to use modulo and divided operators only.
I have the solution below, but do not understand the mechanism..
Maybe anyone could provide some advice, or help to understand, whats going on.
I tried to figure out how the modulo operator works, and go through the code step by step, but still dont understand why theres need of the while statement.
#include <iostream>
using namespace std;
int main()
{
int input;
int crossSum = 0;
cout << "Number please: " << endl;
cin >> input;
while (input != 0)
{
crossSum = crossSum + input % 10;
input = input / 10;
}
cout << crossSum << endl;
system ("pause");
return 0;
}
Lets say my input number is 27. cross sum is 9
frist step: crossSum = crossSum + (input'27' % 10 ) // 0 + (modulo10 of 27 = 7) = 7
next step: input = input '27' / 10 // (27 / 10) = 2.7; Integer=2 ?
how to bring them together, and what does the while loop do? Thanks for help.
Just in case you're not sure:
The modulo operator, or %, divides the number to its left by the number to its right (its operands), and gives the remainder. As an example, 49 % 5 = 4.
Anyway,
The while loop takes a conditional statement, and will do the code in the following brackets over and over until that statement becomes false. In your code, while the input is not equal to zero, do some stuff.
To bring all of this together, every loop, you modulo your input by 10 - this will always return the last digit of a given Base-10 number. You add this onto a running sum (crossSum), and then divide the number by 10, basically moving the digits over by one space. The while loop makes sure that you do this until the number is done - for example, if the input is 104323959134, it has to loop 12 times until it's got all of the digits.
It seems that you are adding the digits present in the input number. Let's go through it with the help of an example, let input = 154.
Iteration1
crossSum= 0 + 154%10 = 4
Input = 154/10= 15
Iteration2
crossSum = 4 + 15%10 = 9
Input = 15/10 = 1
Iteration3
crossSum = 9 + 1%10 = 10
Input = 1/10 = 0
Now the while loop will not be executed since input = 0. Keep a habit of dry running through your code.
#include <iostream>
using namespace std;
int main()
{
int input;
int crossSum = 0;
cout << "Number please: " << endl;
cin >> input;
while (input != 0) // while your input is not 0
{
// means that when you have 123 and want to have the crosssum
// you first add 3 then 2 then 1
// mod 10 just gives you the most right digit
// example: 123 % 10 => 3
// 541 % 10 => 1 etc.
// crosssum means: crosssum(123) = 1 + 2 + 3
// so you need a mechanism to extract each digit
crossSum = crossSum + input % 10; // you add the LAST digit to your crosssum
// to make the number smaller (or move all digits one to the right)
// you divide it by 10 at some point the number will be 0 and the iteration
// will stop then.
input = input / 10;
}
cout << crossSum << endl;
system ("pause");
return 0;
}
but still dont understand why theres need of the while statement
Actually, there isn't need (in literal sense) for, number of digits being representable is limited.
Lets consider signed char instead of int: maximum number gets 127 then (8-bit char provided). So you could do:
crossSum = number % 10 + number / 10 % 10 + number / 100;
Same for int, but as that number is larger, you'd need 10 summands (32-bit int provided)... And: You'd always calculate the 10 summands, even for number 1, where actually all nine upper summands are equal to 0 anyway.
The while loop simplifies the matter: As long as there are yet digits left, the number is unequal to 0, so you continue, and as soon as no digits are left (number == 0), you stop iteration:
123 -> 12 -> 1 -> 0 // iteration stops, even if data type is able
^ ^ ^ // to store more digits
Marked digits form the summands for the cross sum.
Be aware that integer division always drops the decimal places, wheras modulo operation delivers the remainder, just as in your very first math lessons in school:
7 / 3 = 2, remainder 1
So % 10 will give you exactly the last (base 10) digit (the least significant one), and / 10 will drop this digit afterwards, to go on with next digit in next iteration.
You even could calculate the cross sum according to different bases (e. g. 16; base 2 would give you the number of 1-bits in binary representation).
Loop is used when we want to repeat some statements until a condition is true.
In your program, the following statements are repeated till the input becomes 0.
Retrieve the last digit of the input. (int digit = input % 10;)
Add the above retrieved digit to crosssum. (crosssum = crosssum + digit;)
Remove the last digit from the input. (input = input / 10;)
The above statements are repeated till the input becomes zero by repeatedly dividing it by 10. And all the digits in input are added to crosssum.
Hence, the variable crosssum is the sum of the digits of the variable input.

code debugging: 'take a list of ints between 0-9, return largest number divisible by 3'

I'm trying to understand what is wrong with my current solution.
The problem is as follows:
using python 2.7.6"
You have L, a list containing some digits (0 to 9). Write a function answer(L) which finds the largest number that can be made from some or all of these digits and is divisible by 3. if it is not possible to make such a number, return 0 as the answer. L will contain anywhere from 1 to 9 digits. The same digit may appear multiple times in the list, but each element in the list may only be used once.
input: (int list) l = [3, 1, 4, 1]
output: (int) 4311
input (int list) l = [3 ,1 ,4 ,1 ,5, 9]
output: (int) = 94311
This is my code to tackle the problem:
import itertools
def answer(l):
'#remove the zeros to speed combinatorial analysis:'
zero_count = l.count(0)
for i in range(l.count(0)):
l.pop(l.index(0))
' # to check if a number is divisible by three, check if the sum '
' # of the individual integers that make up the number is divisible '
' # by three. (e.g. 431: 4+3+1 = 8, 8 % 3 != 0, thus 431 % 3 != 0)'
b = len(l)
while b > 0:
combo = itertools.combinations(l, b)
for thing in combo:
'# if number is divisible by 3, reverse sort it and tack on zeros left behind'
if sum(thing) % 3 == 0:
thing = sorted(thing, reverse = True)
max_div_3 = ''
for digit in thing:
max_div_3 += str(digit)
max_div_3 += '0'* zero_count
return int(max_div_3)
b -= 1
return int(0)
I have tested this assignment many times in my own sandbox and it always works.
However when I have submitted it against my instructor, I end up always failing 1 case.. with no explanation of why. I cannot interrogate the instructor's tests, they are blindly pitched against the code.
Does anyone have an idea of a condition under which my code fails to either return the largest integer divisible by 3 or, if none exists, 0?
The list always has at least one number in it.
It turns out that the problem was with the order of itertools.combinations(l, b)
and sorted(thing, reverse = True). The original code was finding the first match of n%3 == 0 but not necessarily the largest match. Performing sort BEFORE itertools.combinations allowed itertools to find the largest n%3 == 0.

Count the number of number x that has digit sum equal the digit sum of x*m

I was trying to solve the following problem but I am stuck. I think it is an dynamic programming problem.
Could you please give some ideas?
Problem:
Given a positive number n (n<=18) and a positive number m (m<=100).
Call S(x) is sum of digits of x.
For example S(123)=6
Count the number of integer number x that has n digits and S(x)=S(x*m)
Example:
n= 1, m= 2 result= 2
n= 18, m=1 result = 1000000000000000000
Thanks in advance.
First, we need to come up with a recursive formula:
Starting from the least significant digit (LSD) to the most significant digit (MSD), we have a valid solution if after we compute the MSD, we have S(x) = S(x*m)
To verify whether a number is a valid solution, we need to know three things:
What is the current sum of digit S(x)
What is the current sum of digit S(x*m)
What is the current digit.
So, to answer for the first and last, it is easy, we just need to maintain two parameters sumand digit. To compute the second, we need to maintain two additional parameters, sumOfProduct and lastRemaining.
sumOfProduct is the current S(x*m)
lastRemaining is the result of (m * current digit value + lastRemaining) / 10
For example, we have x = 123 and m = 23
First digit = 3
sum = 3
digit = 0
sumOfProduct += (lastRemaining + 3*m) % 10 = 9
lastRemaining = (m*3 + 0)/10 = 6
Second digit = 2
sum = 5
digit = 1
sumOfProduct += (lastRemaining + 2*m) % 10 = 11
lastRemaining = (m*2 + lastRemaining)/10 = 5
Last digit = 1
sum = 6
digit = 2
sumOfProduct += (lastRemaining + m) % 10 = 19
lastRemaining = (m + lastRemaining)/10 = 2
As this is the last digit, sumOfProduct += S(lastRemaining) = 21.
So, x = 123 and m = 23 is not a valid number. Check x*m = 2829 -> S(x*m) = S(2829) = 21.
So, we can have a recursive formula with state (digit, sum, sumOfProdut, lastRemaining).
Thus, our dynamic programming state is dp[18][18*9 + 1][18*9 + 1][200] (as m <= 100, so lastRemaining not larger than 200).
Now the dpstate is over 300 MB, but if we use an iterative approach, it will become smaller, using about 30MB
This problem can be calculated directly.
From those documents: 1, 2, and 3 (thanks to #LouisRicci for finding them), we can state:
The Repeating Cycle of Sum of Digits of Multiples starts repeating at the last digit but one from the base-number (9 for base-10)
S(x) can be defined as: let a equal x mod 9, if a is zero, take 9 as result, else take a. You can play it in the ES6 snippet below:
IN.oninput= (_=> OUT.value= (IN.value % 9) || 9);
IN.oninput();
Input x:<br>
<input id=IN value=123><br>
S(x):<br>
<input id=OUT disabled>
Multiplication rule: S(x * y) = S(S(x) * S(y)).
S(x) and S(x*m) will always be true for x=0, this way there is no zero result.
With the above statements in mind, we should calc the Repeating Cycle of Sum of Digits of Multiples for S(m):
int m = 88;
int Sm = S(m); // 7
int true_n_times_in_nine = 0;
for (int i=1; i<=9; i++) {
true_n_times_in_nine += i == S(i * Sm);
}
The answer then:
result = ((pow(10, n) / 9) * true_n_times_in_nine);
Plus one because of case zero:
result++;
Here is an ES6 solution:
S= x=> (x % 9) || 9;
TrueIn9= (m, Sm=S(m))=> [1,2,3,4,5,6,7,8,9].filter(i=> i==S(i*Sm)).length;
F= (n,m)=> ~~(eval('1e'+n)/9) * TrueIn9(m) + 1;
N.oninput=
M.oninput=
f=(_=> OUT.value= F(N.value | 0, M.value | 0));
f();
Input n: (number of digits)<br>
<input id=N value=1><br>
Input m: (multiplicative number)<br>
<input id=M value=2><br>
F(n,m):<br>
<input id=OUT disabled><br>

Python returning letter in product *possible project euler#8 spoiler*

So I was doing question 8 on project euler (https://projecteuler.net/problem=8),
and my code was:
def prodcheck (n, count):
digs = []
a = str (n)
for dig in a:
digs.append (int (dig))
n = 0
prod = 1
prodset = []
while n < len (digs):
prod = 1
for num in digs [n: n + count + 1]:
prod *= num
prodset.append (prod)
n += 1
return max(prodset)
and after copying in the huge block number line by line, I got a weird number with a letter as a product(specifically 70573265280L, should have been all numbers), can anyone tell me what went wrong?
letter 'L' at the end of int means long. You should be able to use it normally in other equations as any other number because Python fully supports mixed arithmetic. You can also trim trailing L cause its for informational purpose. So in this case the answer is 70573265280.
For more information about numeric types please visit python documentation page.