Contributor: ANDY KURNIA { Here's a solution! I'm using Borland Pascal 7.0 and MS-DOS, so see the comments to adjust it to other compilers and platforms (especially the Assembly language part...) The code may be cut/copied and pasted anywhere you like it. No royalty is needed. (I can't believe I said that, but it's true!) Save the code as PUZZLE.PAS and create your own dictionary file as WORDS.DIC in the current directory. A sample WORDS.DIC (generated from my big WORDS.DIC using PUZZLE SHIFTED) is also given. Note that PUZZLE.PAS is case-insensitive, you can use upper/lowercase. Every word should be on its own line and must not have spaces in it. Sorting is optional, the output depends on the order found in the file. After you save PUZZLE.PAS and the sample WORDS.DIC, try PUZZLE SHIFT to get 13 words. I have a big WORDS.DIC containing approximately 91,529 words. It is 979,045 bytes. PKZIP -ex produces a 251,926 bytes ZIP file. UUENCODE-ing the ZIP file gives 6 files totaling 353,616 bytes. Anyone interested in it may mail me. Note: The file was not created by me, although I was the one who sorted it. I'm sure I found it somewhere on the net, but I forgot where exactly it was. START OF WORDS.DIC [420 bytes under MS-DOS, CRLF pair is used] deft dei deist des die dies diet diets dif dis dish dite edit edith edits edt eft efts est fed feds fetid fetish fid fie fish fished fist fisted fit fits heft hefts heist hid hide hides hie hied hies his hist hit hits ides set she shed shied shift shifted sid side sift sifted sit site sited std stied ted the thief this tide tides tie tied ties tis END OF WORDS.DIC START OF PUZZLE.PAS [2,913 bytes under MS-DOS, CRLF pair is used] { If you aren't using Borland Pascal 7.0 and MS-DOS, try using just $I-. } {$A+,B-,D-,E-,F-,G+,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V+,X+,Y-} {$M 1024,0,0} Program Puzzle; Var F : Text; S, W : String; I : LongInt; { If you aren't using Borland Pascal 7.0 and MS-DOS try this instead: Function StrLwr(S : String) : String; Var I : Byte; Begin For I := 1 To Length(S) Do If (S[I] >= 'A') And (S[I] <= 'Z') Then Inc(S[I], $20); StrLwr := S End; StrLwr(S) returns S in all lowercase. } Function StrLwr(Const S : String) : String; Assembler; Asm PUSH DS LDS SI, S LES DI, @Result CLD LODSB STOSB XCHG CX, AX MOV CH, 0 JCXZ @3 @1: LODSB CMP AL, 'A' JB @2 CMP AL, 'Z' JA @2 OR AL, 20H @2: STOSB LOOP @1 @3: POP DS End; { If you aren't using Borland Pascal 7.0 change the function header to: Function IsSolution(S, W : String) : Boolean; (Borland Pascal 7.0 tip:) Using Const on String arguments saves stack space and disables modifying the String. (To modify Const S : String you use String((@S)^) in place of S.) S is the list of legal characters. W is a legal word from the dictionary file. IsSolution(S, W) returns True if W can be formed from the letters in S. This time S may have unused letters. If must use all letters from S change: IsSolution := True (last line of function) to: IsSolution := S[0] = #0 or: IsSolution := S = '' (The former is faster, the latter is simpler.) } Function IsSolution(S : String; Const W : String) : Boolean; Var I, J : Byte; Begin IsSolution := False; For I := 1 To Length(W) Do Begin J := Pos(W[I], S); If J = 0 Then Exit; Delete(S, J, 1) End; IsSolution := True End; { The main block. } Begin If ParamCount <> 1 Then Begin WriteLn('PUZZLE - Idea from Campbell Basset'); WriteLn('Created by Andy Kurnia in 1996'); WriteLn; WriteLn('Syntax: PUZZLE listofletters'); WriteLn('Argument: case-insensitive, example allows max. two E'); WriteLn('Example: PUZZLE RSTLNEfghiev'); WriteLn('Requires: WORDS.DIC (text file containing words)'); Halt(1) End; Assign(F, 'WORDS.DIC'); Reset(F); If IOResult <> 0 Then Begin WriteLn('WORDS.DIC not found!'); Halt(2) End; S := StrLwr(ParamStr(1)); I := 0; While Not EOF(F) Do Begin ReadLn(F, W); If IsSolution(S, StrLwr(W)) Then Begin Inc(I); WriteLn(I : 10, '. ', W) End End; Close(F); If I = 0 Then WriteLn('No words found.') Else If I = 1 Then WriteLn('1 word found.') Else WriteLn(I, ' words found.') End.