裏 RjpWiki

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

ダイヤルロックを解除して!

2017年04月18日 | ブログラミング

ダイヤルロックを解除して!

締め切りが 2017/04/18 10:00 AM なので,その 1 分後に投稿されるように予約

設問

以下の図のようなダイヤル式のロックが付いたポストがあります。
このロックを解除するには、ダイヤルを左右交互に回転し、特定の m 桁の番号を作るとポストを開けられます。
なお、最初はダイヤルの位置が「0」にセットされているものとし、左回転から開始します。
(番号は「0」以外から始まり、同じ番号が続くことはありません。) これ重要(見逃して,ドツボに入った)



例えば、m = 3 で「528」という番号の場合、「5」まで左に回し、次に「2」まで右に回し、最後に「8」まで左に回します。
このときに動いた目盛りの数 n を考えます。
上記の「528」の場合、図のように n = 5 + 3 + 6 = 14 となります。
このポストを開けるとき、 m と n は覚えていたのですが、元の番号を忘れてしまいました。
そこで、このポストで m と n の数から番号を推測しようと考えました。
標準入力から m と n がスペース区切りで与えられたとき、考えられる番号が何通りあるかを求め、標準出力に出力してください。
なお、m と n は 0 < m < n < 50 を満たす整数とします。
例えば、 m = 3, n = 6 のとき、以下の10通りがあります。
「104」「178」「180」「192」「202」「214」「290」「312」「324」「434」

【入出力サンプル】
標準入力
3 6

標準出力
10

====================================

いつも通りの方針に従う。すなわち,m の小さい場合について解を求め,規則性を探る。

f = function(m) {
    distribution = integer(9*m)
    for (i in (10^(m-1)):(10^m - 1)) { # m 桁の数が対象
        s = as.integer(unlist(strsplit(sprintf("%0*d", m+1, i), "")))
        count = 0
        for (k in 1:m) {
            if (s[k] == s[k + 1]) { # 「同じ数字が連続することはない」ことから
                count = 0
                break
            } else if (k%%2 == 1) {
                count = count + (s[k]-s[k + 1]) %% 10 # 左回り
            } else {
                count = count + (s[k + 1]-s[k]) %% 10# 右回り
            }
        }
        if (count != 0) {
            distribution[count] = distribution[count] + 1
        }
    }
    distribution
}

> f(1)
[1] 1 1 1 1 1 1 1 1 1
> f(2)
 [1] 0 1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1
> f(3)
 [1]  0  0  1  3  6 10 15 21 28 36 45 52 57 60 61 60 57 52 45 36 28 21 15 10  6  3  1
> f(4)
 [1]   0   0   0   1   4  10  20  35  56  84 120 165 216 270 324 375 420 456 480 489 480 456 420 375 324 270 216 165
[29] 120  84  56  35  20  10   4   1
> f(5)
 [1]    0    0    0    0    1    5   15   35   70  126  210  330  495  710  976 1290 1645 2030 2430 2826 3195 3510
[23] 3750 3900 3951 3900 3750 3510 3195 2826 2430 2030 1645 1290  976  710  495  330  210  126   70   35   15    5
[45]    1

下図のようになっている。


  以下略
 
m=3 の列は,m=2の列の (1,2,3,4,...,3,2,1) を 1 要素ずつずらして 9 回足す。



この規則をプログラム化して,大きな m, n  のときの解を求める。

f = function(m, n) {

    a = rep(1, 9)
    for (i in 2:m) {
        b = numeric(9*i)
        for (j in 1:9) {
            b[seq_along(a)+j] = b[seq_along(a)+j] + a
        }
        a = b
    }
    a[n]
}

f(3, 6) # 10
f(4, 10) # 84
f(5, 20) # 2826
f(10, 30) # 8337880
f(40, 49) # 1677106600

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 上下反転した数字表示器 | トップ | 境界線の長さ »
最新の画像もっと見る

コメントを投稿

ブログラミング」カテゴリの最新記事