問題
N 個の文字列 S_1, ... , S_N と、Q 個の文字列 T_1, ... , T_Q が与えられます。各 T_i について、以下の処理を行ってください。
・ S_j == T_i を満たす最小の j を出力する。ただし、そのような j が存在しない場合は -1 を出力する。
入力される値
N Q
S_1
S_2
...
S_N
T_1
T_2
...
T_Q
期待する出力
Q 行出力してください。i 行目には、S_j == T_i を満たす最小の j を出力してください。ただし、そのような j が存在しない場合は -1 を出力してください。
j_1
...
j_Q
入力例1
3 2
a
b
c
b
d
出力例1
2
-1
C#解答案
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var num = Array.ConvertAll(Console.ReadLine()?.Split(' ') ?? new string[0], int.Parse);
int N = num[0];
int Q = num[1];
List<string> searchList = new List<string>();
for (int i = 0; i < N; i++)
{
searchList.Add(Console.ReadLine() ?? "");
}
for (int j = 0; j < Q; j++)
{
string query = Console.ReadLine() ?? "";
int index = searchList.IndexOf(query);
Console.WriteLine(index == -1 ? -1 : index + 1);
}
}
}
解答案補足
解いたあとにChatGPTに添削してもらい、上記案が出てきた。
初学者につき、? ?? が良くわからずChatGPT先生に解説してもらったので補足とする。
1. ?(nullable 型)
C#では、?を使って値が「null(値がない状態)」になっても良いという型を作ることができます。たとえば、通常の整数(int)は必ず値が必要ですが、int?とすると、値があってもなくてもOKになります。
例:
int? myNumber = null; // 値がなくてもエラーにならない
このように?をつけることで、「この変数はnullでも大丈夫だよ」という意味を持たせることができます。
2. ??(null 合体演算子)
??は、もし左側の値がnullだったら、右側の値を使う、という意味です。これによって、nullが原因でエラーになるのを防ぎつつ、デフォルト値を設定できます。
たとえば、次のように使います。
string myText = null;
string result = myText ?? "デフォルトのテキスト";
Console.WriteLine(result); // "デフォルトのテキスト"と表示される
まず、myTextにはnullが入っています。
resultにはmyTextの値を入れようとしますが、もしmyTextがnullだったら、"デフォルトのテキスト"を使います。
つまり、??は「左側がnullだった場合、右側の値を使う」という便利な方法です。
nullable 型、null 合体演算子について、あなたのコードでは、以下のように使っています:
var num = Array.ConvertAll(Console.ReadLine()?.Split(' ') ?? new string[0], int.Parse);
Console.ReadLine()? は、もしConsole.ReadLine()の値がnullでなければSplit(' ')を実行するという意味です。
次に、もしConsole.ReadLine()?.Split(' ')がnullだった場合、?? new string[0]で空の配列(new string[0])を代わりに使います。
3.三項演算子(? :)の使い方
条件式 ? 値1 : 値2
条件式:trueかfalseを返す条件を指定します。例えば、index == -1は、indexが-1であるかどうかをチェックしています。
値1:条件式がtrueのときに返す値です。
値2:条件式がfalseのときに返す値です。
あなたのコードの具体的な意味:
Console.WriteLine(index == -1 ? -1 : index + 1);
これは、次のような意味になります:
index == -1: indexが-1と等しいかどうかを確認します。
もしtrue(つまり、indexが-1)の場合、次に-1が実行されます。
もしfalse(つまり、indexが-1ではない)場合、次にindex + 1が実行されます。
indexが-1の場合は、そのまま-1を表示しますが、-1でない場合はindex + 1の値を表示します。
三項演算子なしで同じ処理を記述すると…
if (index == -1)
{
Console.WriteLine(-1);
}
else
{
Console.WriteLine(index + 1);
}
三項演算子は、簡潔に書けるため、特に短い条件分岐に向いています。
この書き方に慣れると、コードがすっきりするので、ぜひ試してみてください!