11//! [Day 21: Chronal Conversion](https://adventofcode.com/2018/day/21)
22
33use std:: collections:: HashSet ;
4+ use std:: fmt:: Error ;
45
5- const OPCODES : [ & str ; 16 ] = [
6- "addi" , "addr" , "bani" , "banr" , "bori" , "borr" , "eqir" , "eqri" , "eqrr" , "gtir" , "gtri" , "gtrr" ,
7- "muli" , "mulr" , "seti" , "setr" ,
8- ] ;
9-
10- fn emulate ( opcode : & ' static str , a : u64 , b : u64 , c : u64 , regs : & mut [ u64 ] ) {
11- regs[ c as usize ] = match opcode {
12- "addr" => regs[ a as usize ] + regs[ b as usize ] ,
13- "addi" => regs[ a as usize ] + b,
14- "mulr" => regs[ a as usize ] * regs[ b as usize ] ,
15- "muli" => regs[ a as usize ] * b,
16- "banr" => regs[ a as usize ] & regs[ b as usize ] ,
17- "bani" => regs[ a as usize ] & b,
18- "borr" => regs[ a as usize ] | regs[ b as usize ] ,
19- "bori" => regs[ a as usize ] | b,
20- "setr" => regs[ a as usize ] ,
21- "seti" => a,
22- "gtir" => u64:: from ( a > regs[ b as usize ] ) ,
23- "gtri" => u64:: from ( regs[ a as usize ] > b) ,
24- "gtrr" => u64:: from ( regs[ a as usize ] > regs[ b as usize ] ) ,
25- "eqir" => u64:: from ( a == regs[ b as usize ] ) ,
26- "eqri" => u64:: from ( regs[ a as usize ] == b) ,
27- "eqrr" => u64:: from ( regs[ a as usize ] == regs[ b as usize ] ) ,
28- _ => panic ! ( "bad opcode {opcode}" ) ,
29- } ;
6+ #[ derive( Debug ) ]
7+ enum OpCodes {
8+ Addi ,
9+ Addr ,
10+ Bani ,
11+ Banr ,
12+ Bori ,
13+ Borr ,
14+ Eqir ,
15+ Eqri ,
16+ Eqrr ,
17+ Gtir ,
18+ Gtri ,
19+ Gtrr ,
20+ Muli ,
21+ Mulr ,
22+ Seti ,
23+ Setr ,
24+ }
25+
26+ impl std:: str:: FromStr for OpCodes {
27+ type Err = Box < Error > ;
28+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
29+ let opcode = match s {
30+ "addr" => OpCodes :: Addr ,
31+ "addi" => OpCodes :: Addi ,
32+ "mulr" => OpCodes :: Mulr ,
33+ "muli" => OpCodes :: Muli ,
34+ "banr" => OpCodes :: Banr ,
35+ "bani" => OpCodes :: Bani ,
36+ "borr" => OpCodes :: Borr ,
37+ "bori" => OpCodes :: Bori ,
38+ "setr" => OpCodes :: Setr ,
39+ "seti" => OpCodes :: Seti ,
40+ "gtir" => OpCodes :: Gtir ,
41+ "gtri" => OpCodes :: Gtri ,
42+ "gtrr" => OpCodes :: Gtrr ,
43+ "eqir" => OpCodes :: Eqir ,
44+ "eqri" => OpCodes :: Eqri ,
45+ "eqrr" => OpCodes :: Eqrr ,
46+ _ => panic ! ( "unknown opcode {s}" ) ,
47+ } ;
48+
49+ Ok ( opcode)
50+ }
51+ }
52+
53+ impl OpCodes {
54+ fn emulate ( & self , a : u64 , b : u64 , c : u64 , regs : & mut [ u64 ] ) {
55+ regs[ c as usize ] = match & self {
56+ OpCodes :: Addr => regs[ a as usize ] + regs[ b as usize ] ,
57+ OpCodes :: Addi => regs[ a as usize ] + b,
58+ OpCodes :: Mulr => regs[ a as usize ] * regs[ b as usize ] ,
59+ OpCodes :: Muli => regs[ a as usize ] * b,
60+ OpCodes :: Banr => regs[ a as usize ] & regs[ b as usize ] ,
61+ OpCodes :: Bani => regs[ a as usize ] & b,
62+ OpCodes :: Borr => regs[ a as usize ] | regs[ b as usize ] ,
63+ OpCodes :: Bori => regs[ a as usize ] | b,
64+ OpCodes :: Setr => regs[ a as usize ] ,
65+ OpCodes :: Seti => a,
66+ OpCodes :: Gtir => u64:: from ( a > regs[ b as usize ] ) ,
67+ OpCodes :: Gtri => u64:: from ( regs[ a as usize ] > b) ,
68+ OpCodes :: Gtrr => u64:: from ( regs[ a as usize ] > regs[ b as usize ] ) ,
69+ OpCodes :: Eqir => u64:: from ( a == regs[ b as usize ] ) ,
70+ OpCodes :: Eqri => u64:: from ( regs[ a as usize ] == b) ,
71+ OpCodes :: Eqrr => u64:: from ( regs[ a as usize ] == regs[ b as usize ] ) ,
72+ } ;
73+ }
3074}
3175
32- #[ derive( Debug ) ]
3376struct Instr {
34- opcode : & ' static str ,
77+ opcode : OpCodes ,
3578 a : u64 ,
3679 b : u64 ,
3780 c : u64 ,
3881}
3982
4083impl Instr {
4184 fn run ( & self , regs : & mut [ u64 ] ) {
42- emulate ( self . opcode , self . a , self . b , self . c , regs) ;
85+ self . opcode . emulate ( self . a , self . b , self . c , regs) ;
86+ }
87+ }
88+
89+ impl std:: str:: FromStr for Instr {
90+ type Err = Box < Error > ;
91+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
92+ let s: Vec < _ > = s. split_ascii_whitespace ( ) . collect ( ) ;
93+
94+ let opcode = s[ 0 ] . parse ( ) . unwrap ( ) ;
95+ let a = s[ 1 ] . parse ( ) . unwrap ( ) ;
96+ let b = s[ 2 ] . parse ( ) . unwrap ( ) ;
97+ let c = s[ 3 ] . parse ( ) . unwrap ( ) ;
98+
99+ Ok ( Instr { opcode, a, b, c } )
43100 }
44101}
45102
46103impl std:: fmt:: Display for Instr {
47104 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
48- write ! ( f, "{} {} {} {}" , self . opcode, self . a, self . b, self . c)
105+ write ! ( f, "{:? } {} {} {}" , self . opcode, self . a, self . b, self . c)
49106 }
50107}
51108
@@ -72,16 +129,7 @@ impl Puzzle {
72129 if let Some ( value) = line. strip_prefix ( "#ip " ) {
73130 self . ip_reg = value. parse :: < usize > ( ) . unwrap ( ) ;
74131 } else {
75- let line: Vec < _ > = line. split_ascii_whitespace ( ) . collect ( ) ;
76-
77- let opcode = OPCODES . iter ( ) . find ( |& & opcode| opcode == line[ 0 ] ) . unwrap ( ) ;
78- let a = line[ 1 ] . parse :: < u64 > ( ) . unwrap ( ) ;
79- let b = line[ 2 ] . parse :: < u64 > ( ) . unwrap ( ) ;
80- let c = line[ 3 ] . parse :: < u64 > ( ) . unwrap ( ) ;
81-
82- let instr = Instr { opcode, a, b, c } ;
83-
84- self . program . push ( instr) ;
132+ self . program . push ( line. parse ( ) . unwrap ( ) ) ;
85133 }
86134 }
87135 }
0 commit comments