-
Notifications
You must be signed in to change notification settings - Fork 5
/
scrabbleable.rebmu
123 lines (103 loc) · 3.73 KB
/
scrabbleable.rebmu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
Rebmu [
Title: {Scrabble-able}
Home: http://stackoverflow.com/a/3088746/211160
Purpose: {
Input: a list of words
Output: a legal arrangement for the words on a scrabble board (or
false if impossible). Format of output is entirely up to you, as long
as it is comprehensible. Bonus points for pretty printing. Scrabble
board size is unbounded, no un-listed words should be found in solution.
Examples:
input: {"alice", "bob", "eve"}
output: false
input: {"alice", "eve", "victoria"}
output: a|l|i|c|e
v|i|c|t|o|r|i|a
e
Invoke with:
rebmu/args %scrabbleable.rebmu ["alice" "bob" "eve"]
NOTE: This example appeared to work at one time, although I found
some test data it couldn't solve. So it was already broken somewhere.
The Rebmu language update which removed Rebmu-specific IF/UNLESS/EITHER
behaviors broke it. If you want to see it sort-of-working, revert back
to Rebmu before the IF/UNLESS/EITHER commit. The best idea I think
would probably be a fresh take now that Rebmu has evolved a bit; but
it wasn't worth holding up the important alignment change with Rebol.
}
]
; we use the space constant a lot, so it's worth it to define s to be space
Ssp
; N is the number of input strings
NlnA
; L is our longest string length
L00feZa[LmxLlnZ]
; V is our board size
; expression is v: 1 + (l - 1) * (ad eOD?n1[0] dv n 2)
; we add one because our loop doesn't do the theoretical minimum ++ v
Va2mpBKlADeOD?n01[0]dvN02
; M is our VxV board matrix, initially set to spaces
Mai~Vsi~Vs
; G is a "func" (not a "function") thus can write to the global variable M
; it takes a matrix to replace the matrix with and returns the old one
Ga&[ZcydM MaZ]
; F is the now common iterator finder for coordinates in a matrix
; modified so if you ask about out of range it always returns space
Fa|[ZpcMscA XfsA ZigX00[iZ[skZbkX]] iZ[iT?z[Zno]]eZz{ }]
; T is a "c|function", meaning it takes parameters A B C
;
; it tries to put the string A into the matrix at coordinates B with step
; offset C, and returns true if successful false if not
;
; * as written, will corrupt the board on failure, so save a copy
;
; (for horizontal placemement C = [1 0] and vertical placement C = [0 1])
; rule is that any non-space must match the word we're putting down
; also at least one such collision must happen for a true result
; (ignored by the first word placement)
;
; also we cannot make a continuation of an existing word
; (before first letter and after last must be space or board edge)
; points opposite a collision may be occupied on the other axis, but if there's
; not a collision then those points must be spaces
Tc|[
Xno
Q&[Z01br]
ieSfsFsbBc[w[Zf+A][
JfB KfsJeeSk[OrvCYcEEsFSfADbO[eeSfsFadBngO[chJz]q]q][X01iuKzQ]BadBc
]
ieSfsFb[a?XntZ]]
]
; R recursively applies itself for placing the words in A
; returns true if it succeeds
Ra|[
Q&[iU[br]]
eT?aON[
ZnxSBvL
rpXz[
rpYz[
O[0 1]
lp 2[
JgM ; save matrix copy
UeTfsAre[xY]o[rNXa][eH?a[rNXa]no]
eU00[gJ]
rvO
q
]
q
]
q
]
u
]
]
; Print the result
eRa[
; if r(a) returned true... then
; clean up the unneccessary whitespace on the board
JmW[Kf+J][iM?trtK[JbkJtkJ]]
; and injects i|n|t|e|r|m|e|d|i|a|t|e pipe characters as per problem spec
feZm[Kf+Zw[Jf+Z][ZnxISbkZegKs[egJs{|}s]s Kj]prHDz]
][
; otherwise print false
pr{false}
]