裏 RjpWiki

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

ぐるぐるスクエア

2017年02月17日 | ブログラミング

ぐるぐるスクエア

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

【概要】

下図のように四角形のマスに数が入っています。



マスは無限に広がっており、全てのマスに数が入っています。
数を指定するので、その数が書かれているマスに隣接する(つまり、辺を共有する)4つのマスに書かれている数を、小さい順に出力してください。
※法則は図から読み取ってください

【入出力】
入力は
12
のように、普通に 10進数で来ます。

出力は、
3,11,13,29
のような感じです。

4つの数をコンマ区切りで昇順に並べてください。

【例】
入力     出力
12     3,11,13,29
34     15,33,35,61
77     46,76,78,116

【補足】

    不正な入力に対処する必要はありません。
    入力は、1以上、1000以下です。

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

規則性を利用してプログラム

入力は、1以上、1000以下」の意味は何なのだろうか?上限は幾つだろうと計算時間はほとんど瞬殺。

ru = function(n) 4 * n^2 +  4 * n + 1 # 右上 1,9,25,49,81,... の数列 n=0,1,2,3,4,...
lu = function(n) 4 * n^2 +  6 * n + 3 # 左上 1,3,13,31,57,... の数列
ld = function(n) 4 * n^2 +  8 * n + 5 # 左下 1,5,17,37,65,... の数列
rd = function(n) 4 * n^2 + 10 * n + 7 # 右下 1,7,21,43,73,... の数列
up    = function(n) 8 * n + 9  # 上のサイクルへの差分 例えば 2(サイクル0) から 11(サイクル1) への差分
left  = function(n) 8 * n + 11 # 左のサイクルへの差分 例えば 3(サイクル0) から 14(サイクル1) への差分
down  = function(n) 8 * n + 13 # 下のサイクルへの差分 例えば 6(サイクル0) から 19(サイクル1) への差分
right = function(n) 8 * n + 15 # 右のサイクルへの差分 例えば 8(サイクル0) から 23(サイクル1) への差分

f = function(N) {
    n = 0 # どのサイクルにあるか検出s
    repeat { # サイクルは (1-8), (9-24), (25-48), ... をサイクル 0, 1, 2, ... とする
        if (N >= ru(n) && ru(n + 1) > N) {
            break
        }
        n = n + 1
    }
    RU = ru(n) # サイクルの開始点
    LU = lu(n) # サイクルの左折点(左向きから下向きへ)
    LD = ld(n) # サイクルの左折点(下向きから右向きへ)
    RD = rd(n) # サイクルの左折点(右向きから上向きへ)
    a = if (N == 1) {                                    # N = 1 は特別
        N + c(up(-1), left(-1), down(-1), right(-1))     # (2, 4, 6, 8)
    } else if (N == RU) {                                # N = RU = 49
        c(ru(n - 1) + 1, N - 1, N + 1, ru(n + 1) - 1)    # (26, 48, 50, 80)
    } else if (N == RU + 1) {                            # N = RU+1 = 50
        c(N - 1, N + 1, ru(n + 1), ru(n + 1) + 2)        # (49, 51, 81, 83)
    } else if (N > RU + 1 && LU - 1 > N) {               # N = 51 thru 55
        c(N - up(n - 1), N - 1, N + 1, N + up(n))        # N = 51; (26, 50, 52, 84)
    } else if (N == LU - 1) {                            # N = 56
        c(lu(n - 1), N - 1, N + 1, lu(n + 1) - 2)        # (31, 55, 57, 89)
    } else if (N == LU) {                                # N = LU = 57
        c(N - 1, N + 1, lu(n + 1) - 1, lu(n + 1) + 1)    # (56, 58, 90, 92)
    } else if (N > LU && LD > N) {                       # N = 58 thru 64
        c(N - left(n - 1), N - 1, N + 1, N + left(n))    # N = 58; (31, 57, 59, 93)
    } else if (N == LD) {                                # N = 65
        c(N - 1, N + 1, ld(n + 1) - 1, ld(n + 1) + 1)    # (64, 66, 100, 102)
    } else if (N > LD && RD > N) {                       # N = 66 thru 72
        c(N - down(n - 1), N - 1, N + 1, N + down(n))    # N = 66; (37, 65, 67, 103)
    } else if (N == RD) {                                # N = 73
        c(N - 1, N + 1, rd(n + 1) - 1, rd(n + 1) + 1)    # (72, 74, 110, 112)
    } else if (N > RD && ru(n + 1) > N) {                # N = 74 thru 81
        c(N - right(n - 1), N - 1, N + 1, N + right(n))  # n = 74; (43,73,75,113)
    }
    cat(a, sep = ",")
}

> f(1)
2,4,6,8
> f(2)
1,3,9,11
> f(3)
2,4,12,14
> f(4)
1,3,5,15
> f(5)
4,6,16,18
> f(6)
1,5,7,19
> f(7)
6,8,20,22
> f(8)
1,7,9,23
> f(9)
2,8,10,24
> f(10)
9,11,25,27
> f(100000)
98739,99999,100001,101269

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 「ルーム・アンド・ルーフ」問題 | トップ | 現地で使いやすい両替 »
最新の画像もっと見る

コメントを投稿

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