CodeIQ MAGAZINECodeIQ MAGAZINE

【謎解きプログラム】正しいコードは?【一人すごろく】解答と解説

2017.12.27 Category:CodeIQ問題解説・リーダーボード Tag:

  • 6
  • このエントリーをはてなブックマークに追加

簡単なプログラムにちなんだ謎を解く「謎解きプログラム」。

あなたは見事、謎を解けましたか? というわけで、出題者の柳井さんによる解答と解説をどうぞ!
by CodeIQ運営事務局

【謎解きプログラム】正しいコードは?【一人すごろく】

本問題は、表題のテーマで、プログラムにちなんだ謎を解くというものでした。

それでは以下、各問題とその解答を見ていきましょう。

問題のオープニング

ある日、出社すると、あなたのPCのログイン画面に、謎の挑戦状が表示されていた。

「24時間以内にが解けない場合は、このPCのデータは消失する。

 は、あなたが真のプログラマーなら解けるものだ」

これは挑戦状ではなく脅迫状だ!

そこには、見たことのない謎が掲載されていた。

あなたは歴戦のプログラマーとして、データを救うために、この謎に挑むことになった。

問題1

あなたは、抽象化された「すごろく」の動作を、プログラムで書くことになりました。

示されるコードは、C、Java、JavaScriptなどのプログラミング言語で見られるような、一般的な書き方のコードです。

要求動作を満たすコードを、選択肢から1つ選んで下さい。

変数posはマス目の位置、diceはサイコロの目を表します。関数printlnは出力、関数getDiceは1~6の範囲の整数をランダムで戻します。

● 要求動作

100マス目に到達したらゴール(折り返して戻ったりしない)

● コードと選択肢

// コード
pos = 1;
while(true) {
    dice = getDice();
    pos += dice;
    println("dice " + dice + ", pos " + pos);

    if (pos == 100) {break;}    // 選択肢1
    if (pos >= 100) {break;}    // 選択肢2
    if (pos < 100)  {break;}    // 選択肢3
}
println("GOAL!");

● 答え

「pos = 1;」と、posは1からスタートしています。そのため、100マス目は、posが100の時になります。

そのため、posが100以上の場合(折り返さないので通り過ぎてもよい)にゴールと見なせば、よいことになります。

この条件を満たす判定は、「pos >= 100」なので、答えは選択肢2の「if (pos >= 100) {break;}」になります。

以下、コードを、JavaScriptで処理したものを掲載します。冒頭の変数や関数は、問題2以降も共通です。また、無限に終わらないコードを防ぐために、デバッグ用の終了処理を加えています。

● 確認コード

// 共通
var pos, dice;
var println = console.log;
var getDice = function() {
    return Math.floor(Math.random() * 6) + 1;
}

//----------------------------------------
// 100マス目に到達したらゴール

// 選択肢1 ×
console.log('選択肢1');
(function() {
    pos = 1;
    while(true) {
        dice = getDice();
        pos += dice;
        println("dice " + dice + ", pos " + pos);

        if (pos == 100) {break}
if (pos >= 120) {break}    // デバッグ用
    }
    println("GOAL!");
})();
console.log('-'.repeat(20));

// 選択肢2 ○
console.log('選択肢2');
(function() {
    pos = 1;
    while(true) {
        dice = getDice();
        pos += dice;
        println("dice " + dice + ", pos " + pos);

        if (pos >= 100) {break}
    }
    println("GOAL!");
})();
console.log('-'.repeat(20));

// 選択肢3 ×
console.log('選択肢3');
(function() {
    pos = 1;
    while(true) {
        dice = getDice();
        pos += dice;
        println("dice " + dice + ", pos " + pos);

        if (pos < 100) {break}
    }
    println("GOAL!");
})();
console.log('-'.repeat(20));

● 出力結果(ランダムで動くので一例)

