Inconsummate numbers in base 10
You are encouraged to solve this task according to the task description, using any language you may know.
A consummate number is a non-negative integer that can be formed by some integer N divided by the the digital sum of N.
- For instance
47 is a consummate number.
846 / (8 + 4 + 6) = 47
On the other hand, there are integers that can not be formed by a ratio of any integer over its digital sum. These numbers are known as inconsummate numbers.
62 is an inconsummate number. There is no integer ratio of an integer to its digital sum that will result in 62.
The base that a number is expressed in will affect whether it is inconsummate or not. This task will be restricted to base 10.
- Task
- Write a routine to find inconsummate numbers in base 10;
- Use that routine to find and display the first fifty inconsummate numbers.
- Stretch
- Use that routine to find and display the one thousandth inconsummate number.
- See also
11l
F digitalsum(num)
‘ Return sum of digits of a number in base 10 ’
R sum(String(num).map(d -> Int(d)))
F generate_inconsummate(max_wanted)
‘ generate the series of inconsummate numbers up to max_wanted ’
V minimum_digitsums = (1..14).map(i -> (Int64(10) ^ i, Int((Int64(10) ^ i - 1) / (9 * i))))
V limit = 20 * Int(min(minimum_digitsums.filter(p -> p[1] > @max_wanted).map(p -> p[0])))
V arr = [1] [+] [0] * (limit - 1)
L(dividend) 1 .< limit
V (quo, rem) = divmod(dividend, digitalsum(dividend))
I rem == 0 & quo < limit
arr[quo] = 1
[Int] r
L(flag) arr
I flag == 0
r.append(L.index)
R r
L(n) generate_inconsummate(100000)
V i = L.index
I i < 50
print(f:‘{n:6}’, end' I (i + 1) % 10 == 0 {"\n"} E ‘’)
E I i == 999
print("\nThousandth inconsummate number: "n)
E I i == 9999
print("\nTen-thousanth inconsummate number: "n)
E I i == 99999
print("\nHundred-thousanth inconsummate number: "n)
L.break
- Output:
62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 Thousandth inconsummate number: 6996 Ten-thousanth inconsummate number: 59853 Hundred-thousanth inconsummate number: 536081
Action!
and based on the Algol 68 sample. As with the PL/M sample, the limit of 16 bit arithmetic means only the basic task can be handled.
;;; find some incomsummate numbers: integers that cannot be expressed as
;;; an integer divided by the sum of its digits
PROC Main()
CARD i, tn, hn, th, tt, sumD, d, n, dRatio, count, maxSum, v, maxNumber
; table of numbers that can be formed by n / digit sum n
DEFINE MAX_C = "999"
BYTE ARRAY consummate(MAX_C+1)
FOR i = 0 TO MAX_C DO
consummate( i ) = 0
OD
; calculate the maximum number we must consider
v = MAX_C / 10;
maxSum = 9;
WHILE v > 0 DO
maxSum ==+ 9
v ==/ 10
OD
maxNumber = maxSum * MAX_C
; construct the digit sums of the numbers up to maxNumber
; and find the consumate numbers, we start the loop from 10 to avoid
; having to deal with 0-9
consummate( 1 ) = 1
tn = 1 hn = 0 th = 0 tt = 0
FOR n = 10 TO maxNumber STEP 10 DO
sumD = tt + th + hn + tn
FOR d = n TO n + 9 DO
IF d MOD sumD = 0 THEN
; d is comsummate
dRatio = d / sumD
IF dRatio <= MAX_C THEN
consummate( dRatio ) = 1
FI
FI
sumD ==+ 1
OD
tn ==+ 1
IF tn > 9 THEN
tn = 0
hn ==+ 1
IF hn > 9 THEN
hn = 0
th ==+ 1
IF th > 9 THEN
th = 0
tt ==+ 1
FI
FI
FI
OD
count = 0
PrintE( "The first 50 inconsummate numbers:" )
i = 0
WHILE i < MAX_C AND count < 50 DO
i ==+ 1
IF consummate( i ) = 0 THEN
count ==+ 1
Put(' )
IF i < 10 THEN Put(' ) FI
IF i < 100 THEN Put(' ) FI
IF i < 1000 THEN Put(' ) FI
PrintC( i )
IF count MOD 10 = 0 THEN PutE() FI
FI
OD
RETURN
- Output:
The first 50 inconsummate numbers: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527
ALGOL 68
BEGIN # find some incomsummate numbers: integers that cannot be expressed as #
# an integer divided by the sum of its digits #
# table of numbers that can be formed by n / digit sum n #
[ 0 : 999 999 ]BOOL consummate;
FOR i FROM LWB consummate TO UPB consummate DO
consummate[ i ] := FALSE
OD;
# calculate the maximum number we must consider to find consummate #
# numbers up to UPB consummate - which is 9 * the number of digits in #
# UPB consummate #
INT max sum := 9;
INT v := UPB consummate;
WHILE ( v OVERAB 10 ) > 0 DO max sum +:= 9 OD;
INT max number = UPB consummate * max sum;
# construct the digit sums of the numbers up to max number #
# and find the consumate numbers, we start the loop from 10 to avoid #
# having to deal with 0-9 #
consummate[ 1 ] := TRUE;
INT tn := 1, hn := 0, th := 0, tt := 0, ht := 0, mi := 0, tm := 0;
FOR n FROM 10 BY 10 TO max number DO
INT sumd := tm + mi + ht + tt + th + hn + tn;
FOR d FROM n TO n + 9 DO
IF d MOD sumd = 0 THEN
# d is comsummate #
IF INT d ratio = d OVER sumd;
d ratio <= UPB consummate
THEN
consummate[ d ratio ] := TRUE
FI
FI;
sumd +:= 1
OD;
IF ( tn +:= 1 ) > 9 THEN
tn := 0;
IF ( hn +:= 1 ) > 9 THEN
hn := 0;
IF ( th +:= 1 ) > 9 THEN
th := 0;
IF ( tt +:= 1 ) > 9 THEN
tt := 0;
IF ( ht +:= 1 ) > 9 THEN
ht := 0;
IF ( mi +:= 1 ) > 9 THEN
mi := 0;
tm +:= 1
FI
FI
FI
FI
FI
FI
OD;
INT count := 0;
print( ( "The first 50 inconsummate numbers:", newline ) );
FOR i TO UPB consummate WHILE count < 100 000 DO
IF NOT consummate[ i ] THEN
IF ( count +:= 1 ) < 51 THEN
print( ( whole( i, -6 ) ) );
IF count MOD 10 = 0 THEN print( ( newline ) ) FI
ELIF count = 1 000 OR count = 10 000 OR count = 100 000 THEN
print( ( "Inconsummate number ", whole( count, -6 )
, ": ", whole( i, -8 ), newline
)
)
FI
FI
OD
END
- Output:
The first 50 inconsummate numbers: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 Inconsummate number 1000: 6996 Inconsummate number 10000: 59853 Inconsummate number 100000: 536081
APL
task←{
gen ← ⍳~(⊢(/⍨)⌊=⊢)∘(⊢÷(+/⍎¨∘⍕)¨)∘⍳∘(⊢×9×≢∘⍕)
incons ← gen 9999
⎕←'The first 50 inconsummate numbers:'
⎕←5 10⍴50↑incons
⎕←'The 1000th inconsummate number:',incons[1000]
}
- Output:
The first 50 inconsummate numbers: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 The 1000th inconsummate number: 6996
AppleScript
on inconsummateNumbers(numberRequired)
set limit to numberRequired * 1000 -- Seems to be enough.
script o
property lst : makeList(limit, true)
end script
repeat with n from 11 to limit -- 1 to 10 obviously can't be inconsummate.
set digitSum to n mod 10
set temp to n div 10
repeat while (temp > 9)
set digitSum to digitSum + temp mod 10
set temp to temp div 10
end repeat
set digitSum to digitSum + temp
tell (n div digitSum) to if (it = n / digitSum) then set o's lst's item it to false
end repeat
set i to 0
repeat with n from 11 to limit
if (o's lst's item n) then
set i to i + 1
set o's lst's item i to n
if (i = numberRequired) then return o's lst's items 1 thru i
end if
end repeat
return {}
end inconsummateNumbers
on makeList(limit, filler)
if (limit < 1) then return {}
script o
property lst : {filler}
end script
set counter to 1
repeat until (counter + counter > limit)
set o's lst to o's lst & o's lst
set counter to counter + counter
end repeat
if (counter < limit) then set o's lst to o's lst & o's lst's items 1 thru (limit - counter)
return o's lst
end makeList
on join(lst, delim)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to delim
set txt to lst as text
set AppleScript's text item delimiters to astid
return txt
end join
on task()
script o
property inconsummates : inconsummateNumbers(100000)
end script
set output to {"First 50 inconsummate numbers:"}
set row to {}
repeat with i from 1 to 50
set row's end to text -5 thru -1 of (" " & o's inconsummates's item i)
if (i mod 10 = 0) then
set output's end to join(row, "")
set row to {}
end if
end repeat
set output's end to linefeed & "1,000th inconsummate number: " & o's inconsummates's item 1000
set output's end to "10,000th inconsummate number: " & o's inconsummates's item 10000
set output's end to "100,000th inconsummate number: " & o's inconsummates's end
return join(output, linefeed)
end task
task()
- Output:
"First 50 inconsummate numbers:
62 63 65 75 84 95 161 173 195 216
261 266 272 276 326 371 372 377 381 383
386 387 395 411 416 422 426 431 432 438
441 443 461 466 471 476 482 483 486 488
491 492 493 494 497 498 516 521 522 527
1,000th inconsummate number: 6996
10,000th inconsummate number: 59853
100,000th inconsummate number: 536081"
BASIC
10 DEFINT A-Z
20 M=999
30 DIM C(M)
40 Z=M*9*(LEN(STR$(M))-1)
50 FOR I=10 TO Z
60 J=I:S=0
70 S=S+J MOD 10:J=J\10:IF J GOTO 70
80 IF I MOD S=0 THEN J=I\S:IF J<=M THEN C(J)=-1
90 NEXT
100 J=0
110 FOR I=10 TO M
120 IF J=50 THEN END
130 IF NOT C(I) THEN J=J+1:PRINT I,
140 NEXT
- Output:
62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527
BASIC256
m = 999
dim c(m) fill false
z = m * 9 * (length(string(m))-1)
for i = 10 to z
j = i
s = 0
while j <> 0
s += (j % 10)
j /= 10
end while
if i % s = 0 then j = i \ s : if j <= m then c[j] = true
next i
cont = 0
print "The first 50 inconsummate numbers:"
for i = 10 to m
if cont = 50 then end
if not c[i] then cont += 1 : print rjust(string(i), 4);
next i
Chipmunk Basic
110 m = 999
120 dim c(m)
130 z = m*9*(len(str$(m))-1)
140 for i = 10 to z
150 j = i : s = 0
160 s = s+j mod 10 : j = int(j/10) : if j then goto 160
170 if i mod s = 0 then j = int(i/s) : if j <= m then c(j) = -1
180 next i
190 j = 0
200 for i = 10 to m
210 if j = 50 then end
220 if c(i) <> -1 then j = j+1 : print i,
230 next i
GW-BASIC
The Chipmunk Basic solution works without any changes.
QBasic
The BASIC solution works without any changes.
True BASIC
LET m = 999
DIM c(0)
MAT REDIM c(m)
LET z = m * 9 * (LEN(STR$(m))-1)
FOR i = 10 TO z
LET j = i
LET s = 0
DO
LET s = s + REMAINDER(j,10)
LET j = INT(j/10)
LOOP WHILE j <> 0
IF REMAINDER(i,s) = 0 THEN
LET j = INT(i/s)
IF j <= m THEN LET c(j) = -1
END IF
NEXT i
LET cont = 0
PRINT "The first 50 inconsummate numbers:"
FOR i = 10 TO m
IF cont = 50 THEN EXIT FOR
IF c(i) <> -1 THEN
LET cont = cont + 1
PRINT i;
END IF
NEXT i
END
XBasic
PROGRAM "Inconsummate numbers in base 10"
VERSION "0.0000"
DECLARE FUNCTION Entry ()
FUNCTION Entry ()
m = 999
DIM c[m]
x$ = STRING$(m)
z = m * 9 * LEN(x$) - 1
FOR i = 10 TO z
j = i
s = 0
DO WHILE j <> 0
s = s + (j MOD 10)
j = INT(j / 10)
LOOP
IF i MOD s = 0 THEN
j = INT(i / s)
IF j <= m THEN c[j] = $$TRUE
END IF
NEXT i
cont = 0
PRINT "The first 50 inconsummate numbers:"
FOR i = 10 TO m
IF cont = 50 THEN EXIT FOR
IF NOT c[i] THEN INC cont : PRINT FORMAT$("####",i);
NEXT i
END FUNCTION
END PROGRAM
Yabasic
m = 999
dim c(m)
z = m * 9 * (len(str$(m))-1)
for i = 10 to z
j = i
s = 0
while j <> 0
s = s + mod(j, 10)
j = int(j / 10)
wend
if mod(i, s) = 0 then j = int(i / s) : if j <= m then c(j) = true : fi : fi
next i
cont = 0
print "The first 50 inconsummate numbers:"
for i = 10 to m
if cont = 50 end
if not c(i) then cont = cont + 1 : print i using("####"); : fi
next i
print
C++
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
const uint32_t sieve_size = 10'000;
const uint32_t maximum = 9 * std::to_string(sieve_size).length() * sieve_size;
std::vector<bool> is_consummate(sieve_size + 1, false);
uint32_t digital_sum(const uint32_t& number) {
uint32_t result = 0;
const std::string text = std::to_string(number);
for ( const char ch : text ) {
result += ch - (int) '0';
}
return result;
}
void create_is_consummate() {
for ( uint32_t n = 1; n < maximum; ++n ) {
uint32_t sum = digital_sum(n);
if ( n % sum == 0 ) {
uint32_t quotient = n / sum;
if ( quotient <= sieve_size ) {
is_consummate[quotient] = true;
}
}
}
}
int main() {
create_is_consummate();
std::vector<uint32_t> inconsummates;
for ( uint32_t i = 0; i <= sieve_size; ++i ) {
if ( ! is_consummate[i] ) {
inconsummates.emplace_back(i);
}
}
std::cout << "The first 50 inconsummate numbers in base 10:" << std::endl;
for ( uint32_t i = 1; i <= 50; ++i ) {
std::cout << std::setw(3) << inconsummates[i] << ( i % 10 == 0 ? "\n" : " " );
}
std::cout << "\n" << "The 1,000 inconsummate number is " << inconsummates[1'000] << std::endl;
}
- Output:
The first 50 inconsummate numbers in base 10: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 The 1,000 inconsummate number is 6996
Delphi
function IsCosumate(N: integer): boolean;
{Test is number is consumate = V / SumDigits(V) = N}
var I, V: integer;
begin
Result:=True;
for I:=1 to High(integer) do
begin
{Test values for V that are multiples of N}
V:= I * N;
{Satisfy - V / SumDigits(V) = N? then exit}
if V = (N * SumDigits(V)) then exit;
{This value derrive by trial and error}
if V>=29000000 then break;
end;
Result:=False;
end;
procedure InconsummateNumbers(Memo: TMemo);
var S: string;
var N,I: integer;
begin
{Display first 50 inconsummate numbers}
N:=1; S:='';
for I:=1 to 50 do
begin
while IsCosumate(N) do Inc(N);
S:=S+Format('%5D',[N]);
if (I mod 10)=0 then S:=S+CRLF_Char;
Inc(N);
end;
Memo.Lines.Add(S);
{Then display 1,000th, 10,000th and 100,000th}
N:=1;
for I:=1 to 100000 do
begin
while IsCosumate(N) do Inc(N);
if I=1000 then Memo.Lines.Add( Format(' 1,000th = %7.0n',[N+0.0]));
if I=10000 then Memo.Lines.Add( Format(' 10,000th = %7.0n',[N+0.0]));
if I=100000 then Memo.Lines.Add(Format('100,000th = %7.0n',[N+0.0]));
Inc(N);
end;
end;
- Output:
62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 1,000th = 6,996 10,000th = 59,853 100,000th = 536,081 Elapsed Time: 3.564 Sec.
EasyLang
limit = 10000
maxn = 10000 * 9 * 4
#
len consummate[] limit
#
func digsum i .
res = 0
while i > 0
res += i mod 10
i = i div 10
.
return res
.
for d = 1 to maxn
ds = digsum d
if d mod ds = 0
q = d / ds
if q <= limit
consummate[q] = 1
.
.
.
d = 1
repeat
if d > len consummate[]
print "error - increase limit"
break 1
.
if consummate[d] = 0
cnt += 1
if cnt <= 50
write d & " "
.
.
until cnt = 1000
d += 1
.
print ""
print ""
print d
FreeBASIC
Dim As Boolean consummate(0 To 999999)
For j As Integer = Lbound(consummate) To Ubound(consummate)
consummate(j) = False
Next j
consummate(1) = True
Dim As Integer maxSum = 9
Dim As Integer ub = Ubound(consummate)
While ub > 10
maxSum += 9
ub /= 10
Wend
Dim As Integer maxNumber = Ubound(consummate) * maxSum
Dim As Integer tn = 1, hn = 0, th = 0, tt = 0, ht = 0, mi = 0, tm = 0
Dim As Integer sumD, n, d, dRatio
For n = 10 To maxNumber Step 10
sumD = tm + mi + ht + tt + th + hn + tn
For d = n To n + 9
If d Mod sumD = 0 Then ' d is comsummate
dRatio = d / sumD
If dRatio <= Ubound(consummate) Then consummate(dRatio) = True
End If
sumD += 1
Next d
tn += 1
If tn > 9 Then
tn = 0
hn += 1
If hn > 9 Then
hn = 0
th += 1
If th > 9 Then
th = 0
tt += 1
If tt > 9 Then
tt = 0
ht += 1
If ht > 9 Then
ht = 0
mi += 1
If mi > 9 Then
mi = 0
tm += 1
End If
End If
End If
End If
End If
End If
Next n
Dim As Integer i = 0, count = 0
Print "The first 50 inconsummate numbers:"
While i < Ubound(consummate) And count < 100000
i += 1
If Not consummate(i) Then
count += 1
If count < 51 Then
Print Using "######"; i;
If count Mod 10 = 0 Then Print
Elseif count = 1000 Or count = 10000 Or count = 100000 Then
Print Using !"\nInconsummate number ######: ######"; count; i;
End If
End If
Wend
Sleep
- Output:
The first 50 inconsummate numbers: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 Inconsummate number 1000: 6996 Inconsummate number 10000: 59853 Inconsummate number 100000: 536081
J
With:
dsum=: [: +/"(1) 10&#.inv NB. digital sum
incons=: (-. (% dsum))&(1+i.) (90* 10 >.&.^. ]) NB. exclude many digital sum ratios
We get:
5 10$incons 1000
62 63 65 75 84 95 161 173 195 216
261 266 272 276 326 371 372 377 381 383
386 387 395 411 416 422 426 431 432 438
441 443 461 466 471 476 482 483 486 488
491 492 493 494 497 498 516 521 522 527
999 { incons 10000
6996
9999 { incons 100000
59853
99999 { incons 1000000
536081
Java
import java.util.stream.IntStream;
public final class InconsummateNumbersInBase10 {
public static void main(String[] args) {
createIsConsummate();
int[] inconsummates = IntStream.rangeClosed(0, sieveSize).filter( i -> ! isConsummate[i] ).toArray();
System.out.println("The first 50 inconsummate numbers in base 10:");
for ( int i = 1; i <= 50; i++ ) {
System.out.print(String.format("%3d%s", inconsummates[i], ( i % 10 == 0 ? "\n" : " " )));
}
System.out.println();
System.out.println("The 1,000 inconsummate number is " + inconsummates[1_000]);
}
private static void createIsConsummate() {
isConsummate = new boolean[sieveSize + 1];
for ( int n = 1; n < maximum; n++ ) {
int digitalSum = digitalSum(n);
if ( n % digitalSum == 0 ) {
int quotient = n / digitalSum;
if ( quotient <= sieveSize ) {
isConsummate[quotient] = true;
}
}
}
}
private static int digitalSum(int number) {
return String.valueOf(number).chars().map( i -> i - (int) '0' ).sum();
}
private static boolean[] isConsummate;
private static final int sieveSize = 10_000;
private static final int maximum = 9 * String.valueOf(sieveSize).length() * sieveSize;
}
- Output:
The first 50 inconsummate numbers in base 10: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 The 1,000 inconsummate number is 6996
jq
Adapted from Wren
Works with jq, the C implementation of jq
def digitSum:
def add(s): reduce s as $_ (0; .+$_);
add(tostring | explode[] | . - 48);
# Maximum ratio for 6 digit numbers is 100,000
def cons:
reduce range(1; 1000000) as $i ([];
($i | digitSum) as $ds
| ($i/$ds) as $ids
| if $ids|floor == $ids then .[$ids] = true else . end);
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
def task($n; $nth):
cons as $cons
| reduce range(1; $cons|length) as $i ([];
if ($cons[$i]|not) then . + [$i] else . end)
| "First \($n) inconsummate numbers in base 10:",
(.[0:50] | _nwise(10) | map(lpad(3)) | join(" ")),
"\nThe \($nth)th:",
.[$nth - 1];
task(50; 1000)
- Output:
First 50 inconsummate numbers in base 10: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 The 1000th: 6996
Julia
{{trans|Python||
using ResumableFunctions
@resumable function gen_inconsummate(maxwanted)
mindigitsums = map(i -> (10^i, (10^(i-2) * 11 - 1) ÷ (9 * i - 17)), 2:14)
limit = minimum(p[1] for p in mindigitsums if p[2] > maxwanted)
arr = zeros(Int, limit)
arr[1] = 1
for dividend in 1:limit-1
dsum = sum(digits(dividend))
quo, rem = divrem(dividend, dsum)
rem == 0 && quo < limit && (arr[quo] = 1)
end
for j in eachindex(arr)
arr[j] == 0 && @yield(j)
end
end
println("The first 50 inconsummate numbers in base 10:")
for (i, j) in enumerate(gen_inconsummate(100000))
if i <= 50
print(rpad(j, 6), i % 10 == 0 ? "\n" : "")
elseif i == 1000
println("\nThe one-thousandth inconsummate number in base 10 is $j")
elseif i == 10000
println("The ten-thousandth inconsummate number in base 10 is $j")
elseif i == 100000
println("The hundred-thousandth inconsummate number in base 10 is $j")
break
end
end
- Output:
The first 50 inconsummate numbers in base 10: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 The one-thousandth inconsummate number in base 10 is 6996 The ten-thousandth inconsummate number in base 10 is 59853 The hundred-thousandth inconsummate number in base 10 is 536081
Nim
import std/[math, strformat, sugar]
const
D = 4 # Sufficient to find the one thousandth first, as required.
N = 10^D # Size of sieve.
M = 9 * (D + 1) * N # Maximum value for the number to divide.
func digitalSum(n: Natural): int =
## Return the digital sum of "n".
var n = n
while n != 0:
inc result, n mod 10
n = n div 10
# Fill a sieve to find consummate numbers.
var isConsummate: array[1..N, bool]
for n in 1..M:
let ds = n.digitalSum
if n mod ds == 0:
let q = n div ds
if q <= N:
isConsummate[q] = true
# Build list of inconsummate numbers.
let inconsummateNums = collect:
for n, c in isConsummate:
if not c: n
echo "First 50 inconsummate numbers in base 10:"
for i in 0..49:
stdout.write &"{inconsummateNums[i]:3}"
stdout.write if i mod 10 == 9: '\n' else: ' '
echo &"\nOne thousandth is {inconsummateNums[999]}."
- Output:
First 50 inconsummate numbers in base 10: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 One thousandth is 6996.
Pascal
Free Pascal
program Inconsummate;
{$IFDEF FPC}
{$MODE DELPHI}{$OPTIMIZATION ON,ALL}{$CODEALIGN proc=8,loop=1}
{$ENDIF}
uses
sysutils;
const
base = 10;
DgtSumLmt = base*base*base*base*base;
type
tDgtSum = array[0..DgtSumLmt-1] of byte;
var
DgtSUm : tDgtSum;
max: Uint64;
procedure Init(var ds:tDgtSum);
var
i,l,k0,k1: NativeUint;
Begin
For i := 0 to base-1 do
ds[i] := i;
k0 := base;
repeat
k1 := k0-1;
For i := 1 to base-1 do
For l := 0 to k1 do
begin
ds[k0] := ds[l]+i;
inc(k0);
end;
until k0 >= High(ds);
end;
function GetSumOfDecDigits(n:Uint64):NativeUint;
var
r,d: NativeUint;
begin
result := 0;
repeat
r := n DIv DgtSumLmt;
d := n-r* DgtSumLmt;
result +=DgtSUm[d];
n := r;
until r = 0;
end;
function OneTest(n:Nativeint):Boolean;
var
i,d : NativeInt;
begin
result := true;
d := n;
For i := 1 TO 121 DO
begin
IF GetSumOfDecDigits(n)= i then
Begin
if i > max then
max := i;
Exit(false);
end;
n +=d;
end;
end;
var
d,
cnt,lmt: Uint64;
begin
Init(DgtSUm);
cnt := 0;
For d := 1 to 527 do//5375540350 do
begin
if OneTest(d) then
begin
inc(cnt);
write(d:5);
if cnt mod 10 = 0 then writeln;
end;
end;
writeln;
writeln('Count Number(count) Maxfactor needed');
cnt := 0;
max := 0;
lmt := 10;
For d := 1 to 50332353 do // 5260629551 do
begin
if OneTest(d) then
begin
inc(cnt);
if cnt = lmt then
begin
writeln(cnt:10,d:12,max:5);
lmt *=10;
end;
end;
end;
writeln(cnt);
end.
- @TIO.RUN:
62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 Count Number(count) Maxfactor needed 10 216 27 100 936 36 1000 6996 36 10000 59853 54 100000 536081 63 1000000 5073249 69 10000000 50332353 81 10000000 Real time: 23.898 s @Home AMD 5600G 4.4 Ghz: Count Number(count) Maxfactor needed 10 216 27 100 936 36 1000 6996 36 10000 59853 54 100000 536081 63 1000000 5073249 69 10000000 50332353 81 //real 0m6,395s 100000000 517554035 87 1000000000 5260629551 96 1000000000 real 15m54,915s
Perl
use v5.36;
use List::Util <sum max>;
sub table ($c, @V) { my $t = $c * (my $w = 2 + length max @V); ( sprintf( ('%'.$w.'d')x@V, @V) ) =~ s/.{1,$t}\K/\n/gr }
my $upto = 1e6;
my @cons = (0) x $upto;
for my $i (1..$upto) {
my $r = $i / sum split '', $i;
$cons[$r] = 1 if $r eq int $r;
}
my @incons = grep { $cons[$_]==0 } 1..$#cons;
say 'First fifty inconsummate numbers (in base 10):';
say table 10, @incons[0..49];
say "One thousandth: " . $incons[999];
- Output:
First fifty inconsummate numbers (in base 10): 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 One thousandth: 6996
Phix
with javascript_semantics --constant limit = 1_000*250 -- NB: 250 magic'd out of thin air --constant limit = 10_000*269 -- NB: 269 magic'd out of thin air constant limit = 100_000*290 -- NB: 290 magic'd out of thin air sequence consummate = repeat(false,limit), inconsummate = {} function digital_sum(integer i) integer res = 0 while i do res += remainder(i,10) i = floor(i/10) end while return res end function for d=1 to limit do integer ds = digital_sum(d) if rmdr(d,ds)=0 then integer q = floor(d/ds) if q<=limit then consummate[q] = true end if end if end for for d=1 to limit do if not consummate[d] then inconsummate &= d end if end for printf(1,"First 50 inconsummate numbers in base 10:\n%s\n", join_by(inconsummate[1..50],1,10," ",fmt:="%3d")) printf(1,"One thousandth %,d\n", inconsummate[1_000]) printf(1,"Ten thousandth %,d\n", inconsummate[10_000]) printf(1,"100 thousandth %,d\n", inconsummate[100_000])
- Output:
First 50 inconsummate numbers in base 10: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 One thousandth 6,996 Ten thousandth 59,853 100 thousandth 536,081
PL/M
Based on the Algol 68 sample but only finds the first 50 Inconsummate numbers as it would require more than 16 bit arithmetic t0 go much further.
Calculating the digit sums as here appears to be faster than using MOD and division.
... under CP/M (or an emulator)
100H: /* FIND SOME INCOMSUMMATE NUMBERS: INTEGERS THAT CANNOT BE EXPRESSED */
/* AS AN INTEGER DIVIDED BY THE SUM OF ITS DIGITS */
DECLARE FALSE LITERALLY '0', TRUE LITERALLY '0FFH';
/* CP/M SYSTEM CALL AND I/O ROUTINES */
BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5; END;
PR$CHAR: PROCEDURE( C ); DECLARE C BYTE; CALL BDOS( 2, C ); END;
PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END;
PR$NL: PROCEDURE; CALL PR$CHAR( 0DH ); CALL PR$CHAR( 0AH ); END;
PR$NUMBER: PROCEDURE( N ); /* PRINTS A NUMBER IN THE MINIMUN FIELD WIDTH */
DECLARE N ADDRESS;
DECLARE V ADDRESS, N$STR ( 6 )BYTE, W BYTE;
V = N;
W = LAST( N$STR );
N$STR( W ) = '$';
N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
DO WHILE( ( V := V / 10 ) > 0 );
N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
END;
CALL PR$STRING( .N$STR( W ) );
END PR$NUMBER;
/* END SYSTEM CALL AND I/O ROUTINES */
DECLARE MAX$C LITERALLY '999', /* MAXIMUM NUMBER WE WILL TEST */
MAX$C$PLUS$1 LITERALLY '1000'; /* MAX$C + 1 FOR ARRAY BOUNDS */
DECLARE ( I, J, MAX$SUM, V, MAX$NUMBER, COUNT ) ADDRESS;
/* TABLE OF NUMBERS THAT CAN BE FORMED BY N / DIGIT SUM N */
DECLARE CONSUMMATE ( MAX$C$PLUS$1 ) ADDRESS;
DO I = 0 TO LAST( CONSUMMATE ); CONSUMMATE( I ) = FALSE; END;
/* CALCULATE THE MAXIMUM NUMBER WE MUST CONSIDER TO FIND CONSUMMATE */
/* NUMBERS UP TO LAST(CONSUMMATE)- WHICH IS 9 * THE NUMBER OF DIGITS IN */
/* LAST(CONSUMMATE) */
MAX$SUM = 9;
V = LAST( CONSUMMATE );
DO WHILE ( V := V / 10 ) > 0; MAX$SUM = MAX$SUM + 9; END;
MAX$NUMBER = LAST( CONSUMMATE ) * MAX$SUM;
/* CONSTRUCT THE DIGIT SUMS OF THE NUMBERS UP TO MAX$NUMBER */
/* AND FIND THE CONSUMATE NUMBERS, WE START THE LOOP FROM 10 TO AVOID */
/* HAVING TO DEAL WITH 0-9 */
DO;
DECLARE ( D, N, TN, HN, TH, TT, SUMD ) ADDRESS;
CONSUMMATE( 1 ) = TRUE;
TT, TH, HN = 0; TN = 1;
DO N = 10 TO MAX$NUMBER BY 10;
SUMD = TT + TH + HN + TN;
DO D = N TO N + 9;
IF D MOD SUMD = 0 THEN DO;
/* D IS COMSUMMATE */
DECLARE D$RATIO ADDRESS;
IF ( D$RATIO := D / SUMD ) <= LAST( CONSUMMATE ) THEN DO;
CONSUMMATE( D$RATIO ) = TRUE;
END;
END;
SUMD = SUMD + 1;
END;
IF ( TN := TN + 1 ) > 9 THEN DO;
TN = 0;
IF ( HN := HN + 1 ) > 9 THEN DO;
HN = 0;
IF ( TH := TH + 1 ) > 9 THEN DO;
TH = 0;
TT = TT + 1;
END;
END;
END;
END;
END;
COUNT = 0;
CALL PR$STRING( .'THE FIRST 50 INCONSUMMATE NUMBERS:$' );CALL PR$NL;
I = 0;
DO WHILE ( I := I + 1 ) <= LAST( CONSUMMATE ) AND COUNT < 50;
IF NOT CONSUMMATE( I ) THEN DO;
IF I < 10 THEN CALL PR$CHAR( ' ' );
IF I < 100 THEN CALL PR$CHAR( ' ' );
IF I < 1000 THEN CALL PR$CHAR( ' ' );
CALL PR$CHAR( ' ' );
CALL PR$NUMBER( I );
IF ( COUNT := COUNT + 1 ) MOD 10 = 0 THEN CALL PR$NL;
END;
END;
EOF
- Output:
THE FIRST 50 INCONSUMMATE NUMBERS: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527
Python
''' Rosetta code rosettacode.org/wiki/Inconsummate_numbers_in_base_10 '''
def digitalsum(num):
''' Return sum of digits of a number in base 10 '''
return sum(int(d) for d in str(num))
def generate_inconsummate(max_wanted):
''' generate the series of inconsummate numbers up to max_wanted '''
minimum_digitsums = [(10**i, int((10**i - 1) / (9 * i)))
for i in range(1, 15)]
limit = 20 * min(p[0] for p in minimum_digitsums if p[1] > max_wanted)
arr = [1] + [0] * (limit - 1)
for dividend in range(1, limit):
quo, rem = divmod(dividend, digitalsum(dividend))
if rem == 0 and quo < limit:
arr[quo] = 1
for j, flag in enumerate(arr):
if flag == 0:
yield j
for i, n in enumerate(generate_inconsummate(100000)):
if i < 50:
print(f'{n:6}', end='\n' if (i + 1) % 10 == 0 else '')
elif i == 999:
print('\nThousandth inconsummate number:', n)
elif i == 9999:
print('\nTen-thousanth inconsummate number:', n)
elif i == 99999:
print('\nHundred-thousanth inconsummate number:', n)
break
- Output:
62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 Thousandth inconsummate number: 6996 Ten-thousanth inconsummate number: 59853 Hundred-thousanth inconsummate number: 536081
Raku
Not really pleased with this entry. It works, but seems inelegant.
my $upto = 1000;
my @ratios = unique (^∞).race.map({($_ / .comb.sum).narrow})[^($upto²)].grep: Int;
my @incons = (sort keys (1..$upto * 10) (-) @ratios)[^$upto];
put "First fifty inconsummate numbers (in base 10):\n" ~ @incons[^50]».fmt("%3d").batch(10).join: "\n";
put "\nOne thousandth: " ~ @incons[999]
- Output:
First fifty inconsummate numbers (in base 10): 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 One thousandth: 6996
RPL
∑DIGITS
is defined at Sum digits of an integer
« 999 DUP { } + 0 CON 10 ROT DUP XPON 1 + 9 * * FOR n n DUP ∑DIGITS IF DUP2 MOD NOT THEN / IFERR 1 PUT THEN DROP2 END ELSE DROP2 END NEXT { } SWAP 10 WHILE 3 PICK SIZE 50 < REPEAT IF GETI NOT THEN ROT OVER 1 - + ROT ROT END END DROP2 » 'TASK' STO
- Output:
1: { 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 }
Wren
It appears to be more than enough to calculate ratios for all numbers up to 999,999 (which only takes about 0.4 seconds on my machine) to be sure of finding the 1,000th inconsummate number.
In fact it still finds the 1,000th number if you limit the search to the first 249,999 (but not 248,999) numbers which may be where the first magic number of '250' comes from in the Pascal/Phix entries.
import "./math" for Int
import "./fmt" for Fmt
// Maximum ratio for 6 digit numbers is 100,000
var cons = List.filled(100001, false)
for (i in 1..999999) {
var ds = Int.digitSum(i)
var ids = i/ds
if (ids.isInteger) cons[ids] = true
}
var incons = []
for (i in 1...cons.count) {
if (!cons[i]) incons.add(i)
}
System.print("First 50 inconsummate numbers in base 10:")
Fmt.tprint("$3d", incons[0..49], 10)
Fmt.print("\nOne thousandth: $,d", incons[999])
- Output:
First 50 inconsummate numbers in base 10: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 One thousandth: 6,996
Alternatively and more generally:
...though much quicker as I'm using lower figures for the second component of the minDigitSums tuples.
import "./math" for Int, Nums
import "./fmt" for Fmt
var generateInconsummate = Fiber.new { |maxWanted|
var minDigitSums = (2..14).map { |i| [10.pow(i), ((10.pow(i-2) * 11 - 1) / (9 * i - 17)).floor] }
var limit = Nums.min(minDigitSums.where { |p| p[1] > maxWanted }.map { |p| p[0] })
var arr = List.filled(limit, 0)
arr[0] = 1
for (dividend in 1...limit) {
var ds = Int.digitSum(dividend)
var quo = (dividend/ds).floor
var rem = dividend % ds
if (rem == 0 && quo < limit) arr[quo] = 1
}
for (j in 0...arr.count) {
if (arr[j] == 0) Fiber.yield(j)
}
}
var incons = List.filled(50, 0)
System.print("First 50 inconsummate numbers in base 10:")
for (i in 1..100000) {
var j = generateInconsummate.call(100000)
if (i <= 50) {
incons[i-1] = j
if (i == 50) Fmt.tprint("$3d", incons, 10)
} else if (i == 1000) {
Fmt.print("\nOne thousandth $,d", j)
} else if (i == 10000) {
Fmt.print("Ten thousandth $,d", j)
} else if (i == 100000) {
Fmt.print("100 thousandth $,d", j)
}
}
- Output:
First 50 inconsummate numbers in base 10: 62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 One thousandth 6,996 Ten thousandth 59,853 100 thousandth 536,081
XPL0
func DigSum(Num); \Return sum of digits of a number in base 10
int Num, Sum;
[Sum:= 0;
repeat Num:= Num/10;
Sum:= Sum + rem(0);
until Num = 0;
return Sum;
];
func Consum(N); \Return 'true' if N is a consummate number
int N, M, P;
[M:= 1;
repeat P:= M*N;
if P = N*DigSum(P) then return true;
M:= M+1;
until P >= 1000000; \8-)
return false;
];
int C, N;
[C:= 0; N:= 1;
Format(4, 0);
repeat if not Consum(N) then
[C:= C+1;
if C <= 50 then
[RlOut(0, float(N));
if rem(C/10) = 0 then CrLf(0);
];
if C = 1000 then
[Text(0, "One thousandth inconsummate number: ");
IntOut(0, N);
CrLf(0);
];
];
N:= N+1;
until C >= 1000;
]
- Output:
62 63 65 75 84 95 161 173 195 216 261 266 272 276 326 371 372 377 381 383 386 387 395 411 416 422 426 431 432 438 441 443 461 466 471 476 482 483 486 488 491 492 493 494 497 498 516 521 522 527 One thousandth inconsummate number: 6996