How to resolve the algorithm Four is magic step by step in the Fortran programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Four is magic step by step in the Fortran programming language

Table of Contents

Problem Statement

Write a subroutine, function, whatever it may be called in your language, that takes an integer number and returns an English text sequence starting with the English cardinal representation of that integer, the word 'is' and then the English cardinal representation of the count of characters that made up the first word, followed by a comma. Continue the sequence by using the previous count word as the first word of the next phrase, append 'is' and the cardinal count of the letters in that word. Continue until you reach four. Since four has four characters, finish by adding the words 'four is magic' and a period. All integers will eventually wind up at four. For instance, suppose your are given the integer 3. Convert 3 to Three, add is , then the cardinal character count of three, or five, with a comma to separate if from the next phrase. Continue the sequence five is four, (five has four letters), and finally, four is magic. For reference, here are outputs for 0 through 9.

You can choose to use a library, (module, external routine, whatever) to do the cardinal conversions as long as the code is easily and freely available to the public.
If you roll your own, make the routine accept at minimum any integer from 0 up to 999999. If you use a pre-made library, support at least up to unsigned 64 bit integers. (or the largest integer supported in your language if it is less.) Four is magic is a popular code-golf task. This is not code golf. Write legible, idiomatic and well formatted code.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Four is magic step by step in the Fortran programming language

Source code in the fortran programming language

MODULE FOUR_IS_MAGIC
    IMPLICIT NONE
    CHARACTER(8), DIMENSION(20) :: SMALL_NUMS
    CHARACTER(7), DIMENSION(8) :: TENS
    CHARACTER(7) :: HUNDRED
    CHARACTER(8) :: THOUSAND
    CHARACTER(8) :: MILLION
    CHARACTER(8) :: BILLION
    CHARACTER(9) :: TRILLION
    CHARACTER(11) :: QUADRILLION
    CHARACTER(11) :: QUINTILLION
    CHARACTER(1) :: SEPARATOR
    CHARACTER(1) :: SPACE


    CONTAINS

    SUBROUTINE INIT_ARRAYS

        SMALL_NUMS(1) = "zero"
        SMALL_NUMS(2) = "one"
        SMALL_NUMS(3) = "two"
        SMALL_NUMS(4) = "three"
        SMALL_NUMS(5) = "four"
        SMALL_NUMS(6) = "five"
        SMALL_NUMS(7) = "six"
        SMALL_NUMS(8) = "seven"
        SMALL_NUMS(9) = "eight"
        SMALL_NUMS(10) = "nine"
        SMALL_NUMS(11) = "ten"
        SMALL_NUMS(12) = "eleven"
        SMALL_NUMS(13) = "twelve"
        SMALL_NUMS(14) = "thirteen"
        SMALL_NUMS(15) = "fourteen"
        SMALL_NUMS(16) = "fifteen"
        SMALL_NUMS(17) = "sixteen"
        SMALL_NUMS(18) = "seventeen"
        SMALL_NUMS(19) = "eighteen"
        SMALL_NUMS(20) = "nineteen"

        TENS(1) = "twenty"
        TENS(2) = "thirty"
        TENS(3) = "forty"
        TENS(4) = "fifty"
        TENS(5) = "sixty"
        TENS(6) = "seventy"
        TENS(7) = "eight"
        TENS(8) = "ninety"

        HUNDRED = "hundred"
        THOUSAND = "thousand"
        MILLION = "million"
        BILLION = "billion"
        TRILLION = "trillion"
        QUADRILLION = "quadrillion"
        QUINTILLION = "quintillion"
        SEPARATOR = "-"
        SPACE = " "

    END SUBROUTINE INIT_ARRAYS

    RECURSIVE FUNCTION STRING_REPRESENTATION(NUM) RESULT(NUM_AS_STR)
        INTEGER(16), INTENT(IN) :: NUM
        CHARACTER(1000) :: NUM_AS_STR
        INTEGER(16), DIMENSION(9) :: COMPONENTS

        CALL INIT_ARRAYS()

        COMPONENTS = GET_COMPONENTS(NUM)

        NUM_AS_STR = TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(9), QUINTILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(8), QUADRILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(7), TRILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(6), BILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(5), MILLION)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(4), THOUSAND)))
        NUM_AS_STR = TRIM(NUM_AS_STR) // SPACE // TRIM(ADJUSTL(GET_SUBSET(COMPONENTS(3), HUNDRED)))


        IF (COMPONENTS(2) .EQ. 1) THEN
            NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // SPACE // TRIM(ADJUSTL(SMALL_NUMS(10 + COMPONENTS(1) + 1)))
        ELSE

            IF (COMPONENTS(1) .GT. 0) THEN
                IF (COMPONENTS(2) .GT. 0) THEN
                    NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // SPACE // TRIM(ADJUSTL(TENS(COMPONENTS(2) - 1))) // SEPARATOR
                    NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // TRIM(ADJUSTL(SMALL_NUMS(COMPONENTS(1) + 1)))
                ELSE
                    NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // SPACE // TRIM(ADJUSTL(SMALL_NUMS(COMPONENTS(1) + 1)))
                ENDIF
            ELSE IF (COMPONENTS(2) .GT. 0) THEN
                NUM_AS_STR = TRIM(ADJUSTL(NUM_AS_STR)) // SPACE // TRIM(ADJUSTL(TENS(COMPONENTS(2) - 1)))
            ENDIF
        ENDIF

    END FUNCTION STRING_REPRESENTATION

    FUNCTION GET_COMPONENTS(NUM)
        INTEGER(16), INTENT(IN) :: NUM
        INTEGER(16), DIMENSION(9) :: GET_COMPONENTS
        INTEGER(16) :: I_UNITS
        INTEGER(16) :: I_TENS
        INTEGER(16) :: I_HUNDREDS
        INTEGER(16) :: I_THOUSANDS
        INTEGER(16) :: I_MILLIONS
        INTEGER(16) :: I_BILLIONS
        INTEGER(16) :: I_TRILLIONS
        INTEGER(16) :: I_QUADRILLIONS
        INTEGER(16) :: I_QUINTILLIONS
        REAL(16) DIVIDE_TEMP

        I_UNITS = NUM

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000000000000000))/1000000000000000000
        I_QUINTILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_QUINTILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_QUINTILLIONS*1000000000000000000
        ENDIF


        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000000000000))/1000000000000000
        I_QUADRILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_QUADRILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_QUADRILLIONS*1000000000000000
        ENDIF

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000000000))/1000000000000
        I_TRILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_TRILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_TRILLIONS*1000000000000
        ENDIF

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000000))/1000000000
        I_BILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_BILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_BILLIONS*1000000000
        ENDIF

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000000))/1000000
        
        I_MILLIONS = FLOOR(DIVIDE_TEMP)

        IF (I_MILLIONS .NE. 0) THEN
           I_UNITS = I_UNITS - I_MILLIONS*1000000
        ENDIF

        DIVIDE_TEMP = (I_UNITS - MOD(I_UNITS, 1000))/1000

        I_THOUSANDS = FLOOR(DIVIDE_TEMP)

        IF (I_THOUSANDS .NE. 0) THEN
           I_UNITS = I_UNITS - I_THOUSANDS*1000
        ENDIF

        DIVIDE_TEMP = I_UNITS/1E2
        I_HUNDREDS = FLOOR(DIVIDE_TEMP)

        IF (I_HUNDREDS .NE. 0) THEN
           I_UNITS = I_UNITS - I_HUNDREDS*1E2
        ENDIF

        DIVIDE_TEMP = I_UNITS/10.
        I_TENS =  FLOOR(DIVIDE_TEMP)

        IF (I_TENS .NE. 0) THEN
           I_UNITS = I_UNITS - I_TENS*10
        ENDIF

        GET_COMPONENTS(1) = I_UNITS
        GET_COMPONENTS(2) = I_TENS
        GET_COMPONENTS(3) = I_HUNDREDS
        GET_COMPONENTS(4) = I_THOUSANDS
        GET_COMPONENTS(5) = I_MILLIONS
        GET_COMPONENTS(6) = I_BILLIONS
        GET_COMPONENTS(7) = I_TRILLIONS
        GET_COMPONENTS(8) = I_QUADRILLIONS
        GET_COMPONENTS(9) = I_QUINTILLIONS

    END FUNCTION GET_COMPONENTS

    FUNCTION GET_SUBSET(COUNTER, LABEL) RESULT(OUT_STR)
        CHARACTER(*), INTENT(IN) :: LABEL
        INTEGER(16), INTENT(IN) :: COUNTER
        CHARACTER(100) :: OUT_STR

        OUT_STR = ""

        IF (COUNTER .GT. 0) THEN
            IF (COUNTER .LT. 20) THEN
                OUT_STR = SPACE // TRIM(ADJUSTL(SMALL_NUMS(COUNTER + 1)))
            ELSE
                OUT_STR = SPACE // TRIM(ADJUSTL(STRING_REPRESENTATION(COUNTER)))
            ENDIF
            OUT_STR = TRIM(ADJUSTL(OUT_STR)) // SPACE // TRIM(LABEL)
        ENDIF

    END FUNCTION GET_SUBSET


    SUBROUTINE FIND_MAGIC(NUM)
        INTEGER(16), INTENT(IN) :: NUM
        INTEGER(16) :: CURRENT, LEN_SIZE
        CHARACTER(1000) :: CURRENT_STR, CURRENT_STR_LEN
        CHARACTER(1000) :: OUT_STR

        CURRENT = NUM
        OUT_STR = ""

        DO WHILE (CURRENT .NE. 4)
            CURRENT_STR = STRING_REPRESENTATION(CURRENT)
            LEN_SIZE = LEN_TRIM(ADJUSTL(CURRENT_STR))
            CURRENT_STR_LEN = STRING_REPRESENTATION(LEN_SIZE)
            OUT_STR = TRIM(ADJUSTL(OUT_STR)) // SPACE // TRIM(ADJUSTL(CURRENT_STR))
            OUT_STR = TRIM(ADJUSTL(OUT_STR)) // " is " // TRIM(ADJUSTL(CURRENT_STR_LEN)) // ","
            CURRENT = LEN_SIZE
        ENDDO

        WRITE(*,*) TRIM(ADJUSTL(OUT_STR)) // SPACE // "four is magic."
    END SUBROUTINE FIND_MAGIC
        

END MODULE FOUR_IS_MAGIC

PROGRAM TEST_NUM_NAME
        USE FOUR_IS_MAGIC
        IMPLICIT NONE

        INTEGER(2) I
        INTEGER(16), DIMENSION(10) :: TEST_NUMS = (/5, 13, 78, 797, 2739, 4000, 7893, 93497412, 2673497412, 10344658531277200972/)
        CHARACTER(1000) :: NUM_NAME

        DO I=1, SIZE(TEST_NUMS)
            CALL FIND_MAGIC(TEST_NUMS(I))
        ENDDO
END PROGRAM


  

You may also check:How to resolve the algorithm Roman numerals/Encode step by step in the AutoHotkey programming language
You may also check:How to resolve the algorithm Elementary cellular automaton/Random number generator step by step in the Scheme programming language
You may also check:How to resolve the algorithm Cramer's rule step by step in the Ruby programming language
You may also check:How to resolve the algorithm Count in factors step by step in the Run BASIC programming language
You may also check:How to resolve the algorithm Execute HQ9+ step by step in the ALGOL 68 programming language