Announcement

Collapse
No announcement yet.

Reverse number algorithm

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #41
    I think the better approach would be to assign each digit to a byte and then do the calculations on the resulting byte string. It's not necessary to expressly reverse the sequence of digits of the number being tested, you only have to cross-add the digits -- the first with the last, the second with the second-to-last etc, and then check the resulting sum to see if it is palindromic, again having to deal with each digit separately.

    Create your random starting number with something like:

    sRndNumberBuff = sRndNumberBuff + chr$(rnd(0 to 9))

    up to however many digits you want

    then right-justify the number in the buffer giving it enough room to grow to whatever length you desire

    sRndNumberBuff = string$(chr$(0), 1000000000) + sRndNumberBuff

    This way requires no * or /, places no practical limit on the number of digits the number can grow to and is easily adaptable to any number base from 2 to 256

    Comment


    • #42
      Originally posted by Mark Bullivant View Post
      I think the better approach would be to assign each digit to a byte and then do the calculations on the resulting byte string. It's not necessary to expressly reverse the sequence of digits of the number being tested, you only have to cross-add the digits -- the first with the last, the second with the second-to-last etc, and then check the resulting sum to see if it is palindromic, again having to deal with each digit separately.
      One word: "carry"

      Please provide a simple demonstration of your method with

      "77899" + "99877" = "177776"
      "177776" + "677771" = "855547"
      "855547" + "745558" = "1601105"
      ...

      Comment


      • #43
        Ok, give me a few moments...

        So, here pbMSDigit points to the most-significant digit of the number and pbLSDigit to the least-significant digit. pbSum points to the last byte of a separate buffer that receives the result.

        Yes, the actual addition takes longer, but how much time is saved by not having to extract each digit with *'s and /'s and then reassemble them in reverse?

        Good question, Mark.

        '
        Code:
        gCARRY = 0
          FOR gDigit = 0 TO pbLSDigit - pbMSDigit
            @pbSum[-gDigit] = @pbMSDigit[gDigit] + @pbLSDigit[-gDigit] + gCARRY
            gCARRY = -(@pbSum[-gDigit] > (%NUMBER_BASE - 1))
            IF ISTRUE gCARRY THEN @pbSum[-gDigit] = @pbSum[-gDigit] - %NUMBER_BASE
          NEXT gDigit
        'And...
          IF ISTRUE gCarry THEN
            @pbSum[-gDigit] = 1
          END IF
          '
        This code may be more convenient for testing my algorithm

        '
        Code:
        #COMPILE EXE
        #DIM ALL
        
        %DIG_BUFF_MAX_SIZE = 1024 * 512
        %NUMBER_BASE = 10
        
        FUNCTION PBMAIN () AS LONG
          DIM sDigBuff(0 TO 1) AS STRING
          LOCAL sKBInput AS STRING
          LOCAL pbMSDigit, pbLSDigit, pbSum AS BYTE PTR
          LOCAL gISAPALINDROME AS LONG
        
          sDigBuff(0) = STRING$(%DIG_BUFF_MAX_SIZE, "0")
          sDigBuff(1) = STRING$(%DIG_BUFF_MAX_SIZE, "0")
        
          pbLSDigit = STRPTR(sDigBuff(0)) + %DIG_BUFF_MAX_SIZE - 1
          pbSum = STRPTR(sDigBuff(1)) + %DIG_BUFF_MAX_SIZE - 1
        
        DO
          INPUT "A number or just ENTER to exit ";sKBInput
        
          IF ISFALSE LEN(sKBInput) THEN EXIT FUNCTION
        
          pbMSDigit = AssignRight(pbLSDigit, STRPTR(sKBInput), LEN(sKBInput))
        
          IF ISFALSE pbMSDigit THEN 'failure to intercept this condition will cause a crash
            PRINT "Invalid digit in number (BASE = " + DEC$(%NUMBER_BASE) + ")"
            ITERATE DO '!
          END IF
        
          pbMSDigit = CrossAddDigits(pbMSDigit, pbLSDigit, pbSum, gISAPALINDROME)
        
          SWAP pbSum, pbLSDigit
        
          PRINT GetDigiStr(pbLSDigit, pbMSDigit);
        
          IF ISTRUE gISAPALINDROME THEN
            PRINT " is a palindrome"
          ELSE
            PRINT " is not a palindrome"
          END IF
        
        LOOP
        
        END FUNCTION
        
        FUNCTION GetDigiStr(BYVAL pbLSDigit AS BYTE PTR, BYVAL pbMSDigit AS BYTE PTR) AS STRING
          'returns the digit sequence as an ascii string
          LOCAL sOut AS STRING
        
          DO WHILE pbMSDigit <= pbLSDigit
            sOut = sOut + CHR$(@pbMSDigit + ASC("0"))
            INCR pbMSDigit
          LOOP
        
          FUNCTION = sOut
        
        END FUNCTION
        
        FUNCTION AssignRight(BYVAL pbDestBuffEnd AS BYTE PTR, BYVAL pbSource AS BYTE PTR, BYVAL gLenSource AS LONG) AS DWORD
          'Coverts ascii digits to unbiased byte values and places them at the high end of the buffer
          LOCAL gDigit AS LONG
        
          FOR gDigit = -gLenSource + 1 TO 0
            IF (@pbSource < ASC("0")) OR (@pbSource >= (ASC("0") + %NUMBER_BASE)) THEN
              EXIT FUNCTION 'Digit out-of-range!
            END IF
            @pbDestBuffEnd[gDigit] = @pbSource - ASC("0")
            INCR pbSource
          NEXT gDigit
        
          FUNCTION = pbDestBuffEnd - gLenSource + 1
        
        END FUNCTION
        
        FUNCTION CrossAddDigits(BYVAL pbMSDigit AS BYTE PTR, BYVAL pbLSDigit AS BYTE PTR, BYVAL pbSum AS BYTE PTR, BYREF gISAPALINDROME AS LONG) AS DWORD
          'Cross adds the deliniated sequence of digits, then tests the resulting sum to see if it is palindromic
          LOCAL gDigit, gCARRY AS LONG
        
          FOR gDigit = 0 TO pbLSDigit - pbMSDigit
            @pbSum[-gDigit] = @pbMSDigit[gDigit] + @pbLSDigit[-gDigit] + gCARRY
            gCARRY = -(@pbSum[-gDigit] > (%NUMBER_BASE - 1))
            IF ISTRUE gCARRY THEN @pbSum[-gDigit] = @pbSum[-gDigit] - %NUMBER_BASE
          NEXT gDigit
        
          IF ISTRUE gCarry THEN
            @pbSum[-gDigit] = 1
            INCR gDigit
          END IF
        
          pbMSDigit = pbSum - gDigit + 1
        
          FUNCTION = pbMSDigit
        
          gISAPALINDROME = -1 'Guilty until proven innocent
        
          DO WHILE (ISTRUE gISAPALINDROME) AND (pbSum >= pbMSDigit)
            gISAPALINDROME = (@pbMSDigit = @pbSum)
            DECR pbSum
            INCR pbMSDigit
          LOOP
        
        END FUNCTION
        '
        Last edited by Mark Bullivant; 10 May 2020, 07:23 AM. Reason: Added stuff

        Comment


        • #44
          I don't know i this is of any use but its a technique to reverse the bit pattern of numbers in the range of 0 to 255 and write the to a 256 byte table in an ASMDATA block. If I have it right it can be used 1 byte at a time on the 4 hex numbers in a DWORD to reverse the bit order of each byte then write them back in reverse order with the intention of inverting the entire DWORD bit pattern. As it works a byte at a time, it can be used on any data size that is multiples of a byte.
          Code:
          ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
          
          '   Build with PBWIN.
          
          '   If you want to see how the table was constructed
          '   uncomment the 2 PBCC lines and build with PBCC
          
              #compile exe "bitrev.exe"
          
          ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
          
          FUNCTION PBmain as LONG
          
              #REGISTER NONE
          
              LOCAL var as BYTE
              LOCAL cnt as BYTE
          
              var = 0
              cnt = 0
          
            ' ----------------------------------------
          
            lbl:
              byt$ = bin$(var,8)
              rev$ = right$("00000000"+format$(val(strreverse$(byt$))),8)
              ivs$ = "&H"+right$("00"+hex$(val("&B"+rev$)),2)
          
              ''' StdOut format$(var)+" = "+byt$+" = "+rev$+" = "+ivs$
          
              ! add cnt, 1
          
              If cnt = 16 Then
                table$ = table$+ivs$+chr$(13,10)+"    db "
                cnt = 0
              Else
                table$ = table$+ivs$+","
              End If
          
              rslt$ = left$("    db "+table$,-5)
          
              ! add var, 1
              ! cmp var, 256
              ! jne lbl
          
            ' ----------------------------------------
          
              outp$ = "  ASMDATA invert_bit_order"+chr$(13,10,13,10)+rslt$+chr$(13,10)+"  END ASMDATA"+chr$(13,10)
          
              Open "table.txt" for output as #1
                Print #1, outp$
              Close #1
          
              x& = shell("notepad table.txt",1)
          
              ''' waitkey$
          
          End FUNCTION
          
          ' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
          The output table is as follows.

          Code:
            ASMDATA invert_bit_order
          
              db &H00,&H80,&H40,&HC0,&H20,&HA0,&H60,&HE0,&H10,&H90,&H50,&HD0,&H30,&HB0,&H70,&HF0
              db &H08,&H88,&H48,&HC8,&H28,&HA8,&H68,&HE8,&H18,&H98,&H58,&HD8,&H38,&HB8,&H78,&HF8
              db &H04,&H84,&H44,&HC4,&H24,&HA4,&H64,&HE4,&H14,&H94,&H54,&HD4,&H34,&HB4,&H74,&HF4
              db &H0C,&H8C,&H4C,&HCC,&H2C,&HAC,&H6C,&HEC,&H1C,&H9C,&H5C,&HDC,&H3C,&HBC,&H7C,&HFC
              db &H02,&H82,&H42,&HC2,&H22,&HA2,&H62,&HE2,&H12,&H92,&H52,&HD2,&H32,&HB2,&H72,&HF2
              db &H0A,&H8A,&H4A,&HCA,&H2A,&HAA,&H6A,&HEA,&H1A,&H9A,&H5A,&HDA,&H3A,&HBA,&H7A,&HFA
              db &H06,&H86,&H46,&HC6,&H26,&HA6,&H66,&HE6,&H16,&H96,&H56,&HD6,&H36,&HB6,&H76,&HF6
              db &H0E,&H8E,&H4E,&HCE,&H2E,&HAE,&H6E,&HEE,&H1E,&H9E,&H5E,&HDE,&H3E,&HBE,&H7E,&HFE
              db &H01,&H81,&H41,&HC1,&H21,&HA1,&H61,&HE1,&H11,&H91,&H51,&HD1,&H31,&HB1,&H71,&HF1
              db &H09,&H89,&H49,&HC9,&H29,&HA9,&H69,&HE9,&H19,&H99,&H59,&HD9,&H39,&HB9,&H79,&HF9
              db &H05,&H85,&H45,&HC5,&H25,&HA5,&H65,&HE5,&H15,&H95,&H55,&HD5,&H35,&HB5,&H75,&HF5
              db &H0D,&H8D,&H4D,&HCD,&H2D,&HAD,&H6D,&HED,&H1D,&H9D,&H5D,&HDD,&H3D,&HBD,&H7D,&HFD
              db &H03,&H83,&H43,&HC3,&H23,&HA3,&H63,&HE3,&H13,&H93,&H53,&HD3,&H33,&HB3,&H73,&HF3
              db &H0B,&H8B,&H4B,&HCB,&H2B,&HAB,&H6B,&HEB,&H1B,&H9B,&H5B,&HDB,&H3B,&HBB,&H7B,&HFB
              db &H07,&H87,&H47,&HC7,&H27,&HA7,&H67,&HE7,&H17,&H97,&H57,&HD7,&H37,&HB7,&H77,&HF7
              db &H0F,&H8F,&H4F,&HCF,&H2F,&HAF,&H6F,&HEF,&H1F,&H9F,&H5F,&HDF,&H3F,&HBF,&H7F,&HFF
          
            END ASMDATA
          It then can be used with a simple XCHG algo to reverse bit patterns.
          hutch at movsd dot com
          The MASM Forum

          www.masm32.com

          Comment


          • #45
            Mark

            Excellent approach, however, this still does not solve the problem.
            That is, with this code can you find the first palindrome number in the following series?

            196 + 691 = 887
            788 + 887 = 1675
            5761 + 1675 = 7436
            6347 + 7436 = 13783
            38731 + 13783 = 52514
            41525 + 52514 = 94039
            93049 + 94039 = 187088
            880781 + 187088 = 1067869
            9687601 + 1067869 = 10755470
            7455701 + 1075547 = 8531248
            8421358 + 8531248 = 16952606
            60625961 + 16952606 = 77578567
            76587577 + 77578567 = 154166144
            441661451 + 154166144 = 595827595
            595728595 + 595827595 = 1191556190
            ...

            Comment


            • #46
              Originally posted by Ribeiro Alvo View Post
              Mark

              Excellent approach, however, this still does not solve the problem.
              That is, with this code can you find the first palindrome number in the following series?

              196 + 691 = 887
              788 + 887 = 1675
              5761 + 1675 = 7436
              6347 + 7436 = 13783
              38731 + 13783 = 52514
              41525 + 52514 = 94039
              93049 + 94039 = 187088
              880781 + 187088 = 1067869
              9687601 + 1067869 = 10755470
              7455701 + 1075547 = 8531248
              8421358 + 8531248 = 16952606
              60625961 + 16952606 = 77578567
              76587577 + 77578567 = 154166144
              441661451 + 154166144 = 595827595
              595728595 + 595827595 = 1191556190
              ...
              Since it's already been tested to over a billion iterations generating a six million digit number, that's doubtful. :0

              Comment


              • #47
                Ribeiro, this program will do the search starting with 196 or any other number you enter, but as Stuart pointed out, better programs than this one have worked on the problem and failed to reach a palindrome after billions of iterations.

                https://en.wikipedia.org/wiki/Lychrel_number

                Code:
                #COMPILE EXE
                #DIM ALL
                
                %DIG_BUFF_SIZE = 1024 * 512
                %NUMBER_BASE = 10
                
                FUNCTION PBMAIN () AS LONG
                  DIM sDigBuff(0 TO 1) AS STRING
                  LOCAL sKBInput AS STRING
                  LOCAL pbMSDigit, pbLSDigit, pbSum AS BYTE PTR
                  LOCAL gISAPALINDROME, gIteration AS LONG
                  LOCAL gYPos, gXpos AS LONG
                  LOCAL gShowIteration, gShowIterationStep AS LONG
                
                  RANDOMIZE TIMER
                
                  sDigBuff(0) = STRING$(%DIG_BUFF_SIZE, CHR$(0))
                  sDigBuff(1) = STRING$(%DIG_BUFF_SIZE, CHR$(0))
                
                  PRINT "Press SPACE to abort a search at any time"
                
                  pbLSDigit = STRPTR(sDigBuff(0)) + %DIG_BUFF_SIZE - 1
                  pbSum = STRPTR(sDigBuff(1)) + %DIG_BUFF_SIZE - 1
                
                Start:
                 'This for keyboard input:
                  INPUT "A number or just ENTER to exit ";sKBInput
                
                  IF ISFALSE LEN(sKBInput) THEN EXIT FUNCTION
                
                  pbMSDigit = AssignRight(pbLSDigit, STRPTR(sKBInput), LEN(sKBInput))
                
                  IF ISFALSE pbMSDigit THEN 'failure to intercept this condition will cause a crash
                    PRINT "Invalid digit in number (BASE = " + DEC$(%NUMBER_BASE) + ")"
                    GOTO Start '!
                  END IF
                
                  'Or this for a random number:
                  #IF 0
                  pbMSDigit = GetRndDigiStr(pbLSDigit, 12)  'Last arg is max number of digits (min is always 2)
                  PRINT "Starting with:";
                  GetDigiStr(pbLSDigit, pbMSDigit)
                  PRINT $CRLF + "Press ENTER to exit or any other key to proceed"
                  IF WAITKEY$ = $CR THEN EXIT FUNCTION
                  #ENDIF
                
                  PRINT $CRLF + "ITERATION: "
                
                  gYPos = CURSORY
                  gXPos = 12
                
                  gIteration = 1
                  gShowIterationStep = 1
                  gShowIteration = 1
                
                  CURSOR OFF
                
                DO:
                
                  IF INKEY$ = $SPC THEN GOTO Start
                
                  IF gIteration = gShowIteration THEN
                    LOCATE gYPos, gXPos
                    PRINT DEC$(gIteration) + ", " + DEC$(pbLSDigit - pbMSDigit + 1) + " Digits"
                
                    IF gIteration = 10000 THEN 'Update only every 100th iteration from now on
                      gShowIterationStep = 100
                    END IF
                
                    gShowIteration = gShowIteration + gShowIterationStep
                
                  END IF
                
                  IF (pbLSDigit - pbMSDigit) >= %DIG_BUFF_SIZE THEN
                    PRINT $CRLF + "Maximum digit count reached!" + $CRLF
                    CURSOR ON
                    GOTO Start
                  END IF
                
                  pbMSDigit = CrossAddDigits(pbMSDigit, pbLSDigit, pbSum, gISAPALINDROME)
                
                  SWAP pbSum, pbLSDigit
                
                  IF ISTRUE gISAPALINDROME THEN
                    PRINT DEC$(pbLSDigit - pbMSDigit + 1)+"-digit palindrome found on iteration " + DEC$(gIteration) + "!"
                    PRINT
                    PRINT GetDigiStr(pbLSDigit, pbMSDigit)
                    PRINT
                    CURSOR ON
                    GOTO Start
                  END IF
                
                  INCR gIteration
                
                LOOP
                
                
                END FUNCTION
                
                FUNCTION GetDigiStr(BYVAL pbLSDigit AS BYTE PTR, BYVAL pbMSDigit AS BYTE PTR) AS STRING
                  'returns the deliniated digit sequence as an ascii string
                  LOCAL sOut AS STRING
                
                  DO WHILE pbMSDigit <= pbLSDigit
                    sOut = sOut + CHR$(@pbMSDigit + ASC("0"))
                    INCR pbMSDigit
                  LOOP
                
                  FUNCTION = sOut
                
                END FUNCTION
                
                FUNCTION AssignRight(BYVAL pbDestBuffEnd AS BYTE PTR, BYVAL pbSource AS BYTE PTR, BYVAL gLenSource AS LONG) AS DWORD
                  'Coverts ascii digits to unbiased byte values and places them at the high end of the buffer
                  LOCAL gDigit AS LONG
                
                  FOR gDigit = -gLenSource + 1 TO 0
                    IF (@pbSource < ASC("0")) OR (@pbSource >= (ASC("0") + %NUMBER_BASE)) THEN
                      EXIT FUNCTION 'Digit out-of-range!
                    END IF
                    @pbDestBuffEnd[gDigit] = @pbSource - ASC("0")
                    INCR pbSource
                  NEXT gDigit
                
                  FUNCTION = pbDestBuffEnd - gLenSource + 1
                
                END FUNCTION
                
                FUNCTION CrossAddDigits(BYVAL pbMSDigit AS BYTE PTR, BYVAL pbLSDigit AS BYTE PTR, BYVAL pbSum AS BYTE PTR, BYREF gISAPALINDROME AS LONG) AS DWORD
                  'Cross adds the deliniated sequence of digits, then tests the resulting sum to see if it is palindromic
                  LOCAL gDigit, gCARRY AS LONG
                
                  FOR gDigit = 0 TO pbLSDigit - pbMSDigit
                    @pbSum[-gDigit] = @pbMSDigit[gDigit] + @pbLSDigit[-gDigit] + gCARRY
                    gCARRY = -(@pbSum[-gDigit] > (%NUMBER_BASE - 1))
                    IF ISTRUE gCARRY THEN @pbSum[-gDigit] = @pbSum[-gDigit] - %NUMBER_BASE
                  NEXT gDigit
                
                  IF ISTRUE gCARRY THEN
                    @pbSum[-gDigit] = 1
                    INCR gDigit
                  END IF
                
                  pbMSDigit = pbSum - gDigit + 1
                
                  FUNCTION = pbMSDigit
                
                  gISAPALINDROME = -1 'Guilty until proven innocent
                
                  DO WHILE (ISTRUE gISAPALINDROME) AND (pbSum >= pbMSDigit)
                    gISAPALINDROME = (@pbMSDigit = @pbSum)
                    DECR pbSum
                    INCR pbMSDigit
                  LOOP
                
                END FUNCTION
                
                FUNCTION GetRndDigiStr(BYVAL pbLSDigit AS BYTE PTR, BYVAL gMaxNumDigits AS LONG) AS DWORD
                   LOCAL pbMSDigit AS BYTE PTR
                
                   IF gMaxNumDigits > (%DIG_BUFF_SIZE * 0.8) THEN gMaxNumDigits = %DIG_BUFF_SIZE * 0.8
                
                   pbMSDigit = pbLSDigit - RND(2, gMaxNumDigits)
                
                   DO WHILE pbLSDigit > pbMSDigit
                     @pbLSDigit = RND(0, %NUMBER_BASE - 1)
                     DECR pbLSDigit
                   LOOP
                
                   'Ensure MS digit isn't zero
                   @pbMSDigit = RND(1, %NUMBER_BASE - 1)
                
                   FUNCTION = pbMSDigit
                
                END FUNCTION
                Last edited by Mark Bullivant; 11 May 2020, 02:54 AM. Reason: added link to wiki article

                Comment


                • #48
                  This topic was put here for information, didactic purposes and also for mental recreation.
                  This conjecture, as well as many others, will not be resolved by exhaustive search.
                  This problem is analogous to the search for prime numbers, which as we all know, still has no solution.

                  Is there a pattern that can be found?
                  That is the question.

                  Thank you all for the interesting proposals / contributions.

                  Ribeiro Alvo

                  Comment


                  • #49
                    This is my last contribution to this project unless a bug is brought to my attention. I rewrote the code for the CrossAddDigits function in assembler, which hopefully will make it a bit quicker. I also made a couple of other minor changes.

                    Code:
                    #COMPILE EXE
                    #DIM ALL
                    
                    %DIG_BUFF_SIZE = 1024 * 512
                    %NUMBER_BASE = 10
                    %DIGIT_BIAS = 256 - %NUMBER_BASE
                    
                    FUNCTION PBMAIN () AS LONG
                      DIM sDigBuff(0 TO 1) AS STRING
                      LOCAL sKBInput AS STRING
                      LOCAL pbMSDigit, pbLSDigit, pbSum AS BYTE PTR
                      LOCAL gISAPALINDROME, gIteration AS LONG
                      LOCAL gYPos, gXpos AS LONG
                      LOCAL gShowIteration, gShowIterationStep AS LONG
                    
                      RANDOMIZE TIMER
                    
                      sDigBuff(0) = STRING$(%DIG_BUFF_SIZE, CHR$(0))
                      sDigBuff(1) = STRING$(%DIG_BUFF_SIZE, CHR$(0))
                    
                      PRINT "Press SPACE to abort a search at any time"
                    
                      pbLSDigit = STRPTR(sDigBuff(0)) + %DIG_BUFF_SIZE - 1
                      pbSum = STRPTR(sDigBuff(1)) + %DIG_BUFF_SIZE - 1
                    
                    Start:
                     'This for keyboard input:
                      INPUT "A number or just ENTER to exit ";sKBInput
                    
                      IF ISFALSE LEN(sKBInput) THEN EXIT FUNCTION
                    
                      pbMSDigit = AssignRight(pbLSDigit, STRPTR(sKBInput), LEN(sKBInput))
                    
                      IF ISFALSE pbMSDigit THEN 'failure to intercept this condition will cause a crash
                        PRINT "Invalid digit in number (BASE = " + DEC$(%NUMBER_BASE) + ")"
                        GOTO Start '!
                      END IF
                    
                      'Or this for a random number:
                      #IF 0
                      pbMSDigit = GetRndDigiStr(pbLSDigit, 12)  'Last arg is max number of digits (min is always 2)
                      PRINT "Starting with:";
                      GetDigiStr(pbLSDigit, pbMSDigit)
                      PRINT $CRLF + "Press ENTER to exit or any other key to proceed"
                      IF WAITKEY$ = $CR THEN EXIT FUNCTION
                      #ENDIF
                    
                      PRINT $CRLF + "ITERATION: "
                    
                      gYPos = CURSORY
                      gXPos = 12
                    
                      gIteration = 1
                      gShowIterationStep = 1
                      gShowIteration = 1
                    
                      CURSOR OFF
                    
                    DO:
                    
                      IF INKEY$ = $SPC THEN GOTO Start
                    
                      IF gIteration = gShowIteration THEN
                        LOCATE gYPos, gXPos
                        PRINT DEC$(gIteration) + ", " + DEC$(pbLSDigit - pbMSDigit + 1) + " Digits"
                    
                        IF gIteration = 10000 THEN 'Update only every 100th iteration from now on
                          gShowIterationStep = 100
                        END IF
                    
                        gShowIteration = gShowIteration + gShowIterationStep
                    
                      END IF
                    
                      IF (pbLSDigit - pbMSDigit) >= %DIG_BUFF_SIZE THEN
                        PRINT $CRLF + "Maximum digit count reached!" + $CRLF
                        CURSOR ON
                        GOTO Start
                      END IF
                    
                      pbMSDigit = CrossAddDigits(pbMSDigit, pbLSDigit, pbSum, gISAPALINDROME)
                    
                      SWAP pbSum, pbLSDigit
                    
                      IF ISTRUE gISAPALINDROME THEN
                        PRINT DEC$(pbLSDigit - pbMSDigit + 1)+"-digit palindrome found on iteration " + DEC$(gIteration) + "!"
                        PRINT
                        PRINT GetDigiStr(pbLSDigit, pbMSDigit)
                        PRINT
                        CURSOR ON
                        GOTO Start
                      END IF
                    
                      INCR gIteration
                    
                    LOOP
                    
                    
                    END FUNCTION
                    
                    FUNCTION GetDigiStr(BYVAL pbLSDigit AS BYTE PTR, BYVAL pbMSDigit AS BYTE PTR) AS STRING
                      'returns the deliniated digit sequence as an ascii string
                      LOCAL sOut AS STRING
                    
                      DO WHILE pbMSDigit <= pbLSDigit
                        sOut = sOut + CHR$(@pbMSDigit + ASC("0") - %DIGIT_BIAS)
                        INCR pbMSDigit
                      LOOP
                    
                      FUNCTION = sOut
                    
                    END FUNCTION
                    
                    FUNCTION AssignRight(BYVAL pbDestBuffEnd AS BYTE PTR, BYVAL pbSource AS BYTE PTR, BYVAL gLenSource AS LONG) AS DWORD
                      'Coverts ascii digits to unbiased byte values and places them at the high end of the buffer
                      LOCAL gDigit AS LONG
                    
                      FOR gDigit = -gLenSource + 1 TO 0
                        IF (@pbSource < ASC("0")) OR (@pbSource >= (ASC("0") + %NUMBER_BASE)) THEN
                          EXIT FUNCTION 'Digit out-of-range!
                        END IF
                        @pbDestBuffEnd[gDigit] = @pbSource - ASC("0") + %DIGIT_BIAS
                        INCR pbSource
                      NEXT gDigit
                    
                      FUNCTION = pbDestBuffEnd - gLenSource + 1
                    
                    END FUNCTION
                    
                    FUNCTION CrossAddDigits(BYVAL pbMSDigit AS BYTE PTR, BYVAL pbLSDigit AS BYTE PTR, BYVAL pbSum AS BYTE PTR, BYREF gISAPALINDROME AS LONG) AS DWORD
                      #REGISTER NONE
                      'Cross adds the deliniated sequence of digits, then tests the resulting sum to see if it is palindromic
                    
                      !MOV ESI, pbLSDigit
                      !MOV EBX, ESI
                      !MOV EDI, pbMSDigit
                      !MOV EDX, pbSum
                      !PUSH EDX
                      !MOV ECX, 1
                      !MOV AH, %DIGIT_BIAS  'Digit bias is +(256 - number base), this ensures the carry flag will be set/reset appropiately
                      !CLC
                      !PUSHF
                    
                    #ALIGN 16
                    CALOOP:
                      !MOV AL, [EDI]
                      !SUB AL, AH
                      !POPF
                      !ADC AL, [ESI]
                      !PUSHF
                      !JNC SHORT SKIPADJ
                      !ADD AL, AH
                    
                    SKIPADJ:
                      !MOV [EDX], AL
                      !ADD EDI, ECX
                      !SUB ESI, ECX
                      !SUB EDX, ECX
                      !CMP EDI, EBX
                      !JBE SHORT CALOOP
                    
                     'Prepend 1 to the number if carry is true on adding the last digits
                      !POPF
                      !JNC SHORT SKPA
                      !INC AH         'Digit bias + 1
                      !MOV BYTE [EDX], AH
                      !DEC ESI
                    SKPA:  'Calculate the pos of the MS digit in the Sum buffer
                      !SUB EBX, ESI
                      !POP ESI
                      !MOV EDI, ESI
                      !SUB EDI, EBX
                      !INC EDI
                      !MOV FUNCTION, EDI
                    
                      'See if the number in the sum buffer is palindromic
                      !MOV ECX, gISAPALINDROME 'byref
                      !MOV DWORD [ECX], -1
                    
                    #ALIGN 16
                    CHKPAL:
                      !CMP ESI, EDI
                      !JB SHORT ISAPAL
                      !MOV BL, [ESI]
                      !MOV BH, [EDI]
                      !DEC ESI
                      !INC EDI
                      !CMP BL, BH
                      !JE SHORT CHKPAL
                    
                      !MOV DWORD [ECX], 0
                    
                    ISAPAL:
                    
                    END FUNCTION
                    
                    FUNCTION GetRndDigiStr(BYVAL pbLSDigit AS BYTE PTR, BYVAL dwMaxNumDigits AS DWORD) AS DWORD
                       LOCAL pbMSDigit AS BYTE PTR
                    
                       IF dwMaxNumDigits > (%DIG_BUFF_SIZE * 0.8) THEN
                         dwMaxNumDigits = %DIG_BUFF_SIZE * 0.8
                       ELSEIF dwMaxNumDigits < 2 THEN
                         dwMaxNumDigits = 2
                       END IF
                    
                       pbMSDigit = pbLSDigit - RND(2, dwMaxNumDigits)
                    
                       DO WHILE pbLSDigit > pbMSDigit
                         @pbLSDigit = RND(0, %NUMBER_BASE - 1) + %DIGIT_BIAS
                         DECR pbLSDigit
                       LOOP
                    
                       'Ensure MS digit isn't zero
                       @pbMSDigit = RND(1, %NUMBER_BASE - 1) + %DIGIT_BIAS
                    
                       FUNCTION = pbMSDigit
                    
                    END FUNCTION

                    Comment

                    Working...
                    X