<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("02.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

fn get_char_histogram(input: &str) -> HashMap<char, usize> {
    let mut result = HashMap::new();

    for c in input.chars() {
        let v = match result.get(&c) {
            Some(&v) => v,
            None => 0
        };

        result.insert(c, v + 1);
    }

    result
}

fn get_checksum(ids: &Vec<String>) -> usize {
    let histograms: Vec<HashMap<char, usize>> = ids.iter()
        .map(|x| get_char_histogram(x))
        .collect();

    let exactly_two = histograms.iter()
        .filter(|hist| hist.iter().any(|(_, &v)| v == 2))
        .count();

    let exactly_three = histograms.iter()
        .filter(|hist| hist.iter().any(|(_, &v)| v == 3))
        .count();

    return exactly_two * exactly_three
}

fn diff_id(id1: &str, id2: &str) -> usize {
    id1.chars()
    .zip(id2.chars())
    .filter(|(c1, c2)| c1 != c2)
    .count()
}

fn find_correct_ids<'a>(ids: &'a Vec<String>) -> Option<(&'a str, &'a str)> {
    for (i, id1) in ids.iter().enumerate() {
        for id2 in ids.iter().skip(i + 1) {
            let diff = diff_id(id1, id2);

            if diff == 1 {
                return Some((id1, id2));
            }
        }
    }

    None
}

fn main() {
    let ids: Vec<String> = get_input().unwrap()
        .lines()
        .map(|x| x.to_string())<commit_msg>Remove unnecessary lifetime<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

fn get_input() -> std::io::Result<String> {
    let mut file = File::open("02.txt")?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;

    Ok(contents)
}

fn get_char_histogram(input: &str) -> HashMap<char, usize> {
    let mut result = HashMap::new();

    for c in input.chars() {
        let v = match result.get(&c) {
            Some(&v) => v,
            None => 0
        };

        result.insert(c, v + 1);
    }

    result
}

fn get_checksum(ids: &Vec<String>) -> usize {
    let histograms: Vec<HashMap<char, usize>> = ids.iter()
        .map(|x| get_char_histogram(x))
        .collect();

    let exactly_two = histograms.iter()
        .filter(|hist| hist.iter().any(|(_, &v)| v == 2))
        .count();

    let exactly_three = histograms.iter()
        .filter(|hist| hist.iter().any(|(_, &v)| v == 3))
        .count();

    return exactly_two * exactly_three
}

fn diff_id(id1: &str, id2: &str) -> usize {
    id1.chars()
    .zip(id2.chars())
    .filter(|(c1, c2)| c1 != c2)
    .count()
}

fn find_correct_ids(ids: &Vec<String>) -> Option<(&str, &str)> {
    for (i, id1) in ids.iter().enumerate() {
        for id2 in ids.iter().skip(i + 1) {
            let diff = diff_id(id1, id2);

            if diff == 1 {
                return Some((id1, id2));
            }
        }
    }

    None
}

fn main() {
    let ids: Vec<String> = get_input().unwrap()
        .lines()
        .map(|x| x.to_string())
{'fraction_non_alphanumeric': 0.18914630276102826, 'fraction_numerical': 0.013963821009203427, 'mean_word_length': 2.2629399585921326, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4567866', 'n_tokens_mistral': 1151, 'n_tokens_neox': 1125, 'n_words': 256}