選択肢1
dice 2, pos 3
dice 2, pos 5
dice 4, pos 9
dice 4, pos 13
dice 3, pos 16
dice 6, pos 22
dice 6, pos 28
dice 6, pos 34
dice 2, pos 36
dice 3, pos 39
dice 5, pos 44
dice 5, pos 49
dice 6, pos 55
dice 2, pos 57
dice 3, pos 60
dice 3, pos 63
dice 1, pos 64
dice 3, pos 67
dice 6, pos 73
dice 5, pos 78
dice 3, pos 81
dice 6, pos 87
dice 5, pos 92
dice 1, pos 93
dice 2, pos 95
dice 6, pos 101
dice 3, pos 104
dice 2, pos 106
dice 5, pos 111
dice 6, pos 117
dice 6, pos 123
GOAL!
--------------------
選択肢2
dice 3, pos 4
dice 3, pos 7
dice 1, pos 8
dice 6, pos 14
dice 4, pos 18
dice 6, pos 24
dice 2, pos 26
dice 3, pos 29
dice 4, pos 33
dice 5, pos 38
dice 4, pos 42
dice 3, pos 45
dice 1, pos 46
dice 2, pos 48
dice 2, pos 50
dice 2, pos 52
dice 6, pos 58
dice 4, pos 62
dice 6, pos 68
dice 2, pos 70
dice 6, pos 76
dice 5, pos 81
dice 5, pos 86
dice 3, pos 89
dice 3, pos 92
dice 2, pos 94
dice 6, pos 100
GOAL!
--------------------
選択肢3
dice 1, pos 2
GOAL!
--------------------

問題2

あなたは、抽象化された「すごろく」の動作を、プログラムで書くことになりました。

示されるコードは、C、Java、JavaScriptなどのプログラミング言語で見られるような、一般的な書き方のコードです。

要求動作を満たすコードを、選択肢から1つ選んで下さい。

変数posはマス目の位置、diceはサイコロの目を表します。関数printlnは出力、関数getDiceは1~6の範囲の整数をランダムで戻します。

● 要求動作

7の倍数のマスに停まると、3マス進む。

● コードと選択肢

// コード
pos = 1;
while(true) {
    dice = getDice();
    pos += dice;
    println("dice " + dice + ", pos " + pos);

    if (pos % 7 == 0) {pos = +3;}    // 選択肢1
    if (pos == 7) {dice += 3;}       // 選択肢2
    if (pos % 7 == 0) {pos += 3;}    // 選択肢3

    if (pos >= 100) {break;}
}
println("GOAL!");

● 答え

問題2を見ると、実は問題1の答えが書いてあります。見落としていなければ、問題1の答え合わせがここでできます。

では、問題2です。要求動作は「7の倍数のマスに停まると、3マス進む」です。この条件を満たすには、「7の倍数のマスに停まったかの判定」と「3マス進む処理」の2つを満たさなければなりません。

7の倍数かどうかは、7の剰余を取り(7で割った余りを見て)、その値が0か確認すればよいです。0ならば7の倍数になります。この条件を満たす判定式は「pos % 7 == 0」です。

次に3マス進む処理です。「+= 3」で、変数に値を加えることで、3マス進む処理を表現できます。

この際、posとdiceのどちらに値を加えてもよいように思えるかもしれません。しかし、注意が必要です。「pos += dice;」(位置にダイス目を足す処理)は、選択肢1~3よりも前に行なわれています。そのため、位置に3を足さなければ、意図する動作にはなりません。

というわけで答えは、選択肢3の「if (pos % 7 == 0) {pos += 3}」になります。

以下、コードを、JavaScriptで処理したものを掲載します。冒頭の変数や関数は、問題1と共通です。

● 確認コード

// 共通
var pos, dice;
var println = console.log;
var getDice = function() {
    return Math.floor(Math.random() * 6) + 1;
}

//----------------------------------------
// 7の倍数のマスに停まると、3マス進む。

// 選択肢1 ×
console.log('選択肢1');
(function() {
    pos = 1;
    while(true) {
        dice = getDice();
        pos += dice;
        println("dice " + dice + ", pos " + pos);

        if (pos % 7 == 0) {pos = +3; println("***dice " + dice + ", pos " + pos)}

        if (pos >= 100) {break}
    }
    println("GOAL!");
})();
console.log('-'.repeat(20));

