パズル万華鏡

面白いパズルの紹介と解説をします。

正整数を変換する操作についての考察(2)

 正整数を変換する操作についての考察(2)を紹介します。

考察(2)

 m桁の正整数a(1)に変換操作を行い、
f:id:isemba:20150905092514j:plain
を得たとする。m(2≦m≦7)について、繰り返しの起点となる値a(p),a(1)はつぎのようになる。
f:id:isemba:20150905092540j:plain
 m桁の正整数における繰り返しの起点a(p),a(1)を求めるプログラムはつぎのようになる。

●考え方

①配列要素A(N)(1≦N≦10m-1)に正整数Nに変換操作を1回行って得られる値を
 保存する。

②正整数X(1≦X≦10m-1)からスタートして変換操作を続けたときの正整数の推移
 (a(1)→a(2)→a(3)→…→a(i)→…→a(p)→a(p+1)→…→a(q))を配列Aを
 活用して調べる。

③正整数a(i)の出現した順番iを配列B(a(i))に保存していき、2度目に
 出現したとき、繰り返しの起点とする。

④得られた繰り返しの起点は、配列Cに重複しないように保存する。

⑤配列Cに保存された起点を表示する。

●プログラム(N6174c.bas)

' << N6174c.bas >> 
' Tiny Basic
'
' 繰り返しの起点を探索。
'
Dim A(9999999): ' A(N):正整数Nに変換操作を1回行って得られる値。
Dim B(9999999): ' 変換操作で得られる正整数の順番を保存する配列。
Dim C(99):      ' 起点を保存する配列。
Dim D(9):       ' 正整数の各桁を保存する配列。
'
' 桁数Mの設定。
For M=2 To 7
  '
  N1=1:      ' M桁の正整数の最小数。                     
  N2=10^M-1: ' M桁の正整数の最大数。                     
  '                                                      
  ' 配列A(*)を求める。                                   
  For N=N1 To N2                                         
    '                                                    
    T0=N: ' 変換操作前の正整数T0。                       
    '                                                    
    ' 整数Nを各桁に分解し、配列D(*)に保存。Kは桁数。     
    T=T0: K=0                                            
    While T > 0                                          
      K=K+1: D(K)=T Mod 10: T=Int(T/10)                  
    Wend                                                 
    ' TがM桁未満の場合、0を補う。                        
    While K < M: K=K+1: D(K)=0: Wend                     
    '                                                    
    ' 配列D(*)の要素を昇順に並べる。                     
    For I=K To 1 Step -1                                 
      For J=1 To I-1                                     
        If D(J) > D(J+1) Then                            
          W=D(J): D(J)=D(J+1): D(J+1)=W                  
        End If                                           
      Next J                                             
    Next I                                               
    '                                                    
    ' 最大数MAXNを求める。                               
    MAXN=0                                               
    For I=K To 1 Step -1: MAXN=MAXN*10+D(I): Next I      
    '                                                    
    ' 最小数MINNを求める。                               
    MINN=0                                               
    For I=1 To K: MINN=MINN*10+D(I): Next I              
    '                                                    
    ' 変換操作後の正整数T1:最大値-最小値                   
    T1=MAXN-MINN                                         
    '                                                    
    A(T0)=T1                                             
  Next N                                                 
  '                                                      
  ' 繰り返しの起点Xを求める。                            
  B(0)=0                                                 
  For I=N1 To N2: B(I)=0: Next I                         
  '                                                      
  K=0: C(0)=0                                            
  For I=N1 To N2                                         
    X=I                                                  
    J=0: ' 変換操作の回数。                              
    While B(X) = 0:                                      
      J=J+1: B(X)=J                                      
      X=A(X)                                             
    Wend                                                 
    '                                                    
    ' 起点Xの値を重複を除いて保存する。              
    IND=0                                                
    For L=0 To K                                         
      If C(L) = X Then IND=1: Exit For                   
    Next L                                               
    If IND = 0 Then                                      
      L=K                                                
      While X < C(L): C(L+1)=C(L): L=L-1: Wend           
      If X > C(L) Then C(L+1)=X: K=K+1                   
    End If                                               
    '                                                    
    ' 配列B(*)をリセット。                               
    X=I: While B(X) > 0: B(X)=0: X=A(X): Wend            
  Next I                                                 
  '                                                      
  ' 結果の表示。                                         
  Print M;"桁の正整数"                                   
  For L=1 To K                                           
    Print C(L);                                          
  Next L                                                 
  Print: Print                                                  
Next M
End

実行結果
f:id:isemba:20150905092826j:plain
f:id:isemba:20150905092842j:plain