裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

英語で数を読む

2015年03月16日 | ブログラミング

符号付き 32 ビット整数を英語で読めとのお達しで...

o1 = c("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven",
  "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen")
o2 = c("", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety")
o3 = "Hundred"
o4 = c("Thousand", "Million", "Billion")
count = function(n) {
  cat("n =", n, "\n")
  ans = NULL
  if (0 > n) {
    ans = "Negative"
    n = -n
  }
  s = unlist(strsplit(as.character(abs(n)), ""))
  ns = length(s)
  if (12 > ns) s = c(rep(0, 12 - ns), s)
  s = matrix(as.numeric(s), ncol = 3, byrow = TRUE)
  if (all(s == 0)) ans = "Zero"
  for (i in 1:4) {
    if (any(s[i, ] != 0)) {
      if (s[i, 1] > 0) ans = c(ans, o1[s[i, 1]], o3)
      if (s[i, 2] >= 2) {
        ans = c(ans, o2[s[i, 2]])
        if (s[i, 3] != 0) ans = c(ans, o1[s[i, 3]])
      }
      if (1 >= s[i, 2] && (s[i, 2] + s[i, 3] != 0)) ans = c(ans, o1[s[i, 2] * 10 + s[i, 3]])
      if (3 >= i) ans = c(ans, o4[4 - i])
    }
  }
  paste(ans, collapse = " ")
}
# テストデータ
q = c(7, 123, 4567, 89012, 0, -34, -5678901, 1111111111)
ans = c("Seven", "One Hundred Twenty Three", "Four Thousand Five Hundred Sixty Seven", "Eighty Nine Thousand Twelve",
  "Zero", "Negative Thirty Four", "Negative Five Million Six Hundred Seventy Eight Thousand Nine Hundred One",
  "One Billion One Hundred Eleven Million One Hundred Eleven Thousand One Hundred Eleven")
for (i in seq_along(q)) {
  a = count(q[i])
  cat("a: ", a, "\n")
  cat("b: ", ans[i], "\n")
  if (a != ans[i]) cat("Wrong!!\n\n")
}

結果は一応 OK

n = 7
a:  Seven
b:  Seven

n = 123
a:  One Hundred Twenty Three
b:  One Hundred Twenty Three

n = 4567
a:  Four Thousand Five Hundred Sixty Seven
b:  Four Thousand Five Hundred Sixty Seven

n = 89012
a:  Eighty Nine Thousand Twelve
b:  Eighty Nine Thousand Twelve

n = 0
a:  Zero
b:  Zero

n = -34
a:  Negative Thirty Four
b:  Negative Thirty Four

n = -5678901
a:  Negative Five Million Six Hundred Seventy Eight Thousand Nine Hundred One
b:  Negative Five Million Six Hundred Seventy Eight Thousand Nine Hundred One

n = 1111111111
a:  One Billion One Hundred Eleven Million One Hundred Eleven Thousand One Hundred Eleven
b:  One Billion One Hundred Eleven Million One Hundred Eleven Thousand One Hundred Eleven

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

カプレカ数(その2)

2015年03月16日 | ブログラミング

カプレカ数」での,二番目の定義によるものを出力するプログラム。

かなり時間のかかるプログラムであり,5 番目のカプレカ数を出力するまでには 35 秒かかる。

N = 631764
for (i in 0:N) {
  str = unlist(strsplit(as.character(i), ""))
  big = as.numeric(paste(sort(str, decreasing = TRUE), collapse=""))
  small = as.numeric(paste(sort(str), collapse=""))
  if (big - small == i) print(i)
}

[1] 0
[1] 495
[1] 6174
[1] 549945
[1] 631764
   ユーザ   システム       経過  
    34.915      0.202     34.773

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

カプレカ数

2015年03月16日 | ブログラミング

0 から 1000 までのカプレカ数を求めよとのことだ...

カプレカ数とは馴染みのないものであるが,定義は 2 通りあるそうだ。

1. 2 乗して前の部分と後ろの部分に分けて(偶数桁 2n 桁である場合は先頭 n 桁と末尾 n 桁に分け,奇数桁 2n + 1 桁である場合は先頭 n 桁と末尾 n + 1 桁に分けて)和を取ったとき,元の値に等しくなるもの。

2. 桁を並べ替えて最大にしたものから最小にしたものの差を取ったとき,元の値に等しくなるもの。

今回は,前者のことをいっているようだ。

Wikipedia で調べると
カプレカ数
1, 9, 45, 55, 99, 297, 703, 999, 2223, 2728, 4879, 4950, 5050, 5292, …(オンライン整数列大辞典の数列 A006886 http://oeis.org/A006886)が簡単に見つかる。
プログラムを書いて,0 ~ 5300 の範囲を探索すると,得られる出力と違うところがある。

a1 = 0:5300
a2 = a1^2
old = options(scipen=10)
a3 = strsplit(as.character(a2), "")
options(old)
a4 = sapply(a3, function(x) {
            y = unlist(x)
            n = length(y)
            if (n == 1) {
              as.numeric(paste(y, collapse=""))
            } else {
              m = n %/% 2
              as.numeric(paste(y[1:m], collapse="")) + as.numeric(paste(y[(m+1):n], collapse=""))
            }
          })
a1[a1 == a4]

> a1[a1 == a4]
 [1]    0    1    9   45   55   99  297  703  999 2223 2728 4950 5050

0 は明白な カプレカ数だと思うがそれはさておき,プログラムによる出力には 4879 はない。4879^2 = 2380 と 4641 なので,2380 + 4641 = 7021 になるので,カプレカ数ではないはず。2380 の最後の 0 を無視するというルールならば,238 + 4641 = 4879 になるのでカプレカ数ということになるのだが。同様に,5292^2 = 2800 と 5264 なので,28 + 5264 = 5292 ではあるが?と根拠を求めてネットサーフィンすると,

Karekar numbers
http://www.numbersaplenty.com/set/Kaprekar_number/

に,

Note that the second part can start with zero:  5292^2 = {28} {005264}  and 28+5264=5292.

と書いてあった。後ろ半分の数字の前に 0 があってもよいということは,前の部分の後ろの 0 は無視してもよいということである(無視しない場合も考えよということ)。このルールも加えてプログラムを修正する。

プログラムに for を使うことになったがやむを得ない。

N = 5300
a1 = 0:N
a2 = a1^2
old = options(scipen=10)
a3 = strsplit(as.character(a2), "")
options(old)
a4 = a5 = integer(N+1)
for (i in seq_along(a1)) {
  y = unlist(a3[[i]])
  n = length(y)
  if (n == 1) {
    a4[i] = a5[i] = as.numeric(paste(y, collapse=""))
  } else {
    m = n %/% 2
    a4[i] = as.numeric(paste(y[1:m], collapse="")) + # 前半分の後ろの 0 を無視しない
            as.numeric(paste(y[(m+1):n], collapse=""))
    a5[i] = as.numeric(paste(gsub("0*$", "", y[1:m]), collapse="")) + # 前半分の後ろの 0 を無視する
            as.numeric(paste(y[(m+1):n], collapse=""))
  }
}
a1[a1 == a4 | a1 == a5] # 前半分の後ろの 0 を無視しない場合と無視する場合のどちらか一方でも可ということで

> a1[a1 == a4 | a1 == a5]
 [1]    0    1    9   45   55   99  297  703  999 2223 2728 4879 4950 5050 5292

Wikipedia などの例示と一致した。

10 万までで 5 秒弱かかって,以下の結果を得る。

> print(a1[a1 == a4 | a1 == a5])})
 [1]     0     1     9    45    55    99   297   703   999  2223  2728  4879  4950  5050  5292  7272
[17]  7777  9999 17344 22222 38962 77778 82656 95121 99999

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村