Skip to content

Commit 3f28c45

Browse files
authored
feat: add java solution to lc problem: No.0488 (#2430)
No.0488.Zuma Game
1 parent 81266b1 commit 3f28c45

File tree

3 files changed

+495
-0
lines changed

3 files changed

+495
-0
lines changed

solution/0400-0499/0488.Zuma Game/README.md

+166
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,172 @@ class Solution:
118118
return -1
119119
```
120120

121+
```java
122+
class Solution {
123+
public int findMinStep(String board, String hand) {
124+
final Zuma zuma = Zuma.create(board, hand);
125+
final HashSet<Long> visited = new HashSet<>();
126+
final ArrayList<Zuma> init = new ArrayList<>();
127+
128+
visited.add(zuma.board());
129+
init.add(zuma);
130+
return bfs(init, 0, visited);
131+
}
132+
133+
private int bfs(ArrayList<Zuma> curr, int k, HashSet<Long> visited) {
134+
if (curr.isEmpty()) {
135+
return -1;
136+
}
137+
138+
final ArrayList<Zuma> next = new ArrayList<>();
139+
140+
for (Zuma zuma : curr) {
141+
ArrayList<Zuma> neib = zuma.getNextLevel(k, visited);
142+
if (neib == null) {
143+
return k + 1;
144+
}
145+
146+
next.addAll(neib);
147+
}
148+
return bfs(next, k + 1, visited);
149+
}
150+
}
151+
152+
record Zuma(long board, long hand) {
153+
public static Zuma create(String boardStr, String handStr) {
154+
return new Zuma(Zuma.encode(boardStr, false), Zuma.encode(handStr, true));
155+
}
156+
157+
public ArrayList<Zuma> getNextLevel(int depth, HashSet<Long> visited) {
158+
final ArrayList<Zuma> next = new ArrayList<>();
159+
final ArrayList<long[]> handList = this.buildHandList();
160+
final long[] boardList = new long[32];
161+
final int size = this.buildBoardList(boardList);
162+
163+
for (long[] pair : handList) {
164+
for (int i = 0; i < size; ++i) {
165+
final long rawBoard = pruningCheck(boardList[i], pair[0], i * 3, depth);
166+
if (rawBoard == -1) {
167+
continue;
168+
}
169+
170+
final long nextBoard = updateBoard(rawBoard);
171+
if (nextBoard == 0) {
172+
return null;
173+
}
174+
175+
if (pair[1] == 0 || visited.contains(nextBoard)) {
176+
continue;
177+
}
178+
179+
visited.add(nextBoard);
180+
next.add(new Zuma(nextBoard, pair[1]));
181+
}
182+
}
183+
return next;
184+
}
185+
186+
private long pruningCheck(long insBoard, long ball, int pos, int depth) {
187+
final long L = (insBoard >> (pos + 3)) & 0x7;
188+
final long R = (insBoard >> (pos - 3)) & 0x7;
189+
190+
if (depth == 0 && (ball != R) && (L != R) || depth > 0 && (ball != R)) {
191+
return -1;
192+
}
193+
return insBoard | (ball << pos);
194+
}
195+
196+
private long updateBoard(long board) {
197+
long stack = 0;
198+
199+
for (int i = 0; i < 64; i += 3) {
200+
final long curr = (board >> i) & 0x7;
201+
final long top = (stack) &0x7;
202+
203+
// pop (if possible)
204+
if ((top > 0) && (curr != top) && (stack & 0x3F) == ((stack >> 3) & 0x3F)) {
205+
stack >>= 9;
206+
if ((stack & 0x7) == top) stack >>= 3;
207+
}
208+
209+
if (curr == 0) {
210+
// done
211+
break;
212+
}
213+
// push and continue
214+
stack = (stack << 3) | curr;
215+
}
216+
return stack;
217+
}
218+
219+
private ArrayList<long[]> buildHandList() {
220+
final ArrayList<long[]> handList = new ArrayList<>();
221+
long prevBall = 0;
222+
long ballMask = 0;
223+
224+
for (int i = 0; i < 16; i += 3) {
225+
final long currBall = (this.hand >> i) & 0x7;
226+
if (currBall == 0) {
227+
break;
228+
}
229+
230+
if (currBall != prevBall) {
231+
prevBall = currBall;
232+
handList.add(
233+
new long[] {currBall, ((this.hand >> 3) & ~ballMask) | (this.hand & ballMask)});
234+
}
235+
ballMask = (ballMask << 3) | 0x7;
236+
}
237+
return handList;
238+
}
239+
240+
private int buildBoardList(long[] buffer) {
241+
int ptr = 0;
242+
long ballMask = 0x7;
243+
long insBoard = this.board << 3;
244+
buffer[ptr++] = insBoard;
245+
246+
while (true) {
247+
final long currBall = this.board & ballMask;
248+
if (currBall == 0) {
249+
break;
250+
}
251+
252+
ballMask <<= 3;
253+
insBoard = (insBoard | currBall) & ~ballMask;
254+
buffer[ptr++] = insBoard;
255+
}
256+
return ptr;
257+
}
258+
259+
private static long encode(String stateStr, boolean sortFlag) {
260+
final char[] stateChars = stateStr.toCharArray();
261+
if (sortFlag) {
262+
Arrays.sort(stateChars);
263+
}
264+
265+
long stateBits = 0;
266+
for (char ch : stateChars) {
267+
stateBits = (stateBits << 3) | Zuma.encode(ch);
268+
}
269+
return stateBits;
270+
}
271+
272+
private static long encode(char ch) {
273+
return switch (ch) {
274+
case 'R' -> 0x1;
275+
case 'G' -> 0x2;
276+
case 'B' -> 0x3;
277+
case 'W' -> 0x4;
278+
case 'Y' -> 0x5;
279+
case ' ' -> 0x0;
280+
default ->
281+
throw new IllegalArgumentException("Invalid char: " + ch);
282+
};
283+
}
284+
}
285+
```
286+
121287
<!-- tabs:end -->
122288

123289
<!-- end -->

solution/0400-0499/0488.Zuma Game/README_EN.md

+166
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,172 @@ class Solution:
102102
return -1
103103
```
104104

105+
```java
106+
class Solution {
107+
public int findMinStep(String board, String hand) {
108+
final Zuma zuma = Zuma.create(board, hand);
109+
final HashSet<Long> visited = new HashSet<>();
110+
final ArrayList<Zuma> init = new ArrayList<>();
111+
112+
visited.add(zuma.board());
113+
init.add(zuma);
114+
return bfs(init, 0, visited);
115+
}
116+
117+
private int bfs(ArrayList<Zuma> curr, int k, HashSet<Long> visited) {
118+
if (curr.isEmpty()) {
119+
return -1;
120+
}
121+
122+
final ArrayList<Zuma> next = new ArrayList<>();
123+
124+
for (Zuma zuma : curr) {
125+
ArrayList<Zuma> neib = zuma.getNextLevel(k, visited);
126+
if (neib == null) {
127+
return k + 1;
128+
}
129+
130+
next.addAll(neib);
131+
}
132+
return bfs(next, k + 1, visited);
133+
}
134+
}
135+
136+
record Zuma(long board, long hand) {
137+
public static Zuma create(String boardStr, String handStr) {
138+
return new Zuma(Zuma.encode(boardStr, false), Zuma.encode(handStr, true));
139+
}
140+
141+
public ArrayList<Zuma> getNextLevel(int depth, HashSet<Long> visited) {
142+
final ArrayList<Zuma> next = new ArrayList<>();
143+
final ArrayList<long[]> handList = this.buildHandList();
144+
final long[] boardList = new long[32];
145+
final int size = this.buildBoardList(boardList);
146+
147+
for (long[] pair : handList) {
148+
for (int i = 0; i < size; ++i) {
149+
final long rawBoard = pruningCheck(boardList[i], pair[0], i * 3, depth);
150+
if (rawBoard == -1) {
151+
continue;
152+
}
153+
154+
final long nextBoard = updateBoard(rawBoard);
155+
if (nextBoard == 0) {
156+
return null;
157+
}
158+
159+
if (pair[1] == 0 || visited.contains(nextBoard)) {
160+
continue;
161+
}
162+
163+
visited.add(nextBoard);
164+
next.add(new Zuma(nextBoard, pair[1]));
165+
}
166+
}
167+
return next;
168+
}
169+
170+
private long pruningCheck(long insBoard, long ball, int pos, int depth) {
171+
final long L = (insBoard >> (pos + 3)) & 0x7;
172+
final long R = (insBoard >> (pos - 3)) & 0x7;
173+
174+
if (depth == 0 && (ball != R) && (L != R) || depth > 0 && (ball != R)) {
175+
return -1;
176+
}
177+
return insBoard | (ball << pos);
178+
}
179+
180+
private long updateBoard(long board) {
181+
long stack = 0;
182+
183+
for (int i = 0; i < 64; i += 3) {
184+
final long curr = (board >> i) & 0x7;
185+
final long top = (stack) &0x7;
186+
187+
// pop (if possible)
188+
if ((top > 0) && (curr != top) && (stack & 0x3F) == ((stack >> 3) & 0x3F)) {
189+
stack >>= 9;
190+
if ((stack & 0x7) == top) stack >>= 3;
191+
}
192+
193+
if (curr == 0) {
194+
// done
195+
break;
196+
}
197+
// push and continue
198+
stack = (stack << 3) | curr;
199+
}
200+
return stack;
201+
}
202+
203+
private ArrayList<long[]> buildHandList() {
204+
final ArrayList<long[]> handList = new ArrayList<>();
205+
long prevBall = 0;
206+
long ballMask = 0;
207+
208+
for (int i = 0; i < 16; i += 3) {
209+
final long currBall = (this.hand >> i) & 0x7;
210+
if (currBall == 0) {
211+
break;
212+
}
213+
214+
if (currBall != prevBall) {
215+
prevBall = currBall;
216+
handList.add(
217+
new long[] {currBall, ((this.hand >> 3) & ~ballMask) | (this.hand & ballMask)});
218+
}
219+
ballMask = (ballMask << 3) | 0x7;
220+
}
221+
return handList;
222+
}
223+
224+
private int buildBoardList(long[] buffer) {
225+
int ptr = 0;
226+
long ballMask = 0x7;
227+
long insBoard = this.board << 3;
228+
buffer[ptr++] = insBoard;
229+
230+
while (true) {
231+
final long currBall = this.board & ballMask;
232+
if (currBall == 0) {
233+
break;
234+
}
235+
236+
ballMask <<= 3;
237+
insBoard = (insBoard | currBall) & ~ballMask;
238+
buffer[ptr++] = insBoard;
239+
}
240+
return ptr;
241+
}
242+
243+
private static long encode(String stateStr, boolean sortFlag) {
244+
final char[] stateChars = stateStr.toCharArray();
245+
if (sortFlag) {
246+
Arrays.sort(stateChars);
247+
}
248+
249+
long stateBits = 0;
250+
for (char ch : stateChars) {
251+
stateBits = (stateBits << 3) | Zuma.encode(ch);
252+
}
253+
return stateBits;
254+
}
255+
256+
private static long encode(char ch) {
257+
return switch (ch) {
258+
case 'R' -> 0x1;
259+
case 'G' -> 0x2;
260+
case 'B' -> 0x3;
261+
case 'W' -> 0x4;
262+
case 'Y' -> 0x5;
263+
case ' ' -> 0x0;
264+
default ->
265+
throw new IllegalArgumentException("Invalid char: " + ch);
266+
};
267+
}
268+
}
269+
```
270+
105271
<!-- tabs:end -->
106272

107273
<!-- end -->

0 commit comments

Comments
 (0)