はじめに
paizaとqiitaの記事投稿キャンペーンに参加してみました。の流れでCランクの問題にもチャレンジ内容を解説しました。
関連記事
https://qiita.com/hyonkichi/items/b17aef92bb560d6a53f3
問題
解答コード
#include <stdio.h>
int main(void){
// 自分の得意な言語で
// Let's チャレンジ!!
char str[1000];
int i;
int tousen_num, tousen2_num, tousen3_num;
int kounyuu_num;
int ticket_num;
fgets(str, sizeof(str), stdin);
sscanf(str, "%d\n", &tousen_num);
tousen2_num = (tousen_num%10000);
tousen3_num = (tousen_num%1000);
fgets(str, sizeof(str), stdin);
sscanf(str, "%d\n", &kounyuu_num);
for(i=0; i<kounyuu_num; i++)
{
fgets(str, sizeof(str), stdin);
sscanf(str, "%d\n", &ticket_num);
if(ticket_num == tousen_num) //1等チェック
{
printf("first\n");
}
else
{
if((ticket_num == (tousen_num+1))||(ticket_num == (tousen_num-1))) //前後賞チェック
{
printf("adjacent\n");
}
else
{
ticket_num %= 10000;
if(ticket_num==tousen2_num) //2等チェック
{
printf("second\n");
}
else
{
ticket_num %= 1000;
if(ticket_num==tousen3_num) //3等チェック
{
printf("third\n");
}
else
{
printf("blank\n");
}
}
}
}
}
return 0;
}
解説
プログラムの流れ
-
変数の定義と初期化:
str[1000]は、標準入力から取得した文字列を格納するためのバッファです。
tousen_numは、当選番号を格納する変数です。
tousen2_numとtousen3_numは、当選番号の下4桁および下3桁を格納するための変数です。
kounyuu_numは、購入した宝くじの数を格納する変数です。
ticket_numは、各宝くじ番号を格納する変数です。 -
抽選番号と購入番号の取得:
最初のfgetsとsscanfで当選番号を取得し、tousen_numに格納します。
tousen2_numとtousen3_numには、それぞれ当選番号の下4桁と下3桁が計算されて格納されます。
2つ目のfgetsとsscanfで、宝くじの数を取得し、kounyuu_numに格納します。 -
当選判定のループ処理:
forループ内で、購入した宝くじの番号を1つずつ取得し、当選番号との比較を行います。
まず、購入した番号が当選番号と完全に一致する場合、1等として"first"と出力します。
その後、前後賞の判定を行います。購入した番号が当選番号の前後1桁違いの場合、"adjacent"と出力します。
それ以外の場合、購入番号の下4桁を当選番号の下4桁と比較し、一致すれば2等として"second"と出力します。
下4桁が一致しなければ、さらに下3桁を当選番号の下3桁と比較し、一致すれば3等として"third"と出力します。
上記のいずれにも該当しない場合は、"blank"と出力します。 -
ポイント
1等、前後賞は直感的ですが、2,3等の確認については十進数で表現された番号の"桁を落とす"という工程が発生するのが肝と思います。
16進数であれば0x0FFFのような固定値とANDをとる方法がパッと思いつきますが、今回は十進数なので10000や1000の余りを取得することで頭の桁を落とした番号を算出するのがポイントです。
終わりに
点数自体は100点がついたコードですが、
- 各等級の判定処理を関数化して、もっとすっきりした処理かつ再利用性を上げる
- 直値の使用は避ける
など実務では最低限上記を修正したほうが良いだろうと思います。(保険)