Definitions
In mathematics, additive primes are prime numbers for which the sum of their decimal digits are also primes.



Task
Write a program to determine (and show here) all additive primes less than 500.

Optionally, show the number of additive primes.



Also see

   the OEIS entry:   A046704 additive primes.
   the prime-numbers entry:   additive primes.
   the geeks for geeks entry: additive prime number.
   the prime-numbers fandom: additive primes.


/* FIND ADDITIVE PRIMES - PRIMES WHOSE DIGIT SUM IS ALSO PRIME */
additive_primes_100H: procedure options                                         (main);
 
/* PROGRAM-SPECIFIC %REPLACE STATEMENTS MUST APPEAR BEFORE THE %INCLUDE AS */
/* E.G. THE CP/M PL/I COMPILER DOESN'T LIKE THEM TO FOLLOW PROCEDURES      */
   /* PL/I                                                                      */
      %replace dclsieve by         500;
   /* PL/M */                                                                   /*
      DECLARE  DCLSIEVE LITERALLY '501';
   /* */
 
/* PL/I DEFINITIONS                                                             */
%include 'pg.inc';
/* PL/M DEFINITIONS: CP/M BDOS SYSTEM CALL AND CONSOLE I/O ROUTINES, ETC. */    /*
   DECLARE BINARY LITERALLY 'ADDRESS', CHARACTER LITERALLY 'BYTE';
   DECLARE FIXED  LITERALLY ' ',       BIT       LITERALLY 'BYTE';
   DECLARE STATIC LITERALLY ' ',       RETURNS   LITERALLY ' ';
   DECLARE FALSE  LITERALLY '0',       TRUE LITERALLY '1';
   DECLARE HBOUND LITERALLY 'LAST',    SADDR  LITERALLY '.';
   BDOSF: PROCEDURE( FN, ARG )BYTE;
                               DECLARE FN BYTE, ARG ADDRESS; GOTO 5;   END; 
   BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5;   END;
   PRCHAR:   PROCEDURE( C );   DECLARE C BYTE;      CALL BDOS( 2, C ); END;
   PRSTRING: PROCEDURE( S );   DECLARE S ADDRESS;   CALL BDOS( 9, S ); END;
   PRNL:     PROCEDURE;        CALL PRCHAR( 0DH ); CALL PRCHAR( 0AH ); END;
   PRNUMBER: PROCEDURE( N );
      DECLARE N ADDRESS;
      DECLARE V ADDRESS, N$STR( 6 ) BYTE, W BYTE;
      N$STR( W := LAST( N$STR ) ) = '$';
      N$STR( W := W - 1 ) = '0' + ( ( V := N ) MOD 10 );
      DO WHILE( ( V := V / 10 ) > 0 );
         N$STR( W := W - 1 ) = '0' + ( V MOD 10 );
      END; 
      CALL BDOS( 9, .N$STR( W ) );
   END PRNUMBER;
   MODF:     PROCEDURE( A, B )ADDRESS;
      DECLARE ( A, B ) ADDRESS;
      RETURN A MOD B;
   END MODF;
/* END LANGUAGE DEFINITIONS */
 
   /* TASK */
 
   /* PRIME ELEMENTS ARE 0, 1, ... 500 IN PL/M AND 1, 2, ... 500 IN PL/I */
   /* ELEMENT 0 IN PL/M IS IS UNUSED */
   DECLARE PRIME( DCLSIEVE ) BIT;
   DECLARE ( MAXPRIME, MAXROOT, ACOUNT, I, J, DSUM, V ) FIXED BINARY;
   /* SIEVE THE PRIMES UP TO MAX PRIME */
   PRIME( 1 ) = FALSE; PRIME( 2 ) = TRUE;
   MAXPRIME = HBOUND( PRIME                                                     , 1
                    );
   MAXROOT  = 1; /* FIND THE ROOT OF MAXPRIME TO AVOID 16-BIT OVERFLOW */
   DO WHILE( MAXROOT * MAXROOT < MAXPRIME ); MAXROOT = MAXROOT + 1; END;
   DO I = 3 TO MAXPRIME BY 2; PRIME( I ) = TRUE;  END;
   DO I = 4 TO MAXPRIME BY 2; PRIME( I ) = FALSE; END;
   DO I = 3 TO MAXROOT BY 2;
      IF PRIME( I ) THEN DO;
         DO J = I * I TO MAXPRIME BY I; PRIME( J ) = FALSE; END;
      END;
   END;
   /* FIND THE PRIMES THAT ARE ADDITIVE PRIMES */
   ACOUNT = 0;
   DO I = 1 TO MAXPRIME;
      IF PRIME( I ) THEN DO;
         V    = I;
         DSUM = 0;
         DO WHILE( V > 0 );
            DSUM = DSUM + MODF( V, 10 );
            V    = V / 10;
         END;
         IF PRIME( DSUM ) THEN DO;
            CALL PRCHAR( ' ' );
            IF I <  10 THEN CALL PRCHAR( ' ' );
            IF I < 100 THEN CALL PRCHAR( ' ' );
            CALL PRNUMBER( I );
            ACOUNT = ACOUNT + 1;
            IF MODF( ACOUNT, 12 ) = 0 THEN CALL PRNL;
         END;
      END;
   END;
   CALL PRNL;
   CALL PRSTRING( SADDR( 'FOUND $' ) );
   CALL PRNUMBER( ACOUNT );
   CALL PRSTRING( SADDR( ' ADDITIVE PRIMES BELOW $' ) );
   CALL PRNUMBER( MAXPRIME );
   CALL PRNL;
 
EOF: end additive_primes_100H;