// 選択肢2 ×
console.log('選択肢2');
(function() {
    pos = 1;
    while(true) {
        dice = getDice();
        pos += dice;
        println("dice " + dice + ", pos " + pos);

        if (pos == 7) {dice += 3; println("***dice " + dice + ", pos " + pos)}

        if (pos >= 100) {break}
    }
    println("GOAL!");
})();
console.log('-'.repeat(20));

// 選択肢3 ○
console.log('選択肢3');
(function() {
    pos = 1;
    while(true) {
        dice = getDice();
        pos += dice;
        println("dice " + dice + ", pos " + pos);

        if (pos % 7 == 0) {pos += 3; println("***dice " + dice + ", pos " + pos)}

        if (pos >= 100) {break}
    }
    println("GOAL!");
})();
console.log('-'.repeat(20));

● 出力結果(ランダムで動くので一例)

選択肢1
dice 4, pos 5
dice 1, pos 6
dice 6, pos 12
dice 4, pos 16
dice 6, pos 22
dice 6, pos 28
***dice 6, pos 3
dice 4, pos 7
***dice 4, pos 3
dice 1, pos 4
dice 6, pos 10
dice 3, pos 13
dice 5, pos 18
dice 5, pos 23
dice 3, pos 26
dice 2, pos 28
(何度も3マス目に戻って長いので省略)
dice 1, pos 4
dice 5, pos 9
dice 2, pos 11
dice 4, pos 15
dice 5, pos 20
dice 6, pos 26
dice 3, pos 29
dice 2, pos 31
dice 6, pos 37
dice 4, pos 41
dice 6, pos 47
dice 6, pos 53
dice 6, pos 59
dice 1, pos 60
dice 1, pos 61
dice 5, pos 66
dice 2, pos 68
dice 5, pos 73
dice 5, pos 78
dice 3, pos 81
dice 4, pos 85
dice 4, pos 89
dice 6, pos 95
dice 5, pos 100
GOAL!
--------------------
選択肢2
dice 6, pos 7
***dice 9, pos 7
dice 3, pos 10
dice 5, pos 15
dice 6, pos 21
dice 4, pos 25
dice 5, pos 30
dice 6, pos 36
dice 1, pos 37
dice 1, pos 38
dice 3, pos 41
dice 5, pos 46
dice 5, pos 51
dice 5, pos 56
dice 1, pos 57
dice 4, pos 61
dice 5, pos 66
dice 6, pos 72
dice 6, pos 78
dice 5, pos 83
dice 2, pos 85
dice 2, pos 87
dice 6, pos 93
dice 3, pos 96
dice 5, pos 101
GOAL!
--------------------
選択肢3
dice 5, pos 6
dice 3, pos 9
dice 6, pos 15
dice 2, pos 17
dice 6, pos 23
dice 1, pos 24
dice 5, pos 29
dice 2, pos 31
dice 1, pos 32
dice 2, pos 34
dice 4, pos 38
dice 1, pos 39
dice 3, pos 42
***dice 3, pos 45
dice 3, pos 48
dice 6, pos 54
dice 1, pos 55
dice 6, pos 61
dice 2, pos 63
***dice 2, pos 66
dice 5, pos 71
dice 4, pos 75
dice 5, pos 80
dice 2, pos 82
dice 6, pos 88
dice 1, pos 89
dice 2, pos 91
***dice 2, pos 94
dice 2, pos 96
dice 2, pos 98
***dice 2, pos 101
GOAL!
--------------------

問題3

あなたは、抽象化された「すごろく」の動作を、プログラムで書くことになりました。

示されるコードは、C、Java、JavaScriptなどのプログラミング言語で見られるような、一般的な書き方のコードです。

要求動作を満たすコードを、選択肢から1つ選んで下さい。

変数posはマス目の位置、diceはサイコロの目を表します。関数printlnは出力、関数getDiceは1~6の範囲の整数をランダムで戻します。

● 要求動作

13の倍数のマスに停まると、スタートに戻る。

● コードと選択肢

