2.プログラム

サブルーチン

(1) 逆順の数と足し算を行う (fnAdd(n))

桁数をnとした時、

1桁目とn桁目
2桁目とn−1桁目

……

i桁目とn−i+1桁目

の足し算を順に行っていく。
足し算の結果を配列 dim W%(n+1) に格納し、計算終了後、桁上がりを考慮して、
A%(n) に戻すようにする。プログラムは以下のとおり。

W%(n+1)=0
for i=1 to n
  W%(i)=A%(i)+A%(n-i+1)
  if W%(i)>=10 then W%(i+1)=1 : W%(i)=W%(i)-10
next i
if W%(n+1)>0 then W%(0)=n+1 else W%(0)=n
for i=0 to W%(0)
  A%(i)=W%(i)
next i

先頭の W%(n+1)=0 は足し算によって桁が増えたことを判定するための事前準備である。

確かにこれで計算できるが、

A%(i)+A%(j)=A%(j)+A%(i)

であるから、A%(i)+A%(j) の結果を W%(i)、W%(j) の両方に格納すると、
n桁全部ではなく半分まで計算で済むようになる。これは for の判定条件を

A%(i)<=A%(j)   (最下位≦最上位)

とすればよい。この方針のもとにプログラムを書き直すと ubasic では以下のようになる。

  fnAdd()
  for I%=1 to (K%+1)\2:J%=K%-I%+1
    W%(I%)=A%(I%)+A%(J%):W%(J%)=W%(I%)
  next I%
  A%(1)=0
  for I%=1 to K%
    A%(I%)=A%(I%)+W%(I%)
    if A%(I%)>=10 then A%(I%+1)=1:A%(I%)=A%(I%)-10:goto *
    A%(I%+1)=0
* next I%
  if A%(K%+1)>0 then inc K%
  if K%>M%-1 then return(1)
  return(0)

最後の部分は桁あふれした時のための判定である。


(2) 回文性の判定を行う (fnChk())

これもi=最下位、j=最上位として A%(i)<A%(j) の間、順に比較していけばよい。
リターン値として、回文的になった時は1、そうでない時は0を返すことにする。
プログラムは以下のとおり。

fnChk()
local I%,J%
for I%=1 to K%\2:J%=K%-I%+1
  if A%(I%)<>A%(J%) then cancel for:return(0)
next I%:return(1)

(3) nを配列 A%(n)に格納するサブルーチン (fnDec(n))

nを10で割り、余りを A%(1) から順に格納していき、最後に桁数を返す。
プログラムは以下のとおり。

fnDec(N)
local I%=0
while N>0
  inc I%:N=N\10:A%(I%)=res
wend:return(I%)

(4) 配列 A%(n)の値を表示するサブルーチン (fnPrt())

最上位の方から順に表示していく。表示が終ったら改行する。プログラムは以下のとおり。

fnPrt()
local I%
for I%=K% to 1 step -1
  print cutspc(str(A%(I%)));
next I%:print:return(0)

以上で道具立てはそろった。これらを組み合わせて1本のプログラムにする。

 10   ' additive palindromic
 20   M%=100:dim A%(M%),W%(M%)
 30   input "n=";N
 40   K%=fnDec(N):R%=fnPrt():C%=0:F%=fnChk()
 50   while F%=0
 60     inc C%:F%=fnAdd():if F%=1 then print "infinity":end
 70     R%=fnPrt():F%=fnChk()
 80   wend
 90   print "count=";C%;"keta=";K%:end
100   '
110   fnDec(N)
120   local I%=0
130   while N>0
140     inc I%:N=N\10:A%(I%)=res
150   wend:return(I%)
160   '
170   fnPrt()
180   local I%
190   for I%=K% to 1 step -1
200     print cutspc(str(A%(I%)));
210   next I%:print:return(0)
220   '
230   fnChk()
240   local I%,J%
250   for I%=1 to K%\2:J%=K%-I%+1
260    if A%(I%)<>A%(J%) then cancel for:return(0)
270   next I%:return(1)
280   '
290   fnAdd()
300   for I%=1 to (K%+1)\2:J%=K%-I%+1
310     W%(I%)=A%(I%)+A%(J%):W%(J%)=W%(I%)
320   next I%
330   A%(1)=0
340   for I%=1 to K%
350     A%(I%)=A%(I%)+W%(I%)
360     if A%(I%)>=10 then A%(I%+1)=1:A%(I%)=A%(I%)-10:goto 380
370     A%(I%+1)=0
380   next I%
390   if A%(K%+1)>0 then inc K%
400   if K%>M%-1 then return(1)
410   return(0)

MAX は扱える桁数を指定する。とりあえず 100とした。
このプログラムを実行してみる。
n=89を代入すると実行結果は以下のとおり。

89
187
968
1837
9218
17347
91718
173437
907808
1716517
8872688
17735476
85189247
159487405
664272356
1317544822
3602001953
7193004016
13297007933
47267087164
93445163438
176881317877
955594506548
1801200002107
8813200023188
count= 24 keta= 13

となり24回目で無事回文的になった。


では、12から1000までの数について調べてみることにする。
プログラムはnを入力する部分から countを出力する部分までを
for ループでn=12から1000まで回すようにすればよい。
さて、実行結果はどうなるか。


この章の目次

E-mail : kc2h-msm@asahi-net.or.jp
三島 久典