summaryrefslogtreecommitdiff
path: root/d16/src/main.rs
blob: 06ba9e10c3462d782ef52022e2e6ce5493fdb28c (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
fn generate_data(input: &str, length: usize) -> String {
    let mut a = String::from(input);

    while a.len() < length {
        let mut b = String::new();

        // Fill `b' with reversed and bit-flipped `a'
        for c in a.chars().rev() {
            b.push(if c == '0' { '1' } else { '0' });
        }

        a = format!("{}0{}", a, b);
    }

    a.truncate(length);
    a
}

fn get_checksum(data: &str) -> String {
    let mut chars: Vec<char> = data.chars().collect();

    while chars.len() % 2 == 0 {
        let mut next = Vec::new();

        // For each pair of characters (length is even due to `while')
        for i in 0..chars.len() / 2 {
            // If both chars in this pair are equal
            if chars[2 * i] == chars[2 * i + 1] {
                next.push('1');
            } else {
                next.push('0');
            }
        }

        chars = next;
    }

    chars.into_iter().collect()
}

fn solve_puzzle(input: &str, length: usize) -> String {
    let data = generate_data(input, length);
    get_checksum(&data)
}

fn main() {
    // My personal puzzle input
    let input = "11011110011011101";

    // Part 1 gives 00000100100001100 for me
    println!("Part 1 solution: {}", solve_puzzle(input, 272));

    // Part 1 gives 00011010100010010 for me
    println!("Part 2 solution: {}", solve_puzzle(input, 35651584));
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_data() {
        assert_eq!(generate_data("1", 3), "100");
        assert_eq!(generate_data("0", 3), "001");
        assert_eq!(generate_data("11111", 11), "11111000000");
        assert_eq!(
            generate_data("111100001010", 25),
            "1111000010100101011110000"
        );
    }

    #[test]
    fn test_checksum() {
        assert_eq!(get_checksum("110010110100"), "100");
    }

    #[test]
    fn part1_example1() {
        assert_eq!(solve_puzzle("10000", 20), "01100");
    }
}