// コード
pos = 1;
while(true) {
    dice = getDice();
    pos += dice;
    println("dice " + dice + ", pos " + pos);

    if (pos % 13 == 0) {pos = 0;}     // 選択肢1
    if (pos == 13) {dice = 0;}        // 選択肢2
    if (pos % 13 == 0) {pos = 1;}     // 選択肢3

    if (pos >= 100) {break;}
}
println("GOAL!");

● 答え

要求動作は「13の倍数のマスに停まると、スタートに戻る」です。この条件を満たすには、「13の倍数のマスに停まったかの判定」と「スタートに戻る処理」の2つを満たさなければなりません。

13の倍数かどうかは、7の倍数の判定と同じです。13の剰余を取り(13で割った余りを見て)、その値が0かを確認すればよいです。0ならば13の倍数になります。この条件を満たす判定式は「pos % 13 == 0」です。

次にスタートに戻る処理です。「pos = 0」ではなく「pos = 1」です。マスの初期値は1なので、1にしなければなりません。プログラマーだと、逆に「pos = 0」を選んでしまうかもしれません。

というわけで答えは、選択肢3の「if (pos % 13 == 0) {pos = 1}」になります。

以下、コードを、JavaScriptで処理したものを掲載します。冒頭の変数や関数は、問題1と共通です。

● 確認コード

// 共通
var pos, dice;
var println = console.log;
var getDice = function() {
    return Math.floor(Math.random() * 6) + 1;
}

//----------------------------------------
// 13の倍数のマスに停まると、スタートに戻る。

// 選択肢1 ×
console.log('選択肢1');
(function() {
    pos = 1;
    while(true) {
        dice = getDice();
        pos += dice;
        println("dice " + dice + ", pos " + pos);

        if (pos % 13 == 0) {pos = 0; println("***dice " + dice + ", pos " + pos)}

        if (pos >= 100) {break}
    }
    println("GOAL!");
})();
console.log('-'.repeat(20));

// 選択肢2 ×
console.log('選択肢2');
(function() {
    pos = 1;
    while(true) {
        dice = getDice();
        pos += dice;
        println("dice " + dice + ", pos " + pos);

        if (pos == 13) {dice = 0; println("***dice " + dice + ", pos " + pos)}

        if (pos >= 100) {break}
    }
    println("GOAL!");
})();
console.log('-'.repeat(20));

// 選択肢3 ○
console.log('選択肢3');
(function() {
    pos = 1;
    while(true) {
        dice = getDice();
        pos += dice;
        println("dice " + dice + ", pos " + pos);

        if (pos % 13 == 0) {pos = 1; println("***dice " + dice + ", pos " + pos)}

        if (pos >= 100) {break}
    }
    println("GOAL!");
})();
console.log('-'.repeat(20));

● 出力結果(ランダムで動くので一例)

