CodeIQ MAGAZINECodeIQ MAGAZINE

【謎解きプログラム】どう比較する?【ソート】解答と解説

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

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

言語不問で、プログラムにちなんだ謎を解く「謎解きプログラム」。

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

【謎解きプログラム】どう比較する?【ソート】

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

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

問題のオープニング

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

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

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

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

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

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

問題1

配列のソートは、プログラムでよく見られる処理です。その際、ソートの比較を関数で指定して、並べ替えを制御する方法が、よく用いられます。

以下、プログラムはJavaScriptで書いていますが、内容自体は汎用的なものです。

下記のような入力と出力が行なわれる際、ソートの比較を行なう関数は、選択肢1~3のうち、どのような内容になるでしょうか?

0, 2, 3, 5, 6, 7, 8, 4, 1, 9    // 入力
9, 8, 7, 6, 5, 4, 3, 2, 1, 0    // 出力
// プログラム
var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    // 選択肢のコードは、ここに入る
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力
// 選択肢1
res = b + a;

// 選択肢2
res = b - a;

// 選択肢3
res = b * a; 

以下は、参考用のJavaScriptの数値のソートです。

// 数値のソート
var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {return a - b});   // ソート
console.log(a.join(', '));   // 出力
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

多くのプログラミング言語では、配列のソートを行なう際に、Comparator(コンパレーター)などと呼ばれる、比較を専門に行なう関数を引数に取れるようになっています。そして、この関数の中で、どちらの要素が前で、どちらの要素が後かを判定し、順番を並べ替えます。

参考として挙げているJavaScriptのソートでは、a, bの2つの値を引数に取る関数(compareFunction)が、sort関数の引数として設定されています。

この引数の関数では、0未満の値を戻すと、aをbより前に移動します。0の場合は移動なし。0より大きい場合は、bをaより前に移動します。

上記では、2つの引数a, bを使い、「a – b」の計算結果を戻すことで、昇順で出力されています。「a – b」の計算を行なうことで、0未満の値、0、0より大きい値、が得られるわけです。

問題は、降順で出力されていますので、「a – b」とは逆の順番になっています。

そのため、「b – a」の計算結果を戻せばよいことになります。

というわけで、2番目の選択肢『res = b – a;』が答えになります。

以下、Webブラウザのコンソールで実行可能な、JavaScriptのコードを掲載しておきます。

// サンプルコード
var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    res = b + a;    // 選択肢のコードは、ここに入る
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力


var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    res = b - a;    // 選択肢のコードは、ここに入る
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力


var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    res = b * a;    // 選択肢のコードは、ここに入る
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力
// 出力
9, 1, 4, 8, 7, 6, 5, 3, 2, 0
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
0, 9, 1, 4, 8, 7, 6, 5, 3, 2

問題2

配列のソートは、プログラムでよく見られる処理です。その際、ソートの比較を関数で指定して、並べ替えを制御する方法が、よく用いられます。

以下、プログラムはJavaScriptで書いていますが、内容自体は汎用的なものです。

下記のような入力と出力が行なわれる際、ソートの比較を行なう関数は、選択肢1~3のうち、どのような内容になるでしょうか?

32, 53, 25, 46, 97, 78, 84, 11, 69    // 入力
11, 32, 53, 84, 25, 46, 97, 78, 69    // 出力
// プログラム
var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    // 選択肢のコードは、ここに入る
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力
// 選択肢1 (乗算)
res = a*10 - b*10;

// 選択肢2 (除算)
res = a/10 - b/10;

// 選択肢3 (剰余)
res = a%10 - b%10;

以下は、参考用のJavaScriptの数値のソートです。

// 数値のソート
var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {return a - b});   // ソート
console.log(a.join(', '));   // 出力
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

出力結果の規則性を見つけられれば、すぐに解けます。下1桁でソートが行なわれています。

規則性を見つけられなくても、選択肢の計算の結果、どのようなソートが行なわれるかを考えれば、自ずと答えが出ます。

「選択肢1 (乗算)」と「選択肢2 (除算)」は、「(a – b) * 10」「(a – b) / 10」と変形可能です。これは、単なる昇順のソートと同じです。この2つを除外した、「選択肢3 (剰余)」が答えになります。

というわけで、3番目の選択肢『res = a%10 – b%10;』が答えになります。

以下、Webブラウザのコンソールで実行可能な、JavaScriptのコードを掲載しておきます。

// サンプルコード
var a = [32, 53, 25, 46, 97, 78, 84, 11, 69];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    res = a*10 - b*10;    // 選択肢のコードは、ここに入る
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力


var a = [32, 53, 25, 46, 97, 78, 84, 11, 69];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    res = a/10 - b/10;    // 選択肢のコードは、ここに入る
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力


var a = [32, 53, 25, 46, 97, 78, 84, 11, 69];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    res = a%10 - b%10;    // 選択肢のコードは、ここに入る
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力
// 出力
11, 25, 32, 46, 53, 69, 78, 84, 97
11, 25, 32, 46, 53, 69, 78, 84, 97
11, 32, 53, 84, 25, 46, 97, 78, 69

問題3

配列のソートは、プログラムでよく見られる処理です。その際、ソートの比較を関数で指定して、並べ替えを制御する方法が、よく用いられます。

