@@ -14,58 +14,83 @@ public static void main(final String[] args) throws IOException {
14
14
.map (Instruction ::fromLine )
15
15
.collect (Collectors .toUnmodifiableList ());
16
16
17
- outer :
18
- for ( int i = instructions .size (); --i >= 0 ; ) {
17
+ instructions :
18
+ // "exactly one instruction is corrupted" - try them all
19
+ for (int i = instructions .size (); --i >= 0 ; ) {
19
20
final var toReplace = instructions .get (i );
20
21
21
- if ( "acc" .equalsIgnoreCase ( toReplace .operation ) ) {
22
+ if (toReplace .operation == Operation .acc ) {
23
+ // "No acc instructions were harmed in the corruption of this boot code."
22
24
continue ;
23
25
}
24
- final var opposite = "nop" . equalsIgnoreCase ( toReplace .operation ) ? " jmp" : " nop" ;
26
+ final var opposite = toReplace .operation == Operation . nop ? Operation . jmp : Operation . nop ;
25
27
final var replacement = new Instruction (opposite , toReplace .argument );
26
28
27
29
int total = 0 ;
28
30
int index = 0 ;
29
31
30
32
final var visited = new HashSet <Integer >();
31
- while ( index < instructions .size () ) {
33
+ // "The program is supposed to terminate by attempting to execute an instruction immediately after the last instruction in the file."
34
+ while (index < instructions .size ()) {
32
35
final var instruction = index == i ? replacement : instructions .get (index );
33
- if ( visited .contains ( index ) ) {
34
- continue outer ;
36
+ if (visited .contains (index )) {
37
+ // replacing the instruction causes an infinite loop
38
+ // try replacing a different one
39
+ // NB: Simply re-visiting this instruction is an infinite loop because the argument to each instruction is constant and never dependent on the value of "total"
40
+ continue instructions ;
35
41
}
36
42
visited .add (index );
37
- switch ( instruction .operation ) {
38
- case "acc" :
39
- total += instruction .argument ;
40
- case "nop" :
41
- index ++;
42
- break ;
43
- case "jmp" :
44
- index += instruction .argument ;
45
- break ;
46
- default :
47
- throw new IllegalStateException ("Invalid op: " + instruction .operation );
48
- }
43
+ total = instruction .updateTotal (total );
44
+ index = instruction .updateIndex (index );
49
45
}
50
46
System .out .println ("part 2: " + total );
51
- return ;
47
+ return ; // "exactly one instruction is corrupted"
52
48
}
53
49
}
54
50
}
55
51
56
- public static class Instruction
57
- {
58
- private final String operation ;
52
+ public enum Operation {
53
+ acc {
54
+ public int updateTotal (final int previousTotal , final int argument ) {
55
+ return previousTotal + argument ;
56
+ }
57
+ },
58
+ nop ,
59
+ jmp {
60
+ public int updateIndex (final int previousIndex , final int argument ) {
61
+ return previousIndex + argument ;
62
+ }
63
+ };
64
+
65
+ public int updateIndex (final int previousIndex , final int argument ) {
66
+ return previousIndex + 1 ;
67
+ }
68
+
69
+ public int updateTotal (final int previousTotal , final int argument ) {
70
+ return previousTotal ;
71
+ }
72
+ }
73
+
74
+ public static class Instruction {
75
+ private final Operation operation ;
59
76
private final int argument ;
60
77
61
- public Instruction (final String operation , final int argument ) {
78
+ public Instruction (final Operation operation , final int argument ) {
62
79
this .operation = operation ;
63
80
this .argument = argument ;
64
81
}
65
82
66
83
public static Instruction fromLine (final String line ) {
67
- final var components = line .split (" " );
68
- return new Instruction (components [ 0 ], Integer .parseInt ( components [ 1 ] ) );
84
+ final var components = line .split (" " , 2 );
85
+ return new Instruction (Operation .valueOf (components [0 ]), Integer .parseInt (components [1 ]));
86
+ }
87
+
88
+ public int updateIndex (final int previousIndex ) {
89
+ return operation .updateIndex (previousIndex , argument );
90
+ }
91
+
92
+ public int updateTotal (final int previousTotal ) {
93
+ return operation .updateTotal (previousTotal , argument );
69
94
}
70
95
}
71
96
}
0 commit comments