Advent of Code
毎日2題出題されます。競技プログラミングチックに楽しめます。
この問題概要と実装解答を以下にご紹介します。
問題概要は生成AIに書いてもらったものを貼り付けています。
実装は人間が行なっています。
Day 4: Printing Department
part1 問題概要
- 紙のロール(@)が、2次元グリッド状に並んでいる。
- 入力は、. と @ からなる複数行の図。@ = 紙のロール. = 何もない
- 各ロール(@)について、その8近傍の中にある @ の数が 4 未満ならそのロールはフォークリフトがアクセス可能。このロールの個数を数えて
解答
全探索。
use std::{cmp::max, collections::HashSet};
use itertools::Itertools;
use proconio::{input, marker::Chars};
fn main() {
let h = 139;
input! {
s: [Chars; h]
}
let w = s[0].len();
let didj = vec![(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)];
let mut ans = 0;
for i in 0..h {
for j in 0..w {
if s[i][j] != '@' {
continue;
}
let mut count = 0;
for &(di, dj) in didj.iter() {
let ni = i as isize + di;
let nj = j as isize + dj;
if ni < 0 || ni >= h as isize || nj < 0 || nj >= w as isize {
continue;
}
let ni = ni as usize;
let nj = nj as usize;
if s[ni][nj] == '@' {
count += 1usize;
}
}
if count < 4 {
ans += 1usize;
}
}
}
println!("{}", ans);
}
part2 問題概要
- 現在のグリッドで、周囲8マスの @ が 4 未満のロール(アクセス可能)を全部探す。
- それらを. に変える
- 取り除かれたことで、また周りのロールの「隣接 @ の数」が変わるので、再び 1 に戻って「新しくアクセス可能になったロール」を探す。
- これ以上アクセス可能なロールが無くなるまで繰り返す。
その間に取り除かれた @ の 総数 が答え。
解答
とれるものは取っておいて損はないのでどんどん取っていく。
あるますを取り除いた時の影響範囲は8近傍しかないので、BFSして近傍4つ未満になったロールをどんどん取っていくことで答え。
fn main() {
let h = 139;
input! {
s: [Chars; h]
}
let w = s[0].len();
let didj = vec![(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)];
let mut ans = vec![vec![false; w]; h];
let mut c = vec![vec![0; w]; h];
let mut que = VecDeque::new();
for i in 0..h {
for j in 0..w {
if s[i][j] != '@' {
continue;
}
let mut count = 0;
for &(di, dj) in didj.iter() {
let ni = i as isize + di;
let nj = j as isize + dj;
if ni < 0 || ni >= h as isize || nj < 0 || nj >= w as isize {
continue;
}
let ni = ni as usize;
let nj = nj as usize;
if s[ni][nj] == '@' {
count += 1usize;
}
}
c[i][j] = count;
if count < 4 {
que.push_back((i, j));
ans[i][j] = true;
}
}
}
while !que.is_empty() {
let (i, j) = que.pop_front().unwrap();
for &(di, dj) in didj.iter() {
let ni = i as isize + di;
let nj = j as isize + dj;
if ni < 0 || ni >= h as isize || nj < 0 || nj >= w as isize {
continue;
}
let ni = ni as usize;
let nj = nj as usize;
if ans[ni][nj] || c[ni][nj] == 0 || s[ni][nj] == '.' {
continue;
}
c[ni][nj] -= 1;
if c[ni][nj] < 4 {
ans[ni][nj] = true;
que.push_back((ni, nj));
}
}
}
let ans = ans.iter().flatten().filter(|&&e|e).count();
println!("{}", ans);
}
終わりに
Day5も頑張ります!