🎄
Advent of Code 2020 day06
part1
abc
a
b
c
ab
ac
a
a
a
a
b
のような、day04と同様な空行で区切られたgroupがあり、各行がその同一group内で各人が"yes"
と回答した質問を表す。
part1は、各groupで"yes"
と回答された質問の数をかぞえ、合計を出せ、という問題。単純に各group内で出現するuniqueな文字数をカウントして合計すれば良いだけ。
a
からz
までというのは分かっているので辞書にはHashSet
などを使う必要もなく、26
sizeのbool
配列だけ用意すれば良い。
struct Solution {
inputs: Vec<String>,
}
impl Solution {
fn new(inputs: Vec<String>) -> Self {
Self { inputs }
}
fn solve_1(&self) -> usize {
let mut ret = 0;
let mut d = [false; 26];
for line in self.inputs.iter().chain([String::new()].iter()) {
if line.is_empty() {
for b in d.iter_mut() {
if *b {
ret += 1;
}
*b = false;
}
} else {
for &b in line.as_bytes() {
d[(b - b'a') as usize] = true;
}
}
}
ret
}
}
part2
実はかぞえるべきは「groupの誰かが"yes"
と回答した」ではなく「groupの全員が"yes"
と回答した」質問の数だった、という。
bool
演算でいうと OR
で見ていたのが AND
で見る必要があった、ということになる。
せっかくなので、bool
配列で管理していたものを u32
の各bitで管理するように変更してみた。各人の回答をu32
の値に変換して持ち、part1は |
で、part2は &
でgroup内全員の値をfold
していけばあとは最終的な値のbit countを調べるだけで良くなる。 &
の場合は初期値が全部立っている必要があるので注意。
struct Solution {
groups: Vec<Vec<u32>>,
}
impl Solution {
fn new(inputs: Vec<String>) -> Self {
let mut groups: Vec<Vec<u32>> = Vec::new();
let mut v: Vec<u32> = Vec::new();
for line in inputs.iter().chain([String::new()].iter()) {
if line.is_empty() {
groups.push(v.clone());
v.clear();
} else {
v.push(
line.as_bytes()
.iter()
.map(|&b| 1 << (b - b'a') as usize)
.fold(0, |acc, x| acc | x),
);
}
}
Self { groups }
}
fn solve_1(&self) -> usize {
self.groups
.iter()
.map(|group| group.iter().fold(0, |acc, &x| acc | x).count_ones() as usize)
.sum()
}
fn solve_2(&self) -> usize {
self.groups
.iter()
.map(|group| {
group
.iter()
.fold((1 << 26) - 1, |acc, &x| acc & x)
.count_ones() as usize
})
.sum()
}
}
Discussion