2018年12月23日日曜日

カプレカ数

 しばらく前に,どこかで,カプレカ数(Kaprekar Number)を見かけた。Julia言語でプログラミングしようとすると,あれやこれやわかっていなくて難渋した。

 カプレカ数には複数の定義がある。(1)ある正整数の2乗を上位桁と下位桁の2数に分割して和をとったものが,もとの整数に等しいもの。分割の仕方がより一般的なものとより制限的なものの2種類がある。(2)ある正整数の桁を並べ替えてできる最大の数から最小の数を引いた(カプレラ写像した)ものがもとの整数と等しいもの。どのような3桁の数もカプレラ写像を繰り返すと0または495になる。また,同様に4桁の数は0または6174になる(西山豊 6174の不思議Mysterious Number 6174)。それ以外の桁の数では一定の範囲で反復するが収束しない場合もあるので,そこまで親切に面倒をみていないので残念な下記コードを動かす場合は注意が必要である。

 Julia は強力な型変換機能を持っているが,実数を整数化するような簡単な操作で逆につまずいた。ある実数の値の変数を Int() で整数化しようとするとエラーになる。その実数の値が整数と同じならば問題ない。例えば,x=1. ; print(Int(x)) は問題なしなのだが,x=1.5 ; print(Int(x)) は,InexactError: Int64(Int64, 1.5) となる・・・orz。整数除算の div(m,n) もちょっと見栄えがよくないかも。配列が 0 から始まらないのはまあいいか。


function kaprekar1(m)
#this is a kaprekar number http://oeis.org/A053816
#NOT the definition http://oeis.org/A006886
  m2=m^2
  n=Int(ceil(log10(m2+.1)))
  nun=zeros(Int,n)
  for k in 1:n
    nun[k]=m2 % 10
    m2=div(m2-nun[k],10)
  end
  n1=n%2
  n2=div(n,2)
  sum=nun[n-n2]*n1
  for k in 1:n2
    sum=sum*10+nun[n+1-k]+nun[n-n2+1-k-n1]
  end
  if m==sum
    println(sum)
  end
end

function kaprekar2(m)
#this is an another kaprekar number http://oeis.org/A099009
  n=Int(ceil(log10(m)))
  nun=zeros(Int,n)
  for k in 1:n
    nun[k]=m % 10
    m=div(m-nun[k],10)
  end
  min=sort(nun)
  dif=0
  for k in 1:n
    dif=dif*10+min[n-k+1]-min[k]
  end
  return dif
end

k=2 #inout data1
for i in 10^(k-1):10^k-1
  kaprekar1(i)
end

new=3833 #input data2
cnt=0
while old != new
  old=new
  new=kaprekar2(old)
  cnt=cnt+1
end
  println((cnt,new))

45
55
99
(7, 6174)


0 件のコメント: