ガジェット通信

見たことのないものを見に行こう

【謎解きプログラム】カードを並べて悪魔を消せ!【正規表現】解答と解説

DATE:
  • ガジェット通信を≫

【謎解きプログラム】カードを並べて悪魔を消せ!【正規表現】

本問題は、「カードを並び替えて、悪魔を消せ!」というテーマで、プログラムにちなんだ謎を解くというものでした。

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

問題のオープニング

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

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

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

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

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

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

説明

画面には、「A(Angel)」と「D(Devil)」の文字が横一列に並んでいます。

その下には、文字や正規表現の記号が書かれたカードが並んでいます(正規表現はJavaやJavaScript、rubyでテストしています)。

このカードを上手く並べ替えて、空文字への置換で「D(Devil)」だけを全て消してください。並べ方は、選択肢から選んでください。

問題1

文字列:DDA
カード:..^

// 選択肢
..^
.^.
^..

「^」は、先頭を表します。「.」は、任意の一文字を表します。

問題の文字列では、悪魔を表す「D」が、先頭の2文字分並んでいます。

そのため、「先頭」「任意の一文字」「任意の一文字」とカードを並べると、「D」を全て消すことができます。

というわけで、3番目の選択肢の『^..』が答えになります。

Javaサンプル

以下、サンドボックス(言語は「Java8」)で、実行確認できるコードを示します。コード欄に、下記のコードをコピペして、INPUTは空で、RUNボタンを押してください。

// 参考コード
import java.util.regex.Pattern;
import java.util.Arrays;

class Main{
public static void main(String[]args) {
String q = “DDA”;
String[] arr = {“..^”, “.^.”, “^..”};
Arrays.stream(arr).forEach(itm -> {
try {
Pattern p = Pattern.compile(itm);
System.out.println(itm + ” ” + p.matcher(q).replaceFirst(“”));
} catch(java.util.regex.PatternSyntaxException e) {
System.out.println(itm + ” ” + q);
}
});
}
}

// 出力
..^ DDA
.^. DDA
^.. A

JavaScriptサンプル

以下、ブラウザのコンソールで確認できるように、JavaScriptのコードを示します。

// 参考コード
var q = “DDA”;
var arr = [“..^”, “.^.”, “^..”];

arr.forEach(function(x) {
try {
var re = new RegExp(x);
console.log(x + ” ” + q.replace(re, “”));
} catch(e) {
console.log(x + ” ” + q);
}
});

// 出力
..^ DDA
.^. DDA
^.. A

Rubyサンプル

以下、サンドボックス(言語は「Ruby」)で、実行確認できるコードを示します。コード欄に、下記のコードをコピペして、INPUTは空で、RUNボタンを押してください。

// 参考コード
q = “DDA”
arr = [“..^”, “.^.”, “^..”]
arr.each{|x|
begin
puts x + ” ” + q.sub(Regexp.new(x), “”)
rescue
puts x + ” ” + q
end
}

// 出力
..^ DDA
.^. DDA
^.. A

問題2

文字列:AADD
カード:A+^[]

// 選択肢
^[A+]
^[A]+
[^A+]
[^A]+
^A+[]

「[^~]」は、~以外の文字を表します。また「S+」は、Sを1回以上繰り返すことを表します。

カードを組み合わせると、「[^A]」で「A以外の文字」、つまり「D」を表せます。そして、その「A以外の文字」を「+」で繰り返すことで、「DD」と並んだ文字を対象にできます。

というわけで、4番目の選択肢の『[^A]+』が答えになります。

Javaサンプル

以下、サンドボックス(言語は「Java8」)で、実行確認できるコードを示します。コード欄に、下記のコードをコピペして、INPUTは空で、RUNボタンを押してください。

// 参考コード
import java.util.regex.Pattern;
import java.util.Arrays;

class Main{
public static void main(String[]args) {
String q = “AADD”;
String[] arr = {“^[A+]”, “^[A]+”, “[^A+]”, “[^A]+”, “^A+[]”};
Arrays.stream(arr).forEach(itm -> {
try {
Pattern p = Pattern.compile(itm);
System.out.println(itm + ” ” + p.matcher(q).replaceFirst(“”));
} catch(java.util.regex.PatternSyntaxException e) {
System.out.println(itm + ” ” + q);
}
});
}
}

// 出力
^[A+] ADD
^[A]+ DD
[^A+] AAD
[^A]+ AA
^A+[] AADD

JavaScriptサンプル

以下、ブラウザのコンソールで確認できるように、JavaScriptのコードを示します。

// 参考コード
var q = “AADD”;
var arr = [“^[A+]”, “^[A]+”, “[^A+]”, “[^A]+”, “^A+[]”];

arr.forEach(function(x) {
try {
var re = new RegExp(x);
console.log(x + ” ” + q.replace(re, “”));
} catch(e) {
console.log(x + ” ” + q);
}
});

// 出力
^[A+] ADD
^[A]+ DD
[^A+] AAD
[^A]+ AA
^A+[] AADD

Rubyサンプル

以下、サンドボックス(言語は「Ruby」)で、実行確認できるコードを示します。コード欄に、下記のコードをコピペして、INPUTは空で、RUNボタンを押してください。

// 参考コード
q = “AADD”
arr = [“^[A+]”, “^[A]+”, “[^A+]”, “[^A]+”, “^A+[]”]
arr.each{|x|
begin
puts x + ” ” + q.sub(Regexp.new(x), “”)
rescue
puts x + ” ” + q
end
}

// 出力
^[A+] ADD
^[A]+ DD
[^A+] AAD
[^A]+ AA
^A+[] AADD

問題3

文字列:ADDDA
カード:()+1.

// 選択肢
.+()1
.+(1)
.+(1)
.(1)+
(.)1+

「(~)」で~を選択して、後方参照を可能にします。また、「1」は先に後方参照可能にした文字列(最初の括弧内の文字列)を指します。

「.」は任意の1文字を表します。また「S+」は、Sを1回以上繰り返すことを表します。

カードを組み合わせると、「(.)」で任意の1文字を選択して、後方参照を可能にします。「1」は先に後方参照可能にした文字列を指します。そのため「(.)1」で、連続した2文字を表せます。

さらに「1+」で、「1」(先に後方参照可能にした文字列)を1回以上繰り返します。そのため、「DDD」を選択できます。

というわけで、5番目の選択肢の『(.)1+』が答えになります。

Javaサンプル

以下、サンドボックス(言語は「Java8」)で、実行確認できるコードを示します。コード欄に、下記のコードをコピペして、INPUTは空で、RUNボタンを押してください。

// 参考コード
import java.util.regex.Pattern;
import java.util.Arrays;

class Main{
public static void main(String[]args) {
String q = “ADDDA”;
String[] arr = {“\.+()1″, “\.+(1)”, “.\+(1)”, “.(1)\+”, “(.)\1+”};
Arrays.stream(arr).forEach(itm -> {
try {
Pattern p = Pattern.compile(itm);
System.out.println(itm + ” ” + p.matcher(q).replaceFirst(“”));
} catch(java.util.regex.PatternSyntaxException e) {
System.out.println(itm + ” ” + q);
}
});
}
}

// 出力
.+()1 ADDDA
.+(1) ADDDA
.+(1) ADDDA
.(1)+ ADDDA
(.)1+ AA

JavaScriptサンプル

以下、ブラウザのコンソールで確認できるように、JavaScriptのコードを示します。

// 参考コード
var q = “ADDDA”;
var arr = [“\.+()1″, “\.+(1)”, “.\+(1)”, “.(1)\+”, “(.)\1+”];

arr.forEach(function(x) {
try {
var re = new RegExp(x);
console.log(x + ” ” + q.replace(re, “”));
} catch(e) {
console.log(x + ” ” + q);
}
});

// 出力
.+()1 ADDDA
.+(1) ADDDA
.+(1) ADDDA
.(1)+ ADDDA
(.)1+ AA

Rubyサンプル

以下、サンドボックス(言語は「Ruby」)で、実行確認できるコードを示します。コード欄に、下記のコードをコピペして、INPUTは空で、RUNボタンを押してください。

// 参考コード
q = “ADDDA”
arr = [“\.+()1″, “\.+(1)”, “.\+(1)”, “.(1)\+”, “(.)\1+”]
arr.each{|x|
begin
puts x + ” ” + q.sub(Regexp.new(x), “”)
rescue
puts x + ” ” + q
end
}

// 出力
.+()1 ADDDA
.+(1) ADDDA
.+(1) ADDDA
.(1)+ ADDDA
(.)1+ AA

CodeIQ運営事務局より

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

カテゴリー : デジタル・IT タグ :
CodeIQ MAGAZINEの記事一覧をみる ▶
  • 誤字を発見した方はこちらからご連絡ください。
  • ガジェット通信編集部への情報提供はこちらから
  • 記事内の筆者見解は明示のない限りガジェット通信を代表するものではありません。

TOP