Task

Write a function/procedure/subroutine that is called with an integer value and returns the middle three digits of the integer if possible or a clear indication of an error if this is not possible.

Note: The order of the middle digits should be preserved.

Your function should be tested with the following values; the first line should return valid answers, those of the second line should return clear indications of an error:

123, 12345, 1234567, 987654321, 10001, -10001, -123, -100, 100, -12345
1, 2, -1, -10, 2002, -2002, 0

Show your output on this page.




# we define a UNION MODE so that our middle 3 digits PROC can #
# return either an integer on success or a error message if   #
# the middle 3 digits couldn't be extracted                   #
MODE EINT = UNION( INT # success value #, STRING # error message # );
# PROC to return the middle 3 digits of an integer.           #
# if this is not possible, an error message is returned       #
# instead                                                     #
PROC middle 3 digits = ( INT number ) EINT:
BEGIN
    # convert the absolute value of the number to a string with the  #
    # minumum possible number characters                             #
    STRING digits     = whole( ABS number, 0 );
    INT    len        = UPB digits;
    IF   len < 3
    THEN
        # number has less than 3 digits #
        # return an error message       #
        "number must have at least three digits"
    ELIF ( len MOD 2 ) = 0
    THEN
        # the number has an even number of digits #
        # return an error message                 #
        "number must have an odd number of digits"
    ELSE
        # the number is suitable for extraction of the middle 3 digits #
        INT first digit pos = 1 + ( ( len - 3 ) OVER 2 );
        # the result is the integer value of the three digits          #
        ( ( ( ABS digits[ first digit pos     ] - ABS "0" ) * 100 )
        + ( ( ABS digits[ first digit pos + 1 ] - ABS "0" ) *  10 )
        + ( ( ABS digits[ first digit pos + 2 ] - ABS "0" )       )
        )
    FI
END; # middle 3 digits #
 
main: (
    # test the middle 3 digits PROC #
    []INT test values = (    123,  12345, 1234567, 987654321
                        ,  10001, -10001,    -123,      -100
                        ,    100, -12345
                          # the following values should fail #
                        , 1, 2, -1, -10, 2002, -2002, 0
                        );
    FOR test number FROM LWB test values TO UPB test values
    DO
        CASE middle 3 digits( test values[ test number ] )
        IN
        ( INT     success value ):    # got the middle 3 digits #
            printf( ( $ 11z-d, " : ", 3d $
                    , test values[ test number ]
                    , success value
                    )
                  )
            ,
        ( STRING  error message  ):    # got an error message   #
            printf( ( $ 11z-d, " : ", n( UPB error message )a $
                    , test values[ test number ]
                    , error message
                    )
                  )
        ESAC;
        print( ( newline ) )
    OD
)