選択肢1
dice 2, pos 3
dice 2, pos 5
dice 6, pos 11
dice 1, pos 12
dice 4, pos 16
dice 2, pos 18
dice 3, pos 21
dice 6, pos 27
dice 4, pos 31
dice 3, pos 34
dice 3, pos 37
dice 4, pos 41
dice 2, pos 43
dice 4, pos 47
dice 1, pos 48
dice 3, pos 51
dice 4, pos 55
dice 1, pos 56
dice 2, pos 58
dice 6, pos 64
dice 1, pos 65
***dice 1, pos 0
dice 6, pos 6
dice 4, pos 10
dice 3, pos 13
***dice 3, pos 0
dice 3, pos 3
dice 4, pos 7
dice 5, pos 12
dice 3, pos 15
dice 2, pos 17
dice 3, pos 20
dice 2, pos 22
dice 3, pos 25
dice 3, pos 28
dice 3, pos 31
dice 4, pos 35
dice 5, pos 40
dice 6, pos 46
dice 2, pos 48
dice 2, pos 50
dice 2, pos 52
***dice 2, pos 0
dice 1, pos 1
dice 2, pos 3
dice 3, pos 6
dice 1, pos 7
dice 1, pos 8
dice 2, pos 10
dice 4, pos 14
dice 3, pos 17
dice 2, pos 19
dice 4, pos 23
dice 6, pos 29
dice 6, pos 35
dice 6, pos 41
dice 3, pos 44
dice 2, pos 46
dice 3, pos 49
dice 1, pos 50
dice 5, pos 55
dice 1, pos 56
dice 4, pos 60
dice 2, pos 62
dice 4, pos 66
dice 1, pos 67
dice 2, pos 69
dice 6, pos 75
dice 2, pos 77
dice 2, pos 79
dice 2, pos 81
dice 6, pos 87
dice 2, pos 89
dice 5, pos 94
dice 3, pos 97
dice 3, pos 100
GOAL!
--------------------
選択肢2
dice 2, pos 3
dice 2, pos 5
dice 2, pos 7
dice 3, pos 10
dice 2, pos 12
dice 6, pos 18
dice 2, pos 20
dice 1, pos 21
dice 4, pos 25
dice 1, pos 26
dice 1, pos 27
dice 6, pos 33
dice 6, pos 39
dice 2, pos 41
dice 2, pos 43
dice 4, pos 47
dice 1, pos 48
dice 3, pos 51
dice 2, pos 53
dice 1, pos 54
dice 2, pos 56
dice 6, pos 62
dice 1, pos 63
dice 4, pos 67
dice 2, pos 69
dice 5, pos 74
dice 2, pos 76
dice 2, pos 78
dice 5, pos 83
dice 6, pos 89
dice 1, pos 90
dice 1, pos 91
dice 1, pos 92
dice 2, pos 94
dice 4, pos 98
dice 5, pos 103
GOAL!
--------------------
選択肢3
dice 2, pos 3
dice 4, pos 7
dice 6, pos 13
***dice 6, pos 1
dice 3, pos 4
dice 5, pos 9
dice 2, pos 11
dice 4, pos 15
dice 2, pos 17
dice 1, pos 18
dice 4, pos 22
dice 4, pos 26
***dice 4, pos 1
dice 3, pos 4
dice 2, pos 6
dice 1, pos 7
dice 6, pos 13
***dice 6, pos 1
dice 6, pos 7
dice 4, pos 11
dice 4, pos 15
dice 2, pos 17
dice 2, pos 19
dice 3, pos 22
dice 2, pos 24
dice 5, pos 29
dice 4, pos 33
dice 3, pos 36
dice 3, pos 39
***dice 3, pos 1
dice 6, pos 7
dice 4, pos 11
dice 5, pos 16
dice 3, pos 19
dice 6, pos 25
dice 3, pos 28
dice 1, pos 29
dice 3, pos 32
dice 1, pos 33
dice 1, pos 34
dice 3, pos 37
dice 5, pos 42
dice 6, pos 48
dice 6, pos 54
dice 3, pos 57
dice 5, pos 62
dice 3, pos 65
***dice 3, pos 1
dice 2, pos 3
dice 5, pos 8
dice 2, pos 10
dice 4, pos 14
dice 6, pos 20
dice 4, pos 24
dice 6, pos 30
dice 3, pos 33
dice 4, pos 37
dice 1, pos 38
dice 2, pos 40
dice 2, pos 42
dice 2, pos 44
dice 4, pos 48
dice 4, pos 52
***dice 4, pos 1
dice 5, pos 6
dice 1, pos 7
dice 6, pos 13
***dice 6, pos 1
dice 6, pos 7
dice 1, pos 8
dice 5, pos 13
***dice 5, pos 1
dice 4, pos 5
dice 1, pos 6
dice 4, pos 10
dice 6, pos 16
dice 2, pos 18
dice 3, pos 21
dice 5, pos 26
***dice 5, pos 1
dice 2, pos 3
dice 6, pos 9
dice 1, pos 10
dice 1, pos 11
dice 1, pos 12
dice 5, pos 17
dice 4, pos 21
dice 3, pos 24
dice 2, pos 26
***dice 2, pos 1
dice 2, pos 3
dice 6, pos 9
dice 2, pos 11
dice 5, pos 16
dice 5, pos 21
dice 6, pos 27
dice 1, pos 28
dice 3, pos 31
dice 1, pos 32
dice 3, pos 35
dice 6, pos 41
dice 2, pos 43
dice 4, pos 47
dice 6, pos 53
dice 5, pos 58
dice 6, pos 64
dice 1, pos 65
***dice 1, pos 1
dice 2, pos 3
dice 4, pos 7
dice 6, pos 13
***dice 6, pos 1
dice 4, pos 5
dice 5, pos 10
dice 5, pos 15
dice 3, pos 18
dice 6, pos 24
dice 3, pos 27
dice 5, pos 32
dice 4, pos 36
dice 4, pos 40
dice 4, pos 44
dice 4, pos 48
dice 6, pos 54
dice 4, pos 58
dice 6, pos 64
dice 2, pos 66
dice 1, pos 67
dice 5, pos 72
dice 2, pos 74
dice 2, pos 76
dice 6, pos 82
dice 4, pos 86
dice 2, pos 88
dice 2, pos 90
dice 3, pos 93
dice 2, pos 95
dice 1, pos 96
dice 6, pos 102
GOAL!
--------------------

CodeIQ運営事務局より

柳井さん、ありがとうございました!
現在、柳井さんの最新問題が出題中です。
ぜひ挑戦してみてくださいね!

  • 6
  • このエントリーをはてなブックマークに追加

■関連記事

【謎解きプログラム】どう防ぐ?【無限ループ】解答と解説... 【謎解きプログラム】どう防ぐ?【無限ループ】 本問題は、表題のテーマで、プログラムにちなんだ謎を解くというものでした。 それでは以下、各問題とその解答を見ていきましょう。 問題のオープニング ある日、出社すると、あなたのPCのログイン画面に、謎の挑戦状が表示されていた。 「24時間以内に謎...
数学の問題をプログラミングで解こう!「タワー・ビルディング」問題解説... 問題のおさらい A を一辺が 1 の立方体のブロックとし、B を縦が 1、横が 1、高さが 2 の直方体のブロックとします。 (下は横から見た図です。) 自然数 n, a, b に対し、A を最大 a 個、B を最大 b 個使って、縦が 1、横が 1、高さが n の直方体の塔を作ります。 こ...
数学の問題をプログラミングで解こう!「ペア・ドロップ」問題解説... 問題のおさらい n を自然数とします。1 から n までの自然数が 1 つずつ書かれた n 枚のカードが 2 組あります。 これら 2n 枚のカードをよく混ぜ、A と B の 2 人に n 枚ずつ配ります。 A と B は、それぞれ自分の持ち札の中に番号が一致するカードがあればその 2 枚を捨...
【謎解きプログラム】中身はどうなる?【出し入れ】解答と解説... 【謎解きプログラム】中身はどうなる?【出し入れ】 本問題は、表題のテーマで、プログラムにちなんだ謎を解くというものでした。 それでは以下、各問題とその解答を見ていきましょう。 問題のオープニング ある日、出社すると、あなたのPCのログイン画面に、謎の挑戦状が表示されていた。 「24時間以内...
【謎解きプログラム】座標の移動【Matrix】解答と解説... 【謎解きプログラム】座標の移動【Matrix】 本問題は、表題のテーマで、プログラムにちなんだ謎を解くというものでした。 それでは以下、各問題とその解答を見ていきましょう。 問題のオープニング ある日、出社すると、あなたのPCのログイン画面に、謎の挑戦状が表示されていた。 「24時間以内に...
数学の問題をプログラミングで解こう!「ストレート・ラインズ」問題解説... 問題のおさらい 2 以上の自然数 n に対し、n×n の格子状に並んだ点を考えます。 これらの点のうちちょうど 2 個の点を通る直線の数を F(n) と定義します。 例えば F(2)=6 です。題意を満たす直線は以下の 6 通りです。 また、F(3)=12 です。題意を満たす直線は以下の...

今週のPickUPレポート

新着記事

週間ランキング

CodeIQとは

CodeIQ(コードアイキュー)とは、自分の実力を知りたいITエンジニア向けの、実務スキル評価サービスです。

CodeIQご利用にあたって
関連サイト
codeiq

リクルートグループサイトへ