Advent of Code
毎日2題出題されます。競技プログラミングチックに楽しめます。
この問題概要と実装解答を以下にご紹介します。
問題概要は生成AIに書いてもらったものを貼り付けています。
実装は人間が行なっています。
Day 5: Cafeteria
part1 問題概要
- rangeの配列が
a-bの形で与えられる - その後、数字の配列が与えられる
- 与えられた数字の中でrangeに入っている数字は何個ある?
- ただし、rangeは被っているかもしれないよ
解答
全探索。
fn main() {
let n = 177;
let m = 1000;
input! {
range: [String; n],
num: [usize; m]
}
let lr = range.iter().map(|e| parse_range(e)).collect_vec();
let mut ans = 0;
'l: for &num in num.iter() {
for &(l, r) in lr.iter() {
if l <= num && num <= r {
ans += 1usize;
continue 'l;
}
}
}
println!("{}", ans)
}
part2 問題概要
- 入力で与えられたrangeについて重なっている部分があるけど、実際rangeには何個数字がある?
解答
値が小さいものからソートしておいて、順に範囲を見ていく。
つまり、要素を見ていったときに、見ていない要素の中でより左にあるものがない状態にする。
その状態でマージできる範囲はマージしていく。
マージできる範囲とは、今見ているrangeが[a, b], マージしたい範囲が[c, d]だとすると、
d >= a であることがすぐにわかるので、この時に範囲を
[c, max(b, d)] としてマージする。
マージできないときは一つのrangeの区切りがつくので、ansに足しこむ。
これを繰り返せば答えになる。
fn main() {
let n = 177;
let m = 1000;
input! {
range: [String; n],
_num: [usize; m]
}
let mut lr = range.iter().map(|e| parse_range(e)).collect_vec();
lr.sort_by_key(|&e| (e.0, e.1));
let mut now = (lr[0].0, lr[0].0);
let mut ans = 0;
for &(l, r) in lr.iter() {
let (pl, pr) = now;
assert!(pl <= l);
if pr < l {
ans += pr - pl + 1;
now = (l, r);
continue;
}
now.1 = max(r, pr);
}
ans += now.1 - now.0 + 1;
println!("{}", ans);
}
終わりに
Day6も頑張ります!