PaizaのC問題相当のレベルアップ問題集の解説記事を作成しました。
問題の参考リンクはこちらからどうぞ。
今回はこの問題集の中からイルミネーションについて解説しています。
難易度は1350前後、正答率が約80%の問題です(C問題の中ではちょうど真ん中あたりの難易度です)。
問題文と入力出力例
N 個の LED が付けられた電飾があります。 LED にはそれぞれ 1 から N までの番号が付けられており、0 から 255 までの数値で明るさを調整することができます。 明るさ 0 は LED が消灯していることを意味します。
LED は操作盤を使って、番号と明るさを指定して信号を送ることで操作することができます。
最初はすべての LED が消灯しています。 M 個の信号が与えられるので、N 個の LED が初めて同時に点灯したときの明るさの合計を出力してください。
入力例
N M
a_1 b_1
a_2 b_1
…
a_M b_M
入力例(数値)
4 7
1 1
2 4
2 8
4 16
1 32
3 64
4 128
出力例
120
解説
具体例から想像する
とても簡単な例から挙げてみます。
4 4
1 2
2 2
3 2
4 2
1 3この例であると、正解は8となります。
5行めで1~4すべてが点灯したことになるので、それより後は計算せず、2~5行目までの累計をすればいいので答えが8になるのです。
お膳立ての思考について
少し話はそれますが、この解説記事の1~2までは、数値を数えていましたが、今回からは自動で数える仕組みを採用しています。
この方法により、複雑な問題文でも考え方が逸れずに済むのでぜひこの場で習得してみてください。
let line = 0; // ここで入力行の初期化を行う
const [N, M] = lines[line++].split(" ").map(Number) // line++と表現することで自動化ができるline++(後置で++がある場合)では、ページを読んでからめくる感覚でOK!
また、思考の流れとしては、先に電灯がすべて消灯している状態と、すべてONになった時をカウントする変数を宣言するというものです。
const led = Array(N).fill(0);
let onCount = 0;Array()は新たに配列を作る
for文章の中身について
LEDがすべてONになるまでのif文章
forループの範囲は0回目からM回目の一つ手前まで一つずつやります。
入力で与えられるものをナンバーと明るさ(num, bright)と宣言し、ledの配列と合わせるため-1をします。
次に、ONになったらカウントするif文章を作ります。
ONになるというのは、
最初はOFFでかつ今回の明るさが0より大きいという条件と言い換えられます。
また、ONからOFFになるときにカウントが減るelse文も同様に作っておきます。
その後、LEDの明るさを更新します。
for(let i = 0; i < M; i++) {
const [num, bright] = lines[line++].split(" ").map(Number);// ここでナンバーと明るさ宣言
const index = num - 1;// ledの配列と帳尻合わせ
// OFFかつ明るさ0より大きい、つまりはON
if (led[index] === 0 && bright > 0) {
onCount++;
} else if (led[index] > 0 && bright === 0) {
onCount--;
}
//LEDの明るさ更新
led[index] = bright;LEDがすべてONになった後に行う操作
今回初めてすべてONになった瞬間の合計を計算するということなので、その後は一切計算しません。
つまり合計を計算した後に必ずbreakをします。
また、累計を計算することはforループでもできなくはないですが、別の文法を使うとよりスッキリします。
reduce()は配列の数値を一つに丸め込む文法
//LEDがすべて点灯した場合
if (onCount === N) {
const sum = led.reduce((a, b) => a + b, 0);
console.log(sum);
break;
}
}全体のおさらいコード
reader.on('close', () => {
let idx = 0;
const[N, M] = lines[idx++].split(" ").map(Number);
const led = Array(N).fill(0);
let onCount = 0;
for(let i = 0; i < M; i++) {
const [num, bright] = lines[idx++].split(" ").map(Number);
const index = num - 1;
if (led[index] === 0 && bright > 0) {
onCount++;
} else if (led[index] > 0 && bright === 0) {
onCount--;
}
led[index] = bright;
if (onCount === N) {
const sum = led.reduce((a, b) => a + b, 0);
console.log(sum);
break;
}
}
});