以下、プログラムはJavaScriptで書いていますが、内容自体は汎用的なものです。

下記のような入力と出力が行なわれる際、ソートの比較を行なう関数は、選択肢1~3のうち、どのような内容になるでしょうか?

0, 2, 3, 5, 6, 7, 8, 4, 1, 9    // 入力
1, 3, 5, 7, 9, 0, 2, 4, 6, 8    // 出力
// プログラム
var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    // 選択肢のコードは、ここに入る
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力
// 選択肢1
res = a%2 - b%2;
if (res == 0) {res = a - b};

// 選択肢2
res = b%2 - a%2;
if (res == 0) {res = a - b};

// 選択肢3
res = b%2 - a%2;
if (res == 0) {res = b - a};

以下は、参考用のJavaScriptの数値のソートです。

// 数値のソート
var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {return a - b});   // ソート
console.log(a.join(', '));   // 出力
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

今回は、出力結果の規則性を、すぐには見つけられないかもしれません。

規則性を見つけられない場合は、選択肢の計算の結果がどのようになるのか、確認していけばよいです。

3つの選択肢の処理は、共通点が多いです。最初にa, bの、2の剰余を取って、引き算を行なっています。この部分では、偶数か奇数かという比較を行なっています。

次の行では、resの値が0、つまりどちらも偶数、あるいはどちらも奇数の場合に、a, bを比較して順番を決めています。

「選択肢1」では、最初に偶数を前に、奇数を後ろにして、次に昇順にソートしています。

「選択肢2」では、最初に奇数を前に、偶数を後ろにして、次に昇順にソートしています。

「選択肢3」では、最初に奇数を前に、偶数を後ろにして、次に降順にソートしています。

というわけで、2番目の選択肢『res = b%2 – a%2;』『if (res == 0) {res = a – b};』が答えになります。

以下、Webブラウザのコンソールで実行可能な、JavaScriptのコードを掲載しておきます。

// サンプルコード
var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    res = a%2 - b%2;
    if (res == 0) {res = a - b};
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力


var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    res = b%2 - a%2;
    if (res == 0) {res = a - b};
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力


var a = [0, 2, 3, 5, 6, 7, 8, 4, 1, 9];   // 入力
a.sort((a, b) => {   // ソート
    var res;
    res = b%2 - a%2;
    if (res == 0) {res = b - a};
    return res;   // 戻り値
});
console.log(a.join(', '));   // 出力
// 出力
0, 2, 4, 6, 8, 1, 3, 5, 7, 9
1, 3, 5, 7, 9, 0, 2, 4, 6, 8
9, 7, 5, 3, 1, 8, 6, 4, 2, 0

CodeIQ運営事務局より

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

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

■関連記事

【息抜き】カードを上手く並べよう【言語不問】解答と解説... 【息抜き】カードを上手く並べよう【言語不問】 本問題は、表題のテーマで、簡単なプログラムを書くものです。 それでは以下、問題とその解答を見ていきましょう。 問題 あなたは、11から99までの、89枚のカードを持っています。問題では、横幅と高さの整数が与えられます。この横幅と高さで作られるマス...
【コードミステリ】数字に隠されたメッセージ【言語不問】解答と解説... 【コードミステリ】数字に隠されたメッセージ【言語不問】 本問題は、表題のテーマで、簡単なプログラムを書くものです。 喜屋武ちあきさんによるCodeIQ MAGAZINEでのブックレビューに合わせて、『顔貌売人』(文藝春秋)とのコラボ問題として出題されたものです。 それでは以下、問題とその解...
数学の問題をプログラミングで解こう!「ディバイド・アウト」問題解説... 問題のおさらい 自然数 n と素数 p に対し、n の階乗(n!)を p でこれ以上割り切れなくなるまで繰り返し割り、その商をさらに p で割ったときの余りを F(n, p) と定義します。 例えば F(12, 5)=4 です。 12!(=479001600)は 5 で最大 2 回割ることができ...
【息抜き】ファイル名を作ろう【言語不問】解答と解説... 【息抜き】ファイル名を作ろう【言語不問】 本問題は、表題のテーマで、簡単なプログラムを書くものです。 それでは以下、問題とその解答を見ていきましょう。 問題 ファイルをディレクトリ内に作成する際、同じ名前のファイルがあると、末尾に数字を付けるなどして同じ名前にならないようにします。 こうし...
【夏のミステリー】殺人現場のコード 解答と解説... 【夏のミステリー】殺人現場のコード 本問題は、表題のテーマで、簡単なプログラムを書くものです。 それでは以下、問題とその解答を見ていきましょう。 問題 殺人現場にプログラマが倒れていて、途中までプログラムが書かれている。 「続きを書いて欲しい」 これはダイイングメッセージなのか? どう...
数学の問題をプログラミングで解こう!「キャンディ・アンド・チョコレート」問題解説... 問題のおさらい n 個のキャンディをグループに分けます。 グループの最大のキャンディの個数が k 個となるような分け方の数を F(n, k) と定義します。 例えば、F(8, 3)=5 です。このときの分け方を以下に示します。 なお個々のキャンディを区別せずに扱う点に注意してください。 同...

今週のPickUPレポート

新着記事

週間ランキング

CodeIQとは

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

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

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