以下のpaiza Bランク・スキルチェック過去問の「3Dプリンタ」をC言語で解いたので、覚書しておきます。
戦略はいつもどおり、コツコツ実直に検査していきます。
問題の対象となる空間が最大でも50 x 50 x 50のため、すなおにfor文を回しても大丈夫そうでした。
以下が最終的なコードに、コメントを追加したものです。
#include <stdio.h>
int main(void){
char buf[100];
int x, y, z;
// 入力を受けとる
// 空間の大きさを取得
fgets(buf, sizeof(buf), stdin);
sscanf(buf, "%d %d %d", &x, &y, &z);
// 空間の立体の有無を取得
char field[51][51][51]; // 最大文字列数 + NULL終端文字
for(int i = 0; i < z; i++) {
for(int j = 0; j < x; j++) {
fgets(buf, sizeof(buf), stdin);
for(int k = 0; k < y; k++) {
field[i][j][k] = buf[k];
}
}
fgets(buf, sizeof(buf), stdin); // "--"を読み飛ばす
}
// 入力を正常に受けとれたかテスト
/*
printf("%d %d %d\n", x, y, z);
for(int i = 0; i < z; i++) {
for(int j = 0; j < x; j++) {
printf("%s\n", field[i][j]);
}
}
*/
// ここから解法
char result[51][51] = {0}; // 最終結果用の配列(最大文字列数 + NULL終端文字)
for(int i = 0; i < z; i++) {
for(int j = 0; j < y; j++) {
result[i][j] = '.'; // 最終結果のresult配列を初期化
for(int k = 0; k < x; k++) {
// 立体があったら、result配列の該当位置を'#'として、その列の走査終了
if(field[i][k][j] == '#') {
result[i][j] = '#'; //
break;
}
}
}
}
// 最終結果を出力
for(int i = z - 1; i >= 0; i--) {
printf("%s\n", result[i]);
}
}
空間の座標の方向に少々試行錯誤しました。
まず、入力を受けとるときは、z回数分、y文字の行をx行取得しますので、for文の入れ子は、z -> x -> yとなります。
実際に検査していくときは、横方向から見るため、for文の入れ子はz -> y -> xとなります。(つまり、奥行きがx、縦幅がz、横幅がyです)
この対応は、手元で図を書いて確認しました。
また、以下の条件があり、入力された空間情報を文字列として扱うため、入力データにも出力データも、NULL終端文字をプラスしたサイズを確保します。
条件
すべてのテストケースにおいて、以下の条件をみたします。
・ 1 ≦ X ≦ 50
・ 1 ≦ Y ≦ 50
・ 1 ≦ Z ≦ 50
終わりに
入力を受けとるのには慣れてきた感覚があります。
また、C言語の場合、数値の取り得る範囲を確認して、必要十分なサイズの変数を確保しなければならないので、そこが面倒くさいです。
引き続き、他の問題にもチャレンジしてみたいと思います。