桁数を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)
最後の部分は桁あふれした時のための判定である。
これも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)
nを10で割り、余りを A%(1) から順に格納していき、最後に桁数を返す。
プログラムは以下のとおり。
fnDec(N) local I%=0 while N>0 inc I%:N=N\10:A%(I%)=res wend:return(I%)
最上位の方から順に表示していく。表示が終ったら改行する。プログラムは以下のとおり。
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まで回すようにすればよい。
さて、実行結果はどうなるか。
前 | この章の目次 | 次 |
---|