Task: Disarium numbers




Go: package main

import (
    "fmt"
    "strconv"
)

const DMAX = 20  
const LIMIT = 20 

func main() {
    
    EXP := make([][]uint64, 1+DMAX)
    POW := make([][]uint64, 1+DMAX)

    EXP[0] = make([]uint64, 11)
    EXP[1] = make([]uint64, 11)
    POW[0] = make([]uint64, 11)
    POW[1] = make([]uint64, 11)
    for i := uint64(1); i <= 10; i++ {
        EXP[1][i] = i
    }
    for i := uint64(1); i <= 9; i++ {
        POW[1][i] = i
    }
    POW[1][10] = 9

    for i := 2; i <= DMAX; i++ {
        EXP[i] = make([]uint64, 11)
        POW[i] = make([]uint64, 11)
    }
    for i := 1; i < DMAX; i++ {
        for j := 0; j <= 9; j++ {
            EXP[i+1][j] = EXP[i][j] * 10
            POW[i+1][j] = POW[i][j] * uint64(j)
        }
        EXP[i+1][10] = EXP[i][10] * 10
        POW[i+1][10] = POW[i][10] + POW[i+1][9]
    }

    
    DIGITS := make([]int, 1+DMAX) 
    Exp := make([]uint64, 1+DMAX) 
    Pow := make([]uint64, 1+DMAX) 

    var exp, pow, min, max uint64
    start := 1
    final := DMAX
    count := 0
    for digit := start; digit <= final; digit++ {
        fmt.Println("# of digits:", digit)
        level := 1
        DIGITS[0] = 0
        for {
            
            
            for 0 < level && level < digit {
                
                if DIGITS[level] > 9 {
                    DIGITS[level] = 0
                    level--
                    DIGITS[level]++
                    continue
                }

                
                Exp[level] = Exp[level-1] + EXP[level][DIGITS[level]]
                Pow[level] = Pow[level-1] + POW[digit+1-level][DIGITS[level]]

                
                pow = Pow[level] + POW[digit-level][10]

                if pow < EXP[digit][1] { 
                    DIGITS[level]++
                    continue
                }

                max = pow % EXP[level][10]
                pow -= max
                if max < Exp[level] {
                    pow -= EXP[level][10]
                }
                max = pow + Exp[level]

                if max < EXP[digit][1] { 
                    DIGITS[level]++
                    continue
                }

                
                exp = Exp[level] + EXP[digit][1]
                pow = Pow[level] + 1

                if exp > max || max < pow { 
                    DIGITS[level]++
                    continue
                }

                if pow > exp {
                    min = pow % EXP[level][10]
                    pow -= min
                    if min > Exp[level] {
                        pow += EXP[level][10]
                    }
                    min = pow + Exp[level]
                } else {
                    min = exp
                }

                
                if max < min {
                    DIGITS[level]++ 
                } else {
                    level++ 
                }
            }

            
            if level < 1 {
                break
            }

            
            
            Exp[level] = Exp[level-1] + EXP[level][DIGITS[level]]
            Pow[level] = Pow[level-1] + POW[digit+1-level][DIGITS[level]]

            
            for DIGITS[level] < 10 {
                
                if Exp[level] == Pow[level] {
                    s := ""
                    for i := DMAX; i > 0; i-- {
                        s += fmt.Sprintf("%d", DIGITS[i])
                    }
                    n, _ := strconv.ParseUint(s, 10, 64)
                    fmt.Println(n)
                    count++
                    if count == LIMIT {
                        fmt.Println("\nFound the first", LIMIT, "Disarium numbers.")
                        return
                    }
                }

                
                DIGITS[level]++
                Exp[level] += EXP[level][1]
                Pow[level]++
            }

            
            DIGITS[level] = 0
            level--
            DIGITS[level]++
        }
        fmt.Println()
    }
}






COBOL:        IDENTIFICATION DIVISION.
       PROGRAM-ID. DISARIUM.
       
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 VARIABLES.
          03 CANDIDATE     PIC 9(9).
          03 DIGITS        PIC 9 OCCURS 9 TIMES, REDEFINES CANDIDATE.
          03 IDX           PIC 99.
          03 EXPONENT      PIC 99.
          03 DGT-POWER     PIC 9(9).
          03 DGT-POWER-SUM PIC 9(9).
          03 CAND-OUT      PIC Z(8)9.
          03 AMOUNT        PIC 99 VALUE 18.
          
       PROCEDURE DIVISION.
       BEGIN.
           PERFORM DISARIUM-TEST VARYING CANDIDATE FROM ZERO BY 1
           UNTIL AMOUNT IS ZERO.
           STOP RUN.
        
       DISARIUM-TEST.
           MOVE ZERO TO DGT-POWER-SUM.
           MOVE 1 TO EXPONENT, IDX.
           INSPECT CANDIDATE TALLYING IDX FOR LEADING ZEROES.
           PERFORM ADD-DIGIT-POWER UNTIL IDX IS GREATER THAN 9.
           IF DGT-POWER-SUM IS EQUAL TO CANDIDATE,
               MOVE CANDIDATE TO CAND-OUT,
               DISPLAY CAND-OUT,
               SUBTRACT 1 FROM AMOUNT.
           
       ADD-DIGIT-POWER.
           COMPUTE DGT-POWER = DIGITS(IDX) ** EXPONENT.
           ADD DGT-POWER TO DGT-POWER-SUM.
           ADD 1 TO EXPONENT.
           ADD 1 TO IDX.