No.632 穴埋め門松列

はじめに

競技プログラミングyukicoder
No.632 穴埋め門松列
言語はC#
何かあればTwitter→@pirorirori_n712まで

問題

入力:c1 c2 c3
3つの文字は,'2'か,'3','?'のいずれか
(文字の重複はない)
出力:「1」か「4」か「14」
「?」を「1」か「4」どちらで置き換えれば入力を門松列にできるかを出力する
ただし、どちらでもいい場合は「14」を出力する
☆門松列とは?
3つの自然数から成る数列v=(a1,a2,a3)が次の条件を満たす列
1 a1,a2,a3は全て異なる
2 3つの要素のうちa2が最も大きい,あるいは最も小さい

解き方

門松列は真ん中の文字が
他の2文字よりも「小さい」か「大きい」列なので
真ん中の文字に注目すると短く解ける

入力が3文字と決まっていて「2、3、?」が重複なしで与えられるので
次のように真ん中の文字で場合分けができる

①真ん中の文字が「2」の場合
残りの2文字は「3」と「?」
このとき「2」は「3」よりも小さいので、出来上がる門松列は2が一番小さくなる
(考えられる文字列を書き出すと「3 2 ?」「? 2 3」の2パターン)
3文字の中で真ん中の「2」が一番小さくなければいけないので、
「1」と「4」のうち、「2」よりも大きい「4」が答えとなる
(先ほどのパターンに入れてみると「3 2 4」「4 2 3」となり、門松列になることが分かる)

②真ん中の文字が「3」の場合
残りの2文字は「2」と「?」
このとき「3」は「2」よりも大きいので、出来上がる門松列は3が一番大きくなる
(考えられる文字列を書き出すと「2 3 ?」「? 3 2」の2パターン)
3文字の中で真ん中の「3」が一番大きくなければいけないので、
「1」と「4」のうち、「3」よりも小さい「1」が答えとなる
(先ほどのパターンに入れてみると「2 3 1」「1 3 2」となり、門松列になることが分かる)

③真ん中の文字が「?」の場合
残りの2文字は「2」と「3」
試しに端が「2」と「3」の列を書き出してみると
「2 ? 3」「3 ? 2」の2つであることが分かる
門松列は真ん中が他の2文字よりも「小さい」か「大きい」列である
ここから真ん中に入れる文字を考えると
「1」は「2」と「3」どちらの数字よりも小さい
よって「1」を「?」に置き換えると真ん中が一番小さい門松列が出来上がる
したがって、「1」は正解
次に「4」は「2」と「3」どちらの数字よりも大きい
よって「4」を「?」に置き換えると真ん中が一番大きい門松列が出来上がる
したがって、「4」も正解なので「14」を出力すればいいことが分かる

①ifで場合分け

②条件演算子で場合分け

①ifで場合分け

コード例

using System;

class No632{
    static void Main(string[] args){
        //入力された文字列を「' '」で区切って配列にし、変数strに格納
        var str=Console.ReadLine().Split(' ');
        //出力を書く部分を一つにしたい(Console.WriteLine()を一回しか書きたくない)ので
        //答えを入れる変数を用意し、(適当に0で初期化)
        //ここに答えを入れ最後に出力できるようにする
        var answer=0;
        //真ん中の文字は2番目の文字なのでstr[1]
        //真ん中の文字が2のとき
        if(str[1]=="2"){
            //2が一番小さくなるようにしたいので答えは4
            answer=4;
        }//真ん中の文字が3のとき
        else if(str[1]=="3"){
            //3が一番大きくなるようにしたいので答えは1
            answer=1;
        }//真ん中が「2」でも「3」でもないとき、すなわち「?」のとき
        else{
            //「1」でも「4」でも門松列になるので答えは14
            answer=14;
        }
        //最後に答えを出力
        Console.WriteLine(answer);
    }
}

先にanswerに14を入れて初期化しておくと最後のelseのブロックを省略できる

using System;

class No632{
    static void Main(string[] args){
        //入力された文字列を「' '」で区切って配列にし、変数strに格納
        var str=Console.ReadLine().Split(' ');
        //出力を書く部分を一つにしたい(Console.WriteLine()を一回しか書きたくない)ので
        //答えを入れる変数を用意し
        //以下に続くif分のブロックのどちらの条件(真ん中が「2」か「3」)にも該当しなければ
        //14になるように(真ん中が「?」のときの解答)しておく
        var answer=14;
        //真ん中の文字は2番目の文字なのでstr[1]
        //真ん中の文字が2のとき
        if(str[1]=="2"){
            //2が一番小さくなるようにしたいので答えは4
            answer=4;
        }//真ん中の文字が3のとき
        else if(str[1]=="3"){
            //3が一番大きくなるようにしたいので答えは1
            answer=1;
        }
        //最後に答えを出力
        Console.WriteLine(answer);
    }
}

②条件演算子で場合分け

if文で場合分けをせずに、条件演算子で一行にまとめます

コード例

using System;

class No632{
    static void Main(string[] args){
        //入力された文字列を「' '」で区切って配列にし、変数strに格納
        var str=Console.ReadLine().Split(' ');
        //answerという変数を用意し答えを入れる
        //真ん中の文字が2のとき4,真ん中の文字が3のとき1、真ん中の文字が「2」でも「3」でもないとき(すなわち「?」のとき)14
        var answer=(str[1]=="2")?4:(str[1]=="3")?1:14;
        //最後に答えを出力
        Console.WriteLine(answer);
    }
}