1
1
//! # Crossed Wires
2
2
use crate :: util:: hash:: * ;
3
+ use crate :: util:: iter:: * ;
3
4
use crate :: util:: parse:: * ;
4
5
5
- pub fn parse ( input : & str ) -> & str {
6
- input
7
- }
6
+ type Input < ' a > = ( & ' a str , Vec < [ & ' a str ; 5 ] > ) ;
8
7
9
- pub fn part1 ( input : & str ) -> u64 {
8
+ pub fn parse ( input : & str ) -> Input < ' _ > {
10
9
let ( prefix, suffix) = input. split_once ( "\n \n " ) . unwrap ( ) ;
10
+ let gates = suffix. split_ascii_whitespace ( ) . chunk :: < 5 > ( ) . collect ( ) ;
11
+ ( prefix, gates)
12
+ }
13
+
14
+ pub fn part1 ( input : & Input < ' _ > ) -> u64 {
15
+ let ( prefix, gates) = input;
11
16
12
17
let mut names = FastMap :: new ( ) ;
13
18
let mut cache = FastMap :: new ( ) ;
14
19
let mut ops = FastMap :: new ( ) ;
15
20
16
21
for line in prefix. lines ( ) {
17
- let ( key, value) = line. split_once ( ": " ) . unwrap ( ) ;
22
+ let prefix = & line[ ..3 ] ;
23
+ let suffix = & line[ 5 ..] ;
18
24
19
25
let size = names. len ( ) ;
20
- let index = * names. entry ( key ) . or_insert ( size) ;
26
+ let index = * names. entry ( prefix ) . or_insert ( size) ;
21
27
22
- cache. insert ( index, value . unsigned :: < u64 > ( ) ) ;
28
+ cache. insert ( index, suffix . unsigned ( ) ) ;
23
29
}
24
30
25
- for line in suffix. lines ( ) {
26
- let tokens: Vec < _ > = line. split ( ' ' ) . collect ( ) ;
27
- let op = tokens[ 1 ] ;
28
-
31
+ for & [ left, kind, right, _, to] in gates {
29
32
let size = names. len ( ) ;
30
- let left = * names. entry ( tokens [ 0 ] ) . or_insert ( size) ;
33
+ let left = * names. entry ( left ) . or_insert ( size) ;
31
34
32
35
let size = names. len ( ) ;
33
- let right = * names. entry ( tokens [ 2 ] ) . or_insert ( size) ;
36
+ let right = * names. entry ( right ) . or_insert ( size) ;
34
37
35
38
let size = names. len ( ) ;
36
- let to = * names. entry ( tokens [ 4 ] ) . or_insert ( size) ;
39
+ let to = * names. entry ( to ) . or_insert ( size) ;
37
40
38
- ops. insert ( to, ( left, op , right) ) ;
41
+ ops. insert ( to, ( left, kind , right) ) ;
39
42
}
40
43
41
44
let mut result = 0 ;
@@ -50,105 +53,50 @@ pub fn part1(input: &str) -> u64 {
50
53
result
51
54
}
52
55
53
- pub fn part2 ( _input : & str ) -> String {
54
- // let (_, suffix) = input.split_once("\n\n").unwrap();
55
- // let mut wires = FastMap::new();
56
-
57
- // println!("digraph G {{");
58
-
59
- // for i in 0..46 {
60
- // if i < 45 {
61
- // let key = format!("x{i:02}");
62
- // println!(" {} [pos=\"{},{}!\"]", key, i * 2, 5);
63
- // let value = key.clone();
64
- // wires.insert(key, vec![value]);
65
-
66
- // let key = format!("y{i:02}");
67
- // println!(" {} [pos=\"{},{}!\"]", key, i * 2 + 1, 5);
68
- // let value = key.clone();
69
- // wires.insert(key, vec![value]);
70
- // }
71
-
72
- // let key = format!("z{i:02}");
73
- // println!(" {} [pos=\"{},{}!\"]", key, i * 2, 0);
74
- // }
75
-
76
- // println!();
77
-
78
- // for (name, line) in suffix.lines().enumerate() {
79
- // let tokens: Vec<_> = line.split(' ').collect();
80
- // let [_, _, _, _, to] = tokens[..] else { unreachable!() };
81
- // wires.entry(String::from(to)).or_insert_with(Vec::new).push(format!("{name}"));
82
- // }
83
-
84
- // let mut second = FastMap::new();
85
-
86
- // for (name, line) in suffix.lines().enumerate() {
87
- // let tokens: Vec<_> = line.split(' ').collect();
88
- // let [left, op, right, _, to] = tokens[..] else { unreachable!() };
89
-
90
- // let shape = match op {
91
- // "AND" => "square",
92
- // "OR" => "hexagon",
93
- // "XOR" => "triangle",
94
- // _ => unreachable!(),
95
- // };
96
-
97
- // if left.starts_with('x') || right.starts_with('x') {
98
- // let i: usize = left.unsigned();
99
- // if op == "AND" {
100
- // println!("{} [pos=\"{},{}!\"]", name, i * 2 + 1, 4);
101
- // second.insert(to, i);
102
- // }
103
- // if op == "XOR" {
104
- // println!("{} [pos=\"{},{}!\"]", name, i * 2, 4);
105
- // second.insert(to, i);
106
- // }
107
- // }
108
- // if to.starts_with('z') {
109
- // let i: usize = to.unsigned();
110
- // println!("{} [pos=\"{},{}!\"]", name, i * 2, 1);
111
- // }
112
-
113
- // println!(" {name} [shape={shape}]");
114
- // for edge in &wires[&String::from(left)] {
115
- // println!(" {edge} -> {name} [label=\"{left}\"]");
116
- // }
117
- // for edge in &wires[&String::from(right)] {
118
- // println!(" {edge} -> {name} [label=\"{right}\"]");
119
- // }
120
- // }
121
-
122
- // for (name, line) in suffix.lines().enumerate() {
123
- // let tokens: Vec<_> = line.split(' ').collect();
124
- // let [left, op, right, _, _] = tokens[..] else { unreachable!() };
125
-
126
- // if op == "AND" {
127
- // if let Some(i) = second.get(left) {
128
- // println!("{} [pos=\"{},{}!\"]", name, i * 2 + 1, 3);
129
- // }
130
- // if let Some(i) = second.get(right) {
131
- // println!("{} [pos=\"{},{}!\"]", name, i * 2 + 1, 3);
132
- // }
133
- // }
134
- // if op == "OR" {
135
- // if let Some(i) = second.get(left) {
136
- // println!("{} [pos=\"{},{}!\"]", name, i * 2 + 1, 2);
137
- // }
138
- // if let Some(i) = second.get(right) {
139
- // println!("{} [pos=\"{},{}!\"]", name, i * 2 + 1, 2);
140
- // }
141
- // }
142
- // }
143
-
144
- // for i in 0..46 {
145
- // let key = format!("z{i:02}");
146
- // for edge in &wires[&key] {
147
- // println!(" {edge} -> {key}");
148
- // }
149
- // }
150
-
151
- String :: from ( "n/a" )
56
+ pub fn part2 ( input : & Input < ' _ > ) -> String {
57
+ let ( _, gates) = input;
58
+
59
+ let mut lookup = FastSet :: new ( ) ;
60
+ let mut swapped = FastSet :: new ( ) ;
61
+
62
+ for & [ left, kind, right, _, _] in gates {
63
+ lookup. insert ( ( left, kind) ) ;
64
+ lookup. insert ( ( right, kind) ) ;
65
+ }
66
+
67
+ for & [ left, kind, right, _, to] in gates {
68
+ if kind == "AND" {
69
+ // Check that all AND gates point to an OR, except for first AND.
70
+ if left != "x00" && right != "x00" && !lookup. contains ( & ( to, "OR" ) ) {
71
+ swapped. insert ( to) ;
72
+ }
73
+ }
74
+
75
+ if kind == "OR" {
76
+ // Check that only XOR gates point to output, except for last carry which is OR.
77
+ if to. starts_with ( 'z' ) && to != "z45" {
78
+ swapped. insert ( to) ;
79
+ }
80
+ }
81
+
82
+ if kind == "XOR" {
83
+ if left. starts_with ( 'x' ) || right. starts_with ( 'x' ) {
84
+ // Check that first level XOR points to second level XOR, except for first XOR.
85
+ if left != "x00" && right != "x00" && !lookup. contains ( & ( to, "XOR" ) ) {
86
+ swapped. insert ( to) ;
87
+ }
88
+ } else {
89
+ // Second level XOR must point to output.
90
+ if !to. starts_with ( 'z' ) {
91
+ swapped. insert ( to) ;
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ let mut result: Vec < _ > = swapped. into_iter ( ) . collect ( ) ;
98
+ result. sort_unstable ( ) ;
99
+ result. join ( "," )
152
100
}
153
101
154
102
fn helper (
0 commit comments