1
1
import static java .util .stream .Collectors .toList ;
2
2
3
+ import java .util .Arrays ;
3
4
import java .util .List ;
4
- import java .util .function .Function ;
5
- import java .util .stream .IntStream ;
6
- import java .util .stream .Stream ;
5
+ import java .util .function .IntFunction ;
7
6
8
7
import com .github .pareronia .aoc .Grid .Cell ;
9
- import com .github .pareronia .aoc .IntGrid ;
8
+ import com .github .pareronia .aoc .StringOps ;
9
+ import com .github .pareronia .aoc .StringOps .StringSplit ;
10
10
import com .github .pareronia .aoc .solution .Sample ;
11
11
import com .github .pareronia .aoc .solution .Samples ;
12
12
import com .github .pareronia .aoc .solution .SolutionBase ;
@@ -32,19 +32,80 @@ protected List<Instruction> parseInput(final List<String> inputs) {
32
32
return inputs .stream ().map (Instruction ::fromInput ).collect (toList ());
33
33
}
34
34
35
+ private int solve (final List <Instruction > instructions , final Mode mode ) {
36
+ final int [] lights = new int [1_000_000 ];
37
+ for (final Instruction instruction : instructions ) {
38
+ instruction .action .apply (
39
+ lights , instruction .start , instruction .end , mode );
40
+ }
41
+ return Arrays .stream (lights ).sum ();
42
+ }
43
+
35
44
@ Override
36
- public Integer solvePart1 (final List <Instruction > input ) {
37
- final Grid lights = new Grid (c -> 1 , c -> 0 , c -> c == 1 ? 0 : 1 );
38
- lights .processInstructions (input );
39
- return (int ) lights .getAllLightValues ().filter (l -> l == 1 ).count ();
45
+ public Integer solvePart1 (final List <Instruction > instructions ) {
46
+ return solve (instructions , Mode .MODE_1 );
40
47
}
41
48
42
49
@ Override
43
- public Integer solvePart2 (final List <Instruction > input ) {
44
- final Grid lights = new Grid (c -> c + 1 , c -> Math .max (c - 1 , 0 ), c -> c + 2 );
45
- lights .processInstructions (input );
46
- return lights .getAllLightValues ().sum ();
50
+ public Integer solvePart2 (final List <Instruction > instructions ) {
51
+ return solve (instructions , Mode .MODE_2 );
47
52
}
53
+
54
+ enum Mode { MODE_1 , MODE_2 }
55
+
56
+ record Instruction (Action action , Cell start , Cell end ) {
57
+ public static Instruction fromInput (final String input ) {
58
+ final String s = input .replace ("turn " , "turn_" );
59
+ final StringSplit splits = StringOps .splitOnce (s , " through " );
60
+ final StringSplit actionAndStartSplits
61
+ = StringOps .splitOnce (splits .left (), " " );
62
+ return new Instruction (
63
+ Action .fromString (actionAndStartSplits .left ()),
64
+ Cell .fromString (actionAndStartSplits .right ()),
65
+ Cell .fromString (splits .right ()));
66
+ }
67
+
68
+ enum Action {
69
+ TURN_ON , TURN_OFF , TOGGLE ;
70
+
71
+ public static Action fromString (final String s ) {
72
+ return switch (s ) {
73
+ case "turn_on" -> TURN_ON ;
74
+ case "turn_off" -> TURN_OFF ;
75
+ default -> TOGGLE ;
76
+ };
77
+ }
78
+
79
+ public void apply (
80
+ final int [] grid ,
81
+ final Cell start ,
82
+ final Cell end ,
83
+ final Mode mode
84
+ ) {
85
+ final IntFunction <Integer > f = switch (this ) {
86
+ case TURN_ON -> switch (mode ) {
87
+ case MODE_1 : yield v -> 1 ;
88
+ case MODE_2 : yield v -> v + 1 ;
89
+ };
90
+ case TURN_OFF -> switch (mode ) {
91
+ case MODE_1 : yield v -> 0 ;
92
+ case MODE_2 : yield v -> Math .max (v - 1 , 0 );
93
+ };
94
+ case TOGGLE -> switch (mode ) {
95
+ case MODE_1 : yield v -> v == 1 ? 0 : 1 ;
96
+ case MODE_2 : yield v -> v + 2 ;
97
+ };
98
+ };
99
+ final int rStart = start .getRow () * 1_000 ;
100
+ final int rEnd = end .getRow () * 1_000 ;
101
+ for (int r = rStart ; r <= rEnd ; r += 1_000 ) {
102
+ for (int idx = r + start .getCol (); idx <= r + end .getCol (); idx ++) {
103
+ grid [idx ] = f .apply (grid [idx ]);
104
+ }
105
+ }
106
+ } //apply
107
+ } // Action
108
+ } // Instruction
48
109
49
110
@ Override
50
111
@ Samples ({
@@ -66,61 +127,4 @@ public static void main(final String[] args) throws Exception {
66
127
private static final String TEST3 = "turn off 499,499 through 500,500" ;
67
128
private static final String TEST4 = "turn on 0,0 through 0,0" ;
68
129
private static final String TEST5 = "toggle 0,0 through 999,999" ;
69
-
70
- private static final class Grid {
71
- private final IntGrid lights = new IntGrid (new int [1_000 ][1_000 ]);
72
- private final Function <Integer , Integer > turnOn ;
73
- private final Function <Integer , Integer > turnOff ;
74
- private final Function <Integer , Integer > toggle ;
75
-
76
- protected Grid (
77
- final Function <Integer , Integer > turnOn ,
78
- final Function <Integer , Integer > turnOff ,
79
- final Function <Integer , Integer > toggle
80
- ) {
81
- this .turnOn = turnOn ;
82
- this .turnOff = turnOff ;
83
- this .toggle = toggle ;
84
- }
85
-
86
- public IntStream getAllLightValues () {
87
- return Stream .of (this .lights .getValues ()).flatMapToInt (IntStream ::of );
88
- }
89
-
90
- public void processInstructions (final List <Instruction > instructions ) {
91
- for (final Instruction instruction : instructions ) {
92
- final Function <Integer , Integer > action =
93
- instruction .action == Instruction .Action .TURN_ON
94
- ? this .turnOn
95
- : instruction .action == Instruction .Action .TURN_OFF
96
- ? this .turnOff
97
- : this .toggle ;
98
- for (int rr = instruction .start .getRow (); rr <= instruction .end .getRow (); rr ++) {
99
- for (int cc = instruction .start .getCol (); cc <= instruction .end .getCol (); cc ++) {
100
- this .lights .setValue (Cell .at (rr , cc ), action .apply (this .lights .getValue (Cell .at (rr , cc ))));
101
- }
102
- }
103
- }
104
- }
105
- }
106
-
107
- record Instruction (Action action , Cell start , Cell end ) {
108
-
109
- enum Action { TURN_ON , TURN_OFF , TOGGLE }
110
-
111
- public static Instruction fromInput (final String input ) {
112
- final String s = input .replace ("turn " , "turn_" );
113
- final String [] splits = s .split (" through " );
114
- final String [] actionAndStartSplits = splits [0 ].split (" " );
115
- final Cell start = Cell .fromString (actionAndStartSplits [1 ]);
116
- final Cell end = Cell .fromString (splits [1 ]);
117
- if ("turn_on" .equals (actionAndStartSplits [0 ])) {
118
- return new Instruction (Action .TURN_ON , start , end );
119
- } else if ("turn_off" .equals (actionAndStartSplits [0 ])) {
120
- return new Instruction (Action .TURN_OFF , start , end );
121
- } else {
122
- return new Instruction (Action .TOGGLE , start , end );
123
- }
124
- }
125
- }
126
130
}
0 commit comments