2〜36進数でカプレカ数

カプレカ数が何かについては カプレカ数 - Wikipediaの 2 番目の定義の方を見てください。
で、10 進法以外の場合でもカプレカ数の説明にある演算を行って、収束するかループするか調べる PostScript プログラムを作ってみた。

% ./kaprekar.ps -b 16 123

とすると

123 1FE DF2 CF3 BF4 AF5 9F6 8F7 7F8 7F8 以下ループ

などと表示される。123->1FE->DF2->...->7F8 と変わっていき、7F8 で収束する。ということで 7F8 が 16進数 3 桁のカプレカ数であることがわかる。(他にもあるかもしれないけど)

% ./kaprekar.ps -b 16 1234

などとすると、

1234 30ED E952 C3B4 9687 30ED 以下ループ

と表示され 30ED->E952->C3B4->9687->30ED でループすることがわかる。
以下ソース

#!/bin/sh
exec gs -q -dNODISPLAY -dBATCH -d#!='{2{currentfile 128 string readline{pop}if}repeat}' -- $0 "$@"

/base 10 def
/next_arg_is_base false def
/upcase{
    0 1 index{
        dup 97 ge 1 index 122 le and{
            32 sub
            3 copy put
        }if
        pop
        1 add
    }forall
    pop
}def

/basecvi{
    (  )cvs (#) concatstrings exch concatstrings cvi
}def

/repeatchar{
    dup string exch
    1 sub -1 0{
        1 index exch 3 index put
    }for
    exch pop
}def

/kaprekar{
    dup 40 string copy
    {lt}.sort /smaller exch def
    40 string copy
    {gt}.sort /larger exch def

    larger base basecvi
    smaller base basecvi sub
    base 40 string cvrs

    48 smaller length 2 index length sub repeatchar
    exch concatstrings
}def

[ARGUMENTS{
    next_arg_is_base{
        /base exch cvi def
        /next_arg_is_base false def
    }{
        dup(-b)eq{
            pop
            /next_arg_is_base true def
        }if
    }ifelse
}forall]
{
    [
        exch
        upcase
        {
            {
                dup =only ( ) print
                dup kaprekar
                counttomark 1 sub -1 1{
                    index 1 index eq{stop}if
                }for
            }loop
        }stopped pop
        =only( 以下ループ)=
    ] pop
}forall