For training purposes in REXX, let's try to create simple but effective REXX code to solve classical task: placing given list of words into rectangular matrix, with at least one common letter of every word with another one.
The recommended interface is like this
Placing 15 words into matrix 13 X 21 filled with RANDOM
Successfully attempted at 775 step
B A H R A I N E Q A V B T
A F G H A N I S T A N K H
N Q A N T I G U A S L R X
G F R B K C A S Z J V L D
L T M A U S T R I A S Q M
A Z E R B A I J A N R V T
D C N B B U G Y P I V J D
E F I U A S L W H B O N S
S R A D H T L V K L V F W
H N N A A R G E N T I N A
S O D H M A S E G F L U J
J A O U A L Q H Y M X D P
S V R T S I Q I G U S T D
L J R K F A E F W J J Z J
W O A L G E R I A C K B A
A N L A D L N A T N H L X
D X B F U R V Y W A E G Z
P G A C F S A C F Y R M X
K A N G O L A S M G B V J
H Q I Z O O M V P O Q J U
W K A E V Y X Q M N U L J
READY
END
Placing 15 words into matrix 13 X 21 filled with DOTS
Successfully attempted at 775 step
B A H R A I N . . . . . .
A F G H A N I S T A N . .
N . A N T I G U A . . . .
G . R B . . . . . . . . .
L . M A U S T R I A . . .
A Z E R B A I J A N . . .
D . N B B U . . . . . . .
E . I U A S . . . . . . .
S . A D H T . . . . . . .
H . N A A R G E N T I N A
. . D . M A . . . . . . .
. . O . A L . . . . . . .
. . R . S I . . . . . . .
. . R . . A . . . . . . .
. . A L G E R I A . . . .
. . L . . . . . . . . . .
. . B . . . . . . . . . .
. . A . . . . . . . . . .
. A N G O L A . . . . . .
. . I . . . . . . . . . .
. . A . . . . . . . . . .
READY
END
My code (normally aligned, and separated) is 152 lines.
15-50 words are allocated in few moments.
Tried to use it up to 199 input words into matrix 34x50; that took several minutes to complete.
/* initial words positioning */
Do iW = 1 To WordList.0
Parse Var WordList.iW lW W .
If (iW // 2 > 0) Then
WordList.iW = lW W 1 0 (XSize - lW + 1) YSize
Else
WordList.iW = lW W 1 0 XSize (YSize - lW + 1)
End
iW = 1 /* indexWord is running back and forth between 1 and list size */
Do stepW = 1 By 1 While iW > 0 & iW <= WordList.0
/* re-calculate next position for the current word */
Parse Var WordList.iW lW W xPos yPos xMax yMax /* get last values */
If yPos < yMax Then Do /* shift vertically */
WordList.iW = lW W xPos (yPos + 1) xMax yMax /* save updates */
End
Else If xPos < xMax Then Do /* shift horizontally */
WordList.iW = lW W (xPos + 1) 1 xMax yMax /* save updates */
End
Else Do /* get back to previous word */
WordList.iW = lW W 1 0 xMax yMax /* reset, and save updates */
iW = iW - 1 /* previous word index */
Iterate stepW /* back to shifting previous word */
End
Parse Var WordList.iW lW W xPos yPos xMax yMax /* re-new values */
If WordFits?(iW) Then Do /* this word succeeded? */
If iW >= WordList.0 Then Do /* is it the last word? */
Say "Successfully attempted at" stepW "step"
Return 1 /* success */
End
iW = iW + 1 /* shift to the next word */
End
End stepW
Say "Failed to match after" stepW "steps"
Matrix. = ''
CrossCount = (nW = 1) /* first word intercross not required */
Call PlacePreviousWords(nW - 1)
Parse Var WordList.nW lW W X Y .
Do iL = 1 to lW
NewLetter = Substr( W, iL, 1 )
If Matrix.X.Y = '' Then
Matrix.X.Y = NewLetter /* empty space occupied */
Else If Matrix.X.Y = NewLetter Then
CrossCount = CrossCount + 1 /* good cross-letter */
Else
Return 0 /* letters conflict, break test */
If (nW // 2 > 0) Then X = X + 1 /* go horizontally */
Else Y = Y + 1 /* go vertically */
End iL
Return (CrossCount > 0) /* only accept crossed words (after word 1) */
/**********************************************************************/
PlacePreviousWords: procedure expose Matrix. WordList.
Arg nW
Do iW = 1 to nW
Parse Var WordList.iW lW W X Y . /* handle current word */
Do iL = 1 to lW
NewLetter = Substr( W, iL, 1 )
Matrix.X.Y = NewLetter
If (iW // 2 > 0) Then X = X + 1
Else Y = Y + 1
End iL
End iW
If FillMode = 'RANDOM' Then
Do i = 1 To XSize
Do j = 1 To YSize
Rand = Random( 1, 26 )
Matrix.i.j = Substr( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', Rand, 1 )
End j
End i
Else
Matrix. = '.'
Call PlacePreviousWords WordList.0
Do y = 1 to YSize
OneLine = ''
Do x = 1 to XSize
OneLine = OneLine Matrix.x.y
End x
Say OneLine
End y