Inconsummate numbers in base 10: Difference between revisions
Content added Content deleted
(→{{header|ALGOL 68}}: Simplify - no need for the divisor sum table, find the consummate numbers while finding the sums, handle the stretch goal) |
(Added PL/M) |
||
Line 282: | Line 282: | ||
Real time: 3.342 s CPU share: 99.16 % |
Real time: 3.342 s CPU share: 99.16 % |
||
</pre> |
|||
=={{header|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.<br> |
|||
Calculating the digit sums as here appears to be faster than using MOD and division. |
|||
{{works with|8080 PL/M Compiler}} ... under CP/M (or an emulator) |
|||
<syntaxhighlight lang="plm"> |
|||
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 |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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 |
|||
</pre> |
</pre> |
||