Sokoban: Difference between revisions
Content added Content deleted
(→{{header|Perl}}: Totally rewrote the perl solution.) |
(Safer second D entry) |
||
Line 923: | Line 923: | ||
enum Cell : ubyte { space, wall, player, box } |
enum Cell : ubyte { space, wall, player, box } |
||
alias CellIndex = ushort; |
|||
alias |
alias Thash = uint; |
||
hash_t = uint; |
|||
Line 931: | Line 930: | ||
/// indices of player and boxes. |
/// indices of player and boxes. |
||
struct State { // Variable length struct. |
struct State { // Variable length struct. |
||
Thash h; |
|||
State* prev, next, qNext; |
State* prev, next, qNext; |
||
CellIndex[0] c_; |
CellIndex[0] c_; |
||
CellIndex get(in size_t i) inout pure nothrow { |
|||
return |
return c_.ptr[i]; |
||
} |
|||
void set(in size_t i, in CellIndex v) pure nothrow { |
|||
c_.ptr[i] = v; |
|||
} |
} |
||
CellIndex[] slice(in size_t i, in size_t j) pure nothrow { |
CellIndex[] slice(in size_t i, in size_t j) pure nothrow { |
||
return |
return c_.ptr[i .. j]; |
||
} |
} |
||
} |
} |
||
Line 950: | Line 953: | ||
__gshared State* blockRoot, blockHead, nextLevel, done; |
__gshared State* blockRoot, blockHead, nextLevel, done; |
||
__gshared State*[] buckets; |
__gshared State*[] buckets; |
||
__gshared |
__gshared Thash hashSize, fillLimit, filled; |
||
Line 1,058: | Line 1,061: | ||
i.markLive; |
i.markLive; |
||
if (s[i] == '$' || s[i] == '*') |
if (s[i] == '$' || s[i] == '*') |
||
state. |
state.set(++j, i); |
||
else if (s[i] == '@' || s[i] == '+') |
else if (s[i] == '@' || s[i] == '+') |
||
state. |
state.set(0, i); |
||
} |
} |
||
Line 1,070: | Line 1,073: | ||
void hash(State* s, in size_t nBoxes) pure nothrow { |
void hash(State* s, in size_t nBoxes) pure nothrow { |
||
if (!s.h) { |
if (!s.h) { |
||
Thash ha = 0; |
|||
foreach (immutable i; 0 .. nBoxes + 1) |
foreach (immutable i; 0 .. nBoxes + 1) |
||
ha = s. |
ha = s.get(i) + 31 * ha; |
||
s.h = ha; |
s.h = ha; |
||
} |
} |
||
Line 1,097: | Line 1,100: | ||
buckets[oldSize .. hashSize] = null; |
buckets[oldSize .. hashSize] = null; |
||
immutable |
immutable Thash bits = hashSize - 1; |
||
foreach (immutable i; 0 .. oldSize) { |
foreach (immutable i; 0 .. oldSize) { |
||
auto head = buckets[i]; |
auto head = buckets[i]; |
||
Line 1,133: | Line 1,136: | ||
extendTable; |
extendTable; |
||
immutable |
immutable Thash i = s.h & (hashSize - 1); |
||
s.next = buckets[i]; |
s.next = buckets[i]; |
||
Line 1,143: | Line 1,146: | ||
bool success(in State* s) nothrow { |
bool success(in State* s) nothrow { |
||
foreach (immutable i; 1 .. nBoxes + 1) |
foreach (immutable i; 1 .. nBoxes + 1) |
||
if (!goals[s. |
if (!goals[s.get(i)]) |
||
return false; |
return false; |
||
return true; |
return true; |
||
Line 1,150: | Line 1,153: | ||
State* moveMe(State* s, in int dy, in int dx) nothrow { |
State* moveMe(State* s, in int dy, in int dx) nothrow { |
||
immutable int y = s. |
immutable int y = s.get(0) / w; |
||
immutable int x = s. |
immutable int x = s.get(0) % w; |
||
immutable int y1 = y + dy; |
immutable int y1 = y + dy; |
||
immutable int x1 = x + dx; |
immutable int x1 = x + dx; |
||
Line 1,161: | Line 1,164: | ||
int atBox = 0; |
int atBox = 0; |
||
foreach (immutable i; 1 .. nBoxes + 1) |
foreach (immutable i; 1 .. nBoxes + 1) |
||
if (s. |
if (s.get(i) == c1) { |
||
atBox = i; |
atBox = i; |
||
break; |
break; |
||
Line 1,172: | Line 1,175: | ||
return null; |
return null; |
||
foreach (immutable i; 1 .. nBoxes + 1) |
foreach (immutable i; 1 .. nBoxes + 1) |
||
if (s. |
if (s.get(i) == c2) |
||
return null; |
return null; |
||
} |
} |
||
Line 1,179: | Line 1,182: | ||
n.slice(1, nBoxes + 1)[] = s.slice(1, nBoxes + 1); |
n.slice(1, nBoxes + 1)[] = s.slice(1, nBoxes + 1); |
||
n. |
n.set(0, cast(CellIndex)c1); |
||
if (atBox) |
if (atBox) |
||
n. |
n.set(atBox, cast(CellIndex)c2); |
||
// Bubble sort. |
// Bubble sort. |
||
Line 1,188: | Line 1,191: | ||
CellIndex t = 0; |
CellIndex t = 0; |
||
foreach (immutable j; 1 .. i) { |
foreach (immutable j; 1 .. i) { |
||
if (n. |
if (n.get(j) > n.get(j + 1)) { |
||
t = n. |
t = n.get(j); |
||
n. |
n.set(j, n.get(j + 1)); |
||
n. |
n.set(j + 1, t); |
||
} |
} |
||
} |
} |
||
Line 1,235: | Line 1,238: | ||
b[] = cast(typeof(b))board[]; |
b[] = cast(typeof(b))board[]; |
||
b[s. |
b[s.get(0)] = Cell.player; |
||
foreach (immutable i; 1 .. nBoxes + 1) |
foreach (immutable i; 1 .. nBoxes + 1) |
||
b[s. |
b[s.get(i)] = Cell.box; |
||
foreach (immutable i, immutable bi; b) { |
foreach (immutable i, immutable bi; b) { |