🎄

Advent of Code 2020 day02

2020/12/09に公開

https://adventofcode.com/2020/day/2

part1

1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc

という形式の入力をparseしていき、条件を見たしている行の数を返す。
part1では 1-3 a は「a1回以上 3回以下出現する」という意味になる。そのまま実装するだけ。

正規表現つかってみたけど captureの取り出し方ってもっと上手い方法あるのかな…

    fn solve_1(&self) -> usize {
        let re: Regex = Regex::new(r"^(\d+)\-(\d+) (.): (.+)$").unwrap();
        self.inputs
            .iter()
            .filter(|&input| {
                if let Some(cap) = re.captures(input) {
                    let min = cap[1].parse::<usize>().unwrap();
                    let max = cap[2].parse::<usize>().unwrap();
                    let chr = cap[3].chars().next().unwrap();
                    let appear = cap[4].chars().filter(|&c| c == chr).count();
                    (min..=max).contains(&appear)
                } else {
                    false
                }
            })
            .count()
    }

part2

解釈が変わって 1-3 a は「1文字目か 3文字目 どちらかだけが aである」という意味になる。 indexは 0-origin ではないことに注意。

どちらかだけが条件を満たす、というところで matches macro を使ってみた。

    fn solve_2(&self) -> usize {
        let re: Regex = Regex::new(r"^(\d+)\-(\d+) (.): (.+)$").unwrap();
        self.inputs
            .iter()
            .filter(|&input| {
                if let Some(cap) = re.captures(input) {
                    let pos1 = cap[1].parse::<usize>().unwrap();
                    let pos2 = cap[2].parse::<usize>().unwrap();
                    let chr = cap[3].chars().next().unwrap();
                    matches!(
                        (
                            cap[4].chars().nth(pos1 - 1) == Some(chr),
                            cap[4].chars().nth(pos2 - 1) == Some(chr),
                        ),
                        (true, false) | (false, true),
                    )
                } else {
                    false
                }
            })
            .count()
    }

code

use regex::Regex;
use std::io::{BufRead, BufReader};

struct Solution {
    inputs: Vec<String>,
    re: Regex,
}

impl Solution {
    fn new(inputs: Vec<String>) -> Self {
        Self {
            inputs,
            re: Regex::new(r"^(\d+)\-(\d+) (.): (.+)$").unwrap(),
        }
    }
    fn solve_1(&self) -> usize {
        self.inputs
            .iter()
            .filter(|&input| {
                if let Some(cap) = self.re.captures(input) {
                    let min = cap[1].parse::<usize>().unwrap();
                    let max = cap[2].parse::<usize>().unwrap();
                    let chr = cap[3].chars().next().unwrap();
                    let appear = cap[4].chars().filter(|&c| c == chr).count();
                    (min..=max).contains(&appear)
                } else {
                    false
                }
            })
            .count()
    }
    fn solve_2(&self) -> usize {
        self.inputs
            .iter()
            .filter(|&input| {
                if let Some(cap) = self.re.captures(input) {
                    let pos1 = cap[1].parse::<usize>().unwrap();
                    let pos2 = cap[2].parse::<usize>().unwrap();
                    let chr = cap[3].chars().next().unwrap();
                    matches!(
                        (
                            cap[4].chars().nth(pos1 - 1) == Some(chr),
                            cap[4].chars().nth(pos2 - 1) == Some(chr),
                        ),
                        (true, false) | (false, true),
                    )
                } else {
                    false
                }
            })
            .count()
    }
}

Discussion