aboutsummaryrefslogtreecommitdiff
path: root/2023/day-01/src/bin/part2.rs
blob: 99f87480b2febdc4de5b459791ca285fc8830178 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use std::collections::HashMap;

fn main() {
    let input = include_str!("./input.txt");
    let output: i32 = input.lines().map(process_line).sum();
    println!("Result {}", output);
}

/// Return the position of `needle` in `string`
fn find_ocurrences<'a>(string: &'a str, needle: &str) -> Vec<(usize, &'a str)> {
    string.match_indices(needle).collect()
}

fn find_min<'a>(matches: &[(usize, &'a str)]) -> (usize, &'a str) {
    let (position, word) = matches.iter().min_by(|(x,_), (y, _)| {
	x.cmp(y)
    }).unwrap();

    (*position, word)
}

fn find_max<'a>(matches: &[(usize, &'a str)]) -> (usize, &'a str) {
    let (position, word) = matches.iter().min_by(|(x,_), (y, _)| {
	y.cmp(x)
    }).unwrap();

    (*position, word)
}

/// Return the first and last number on `s`
fn process_line(s: &str) -> i32 {
    let mapping: HashMap<&str, i32> = HashMap::from([
	("one", 1), ("two", 2), ("three", 3),
	("four", 4), ("five", 5), ("six", 6),
	("seven", 7), ("eight", 8), ("nine", 9),
	("1", 1), ("2", 2), ("3", 3), ("4", 4), ("5", 5),
	("6", 6), ("7", 7), ("8", 8), ("9", 9),
    ]);

    let matches = mapping.iter().map(|(k, _)| {
	find_ocurrences(s, k)
    }).collect::<Vec<_>>().concat();
    let (_, min_number) = find_min(&matches);
    let (_, max_number) = find_max(&matches);

    (mapping[min_number] * 10) + mapping[max_number]
}


#[test]
fn test_find_min_1() {
    let input = vec!((1, "eight"), (2, "eight"), (3, "2"));
    assert_eq!(find_min(&input), (1, "eight"));
}

#[test]
fn test_find_min_2() {
    let input = vec!((4, "eight"), (5, "eight"), (3, "2"));
    assert_eq!(find_min(&input), (3, "2"));
}

#[test]
fn simple_input() {
    let string = "onetwo";
    assert_eq!(process_line(string), 12);
}

#[test]
fn overlap_input() {
    let string = "oneight";
    assert_eq!(process_line(string), 18);
}

#[test]
fn example() {
    let string = "two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen";

    let result: Vec<i32> = string.lines().map(process_line).collect();

    assert_eq!(result, &[29, 83, 13, 24, 42, 14, 76]);
}