summaryrefslogtreecommitdiff
path: root/08/src/part-2.rs
blob: a11e7b9c94bda7290e94a50764a7cd6158c77f2a (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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
mod bitfield;

use std::io::{BufRead};

use crate::bitfield::{Bitfield, parse_input};

// This is embarassingly inefficient, and full of completely needless
// allocations. I just wanna get day 8 done!
fn perms(x: Vec<usize>) -> Vec<Vec<usize>> {
    if x.len() == 1 { vec![x] }
    else {
        let mut ret: Vec<Vec<usize>> = Vec::new();
        for perm in perms(x[1..].to_vec()) {
            for i in 0..x.len() {
                let mut tmp: Vec<usize> = Vec::with_capacity(perm.len() + 1);
                tmp.extend(& perm[0..i]);
                tmp.push(x[0]);
                tmp.extend(& perm[i..]);
                ret.push(tmp);
            }
        }
        ret
    }
}

const DIGIT_0: Bitfield = Bitfield { data: (1 << 0) | (1 << 1) | (1 << 2) | (0 << 3) | (1 << 4) | (1 << 5) | (1 << 6) };
const DIGIT_1: Bitfield = Bitfield { data: (0 << 0) | (0 << 1) | (1 << 2) | (0 << 3) | (0 << 4) | (1 << 5) | (0 << 6) };
const DIGIT_2: Bitfield = Bitfield { data: (1 << 0) | (0 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (0 << 5) | (1 << 6) };
const DIGIT_3: Bitfield = Bitfield { data: (1 << 0) | (0 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (1 << 6) };
const DIGIT_4: Bitfield = Bitfield { data: (0 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (0 << 6) };
const DIGIT_5: Bitfield = Bitfield { data: (1 << 0) | (1 << 1) | (0 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (1 << 6) };
const DIGIT_6: Bitfield = Bitfield { data: (1 << 0) | (1 << 1) | (0 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) };
const DIGIT_7: Bitfield = Bitfield { data: (1 << 0) | (0 << 1) | (1 << 2) | (0 << 3) | (0 << 4) | (1 << 5) | (0 << 6) };
const DIGIT_8: Bitfield = Bitfield { data: (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) };
const DIGIT_9: Bitfield = Bitfield { data: (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (0 << 4) | (1 << 5) | (1 << 6) };

fn decode(x: Bitfield) -> Option<usize> {
    match x {
        DIGIT_0 => Some(0),
        DIGIT_1 => Some(1),
        DIGIT_2 => Some(2),
        DIGIT_3 => Some(3),
        DIGIT_4 => Some(4),
        DIGIT_5 => Some(5),
        DIGIT_6 => Some(6),
        DIGIT_7 => Some(7),
        DIGIT_8 => Some(8),
        DIGIT_9 => Some(9),
        _       => None
    }
}


pub fn main() {
    let mut stdin = std::io::stdin();
    let mut handle = stdin.lock();

   /*
    println!("{}", DIGIT_0 == Bitfield::try_from("abcefg").unwrap());
    println!("{}", DIGIT_1 == Bitfield::try_from("cf").unwrap());
    println!("{}", DIGIT_2 == Bitfield::try_from("acdeg").unwrap());
    println!("{}", DIGIT_3 == Bitfield::try_from("acdfg").unwrap());
    println!("{}", DIGIT_4 == Bitfield::try_from("bcdf").unwrap());
    println!("{}", DIGIT_5 == Bitfield::try_from("abdfg").unwrap());
    println!("{}", DIGIT_6 == Bitfield::try_from("abdefg").unwrap());
    println!("{}", DIGIT_7 == Bitfield::try_from("acf").unwrap());
    println!("{}", DIGIT_8 == Bitfield::try_from("abcdefg").unwrap());
    println!("{}", DIGIT_9 == Bitfield::try_from("abcdfg").unwrap());
    return;
     */

    let mut sum: usize = 0;
    
    for line in handle.lines() {
        let l = line.unwrap();
        let (all, output) = parse_input(& l);
        let mut decoded_output: [usize; 4] = [0; 4];

        for perm in perms(vec![0,1,2,3,4,5,6]) {
            let mut all_digits = [Bitfield::new(); 10];
            for a in 0..10 {
                all_digits[a] = all[a].permute((& perm).into_iter());
            }
            let mut seen_digits: Vec<bool> = std::iter::repeat(false).take(10).collect();
            for a in 0..10 {
                if let Some(digit) = decode(all_digits[a]) {
                    seen_digits[digit] = true;
                }
            }
            /*
            print!("Decoded: ");
            for a in 0..10 {
                if seen_digits[a] { print!("{} ", a); }
            }
             */
            if (& seen_digits).into_iter().all(|&d| d) {
                println!("OK!");
                for a in 0..4 {
                    let descrambled = output[a].permute((& perm).into_iter());
                    decoded_output[a] = decode(descrambled).unwrap();
                }
                break;
            }
        }

        let line_answer = decoded_output[3]*1 + decoded_output[2]*10 + decoded_output[1]*100 + decoded_output[0]*1000;
        println!("Answer: {}", line_answer);
        sum += line_answer;
    }

    println!("Sum: {}", sum);
}