A "word wheel" is a type of word game commonly found on the "puzzle" page of
newspapers. You are presented with nine letters arranged in a circle or 3×3
grid. The objective is to find as many words as you can using only the letters
contained in the wheel or grid. Each word must contain the letter in the centre
of the wheel or grid. Usually there will be a minimum word length of 3 or 4
characters. Each letter may only be used as many times as it appears in the wheel
or grid.



An example
 


 N

 D

 E


 O

 K

 G


 E

 L

 W



Task

Write a program to solve the above "word wheel" puzzle.

Specifically:

 Find all words of 3 or more letters using only the letters in the string   ndeokgelw.
 All words must contain the central letter   K.
 Each letter may be used only as many times as it appears in the string.
 For this task we'll use lowercase English letters exclusively.


A "word" is defined to be any string contained in the file located at   http://wiki.puzzlers.org/pub/wordlists/unixdict.txt.

If you prefer to use a different dictionary,   please state which one you have used.

Optional extra

Word wheel puzzles usually state that there is at least one nine-letter word to be found.
Using the above dictionary, find the 3x3 grids with at least one nine-letter
solution that generate the largest number of words of three or more letters.




Other tasks related to string operations:

Metrics
 Array length
 String length
 Copy a string
 Empty string  (assignment)
Counting
 Word frequency
 Letter frequency
 Jewels and stones
 I before E except after C
 Bioinformatics/base count
 Count occurrences of a substring
 Count how many vowels and consonants occur in a string
Remove/replace
 XXXX redacted
 Conjugate a Latin verb
 Remove vowels from a string
 String interpolation (included)
 Strip block comments
 Strip comments from a string
 Strip a set of characters from a string
 Strip whitespace from a string -- top and tail
 Strip control codes and extended characters from a string
Anagrams/Derangements/shuffling
 Word wheel
 ABC problem
 Sattolo cycle
 Knuth shuffle
 Ordered words
 Superpermutation minimisation
 Textonyms (using a phone text pad)
 Anagrams
 Anagrams/Deranged anagrams
 Permutations/Derangements
Find/Search/Determine
 ABC words
 Odd words
 Word ladder
 Semordnilap
 Word search
 Wordiff  (game)
 String matching
 Tea cup rim text
 Alternade words
 Changeable words
 State name puzzle
 String comparison
 Unique characters
 Unique characters in each string
 Extract file extension
 Levenshtein distance
 Palindrome detection
 Common list elements
 Longest common suffix
 Longest common prefix
 Compare a list of strings 
 Longest common substring
 Find common directory path
 Words from neighbour ones
 Change e letters to i in words
 Non-continuous subsequences
 Longest common subsequence
 Longest palindromic substrings
 Longest increasing subsequence
 Words containing "the" substring
 Sum of the digits of n is substring of n
 Determine if a string is numeric
 Determine if a string is collapsible
 Determine if a string is squeezable
 Determine if a string has all unique characters
 Determine if a string has all the same characters
 Longest substrings without repeating characters
 Find words which contains all the vowels
 Find words which contains most consonants
 Find words which contains more than 3 vowels
 Find words which first and last three letters are equals
 Find words which odd letters are consonants and even letters are vowels or vice_versa
Formatting
 Substring
 Rep-string
 Word wrap
 String case
 Align columns
 Literals/String
 Repeat a string
 Brace expansion
 Brace expansion using ranges
 Reverse a string
 Phrase reversals
 Comma quibbling
 Special characters
 String concatenation
 Substring/Top and tail
 Commatizing numbers
 Reverse words in a string
 Suffixation of decimal numbers
 Long literals, with continuations 
 Numerical and alphabetical suffixes
 Abbreviations, easy
 Abbreviations, simple
 Abbreviations, automatic
Song lyrics/poems/Mad Libs/phrases
 Mad Libs
 Magic 8-ball
 99 Bottles of Beer
 The Name Game (a song)
 The Old lady swallowed a fly
 The Twelve Days of Christmas
Tokenize
 Text between
 Tokenize a string
 Word break problem
 Tokenize a string with escaping
 Split a character string based on change of character
Sequences
 Show ASCII table
 De Bruijn sequences
 Self-referential sequences
 Generate lower case ASCII alphabet




puts:	equ	9		; CP/M syscall to print string
fopen:	equ	15		; CP/M syscall to open a file
fread:	equ	20		; CP/M syscall to read from file
FCB1:	equ	5Ch		; First FCB (input file)
DTA:	equ	80h		; Disk transfer address
	org	100h
	;;;	Make wheel (2nd argument) lowercase and store it
	lxi	d,DTA+1		; Start of command line arguments
scan:	inr	e		; Scan until we find a space
	rz			; Stop if not found in 128 bytes
	ldax	d
	cpi	' '		; Found it?
	jnz	scan		; If not, try again
	inx	d		; If so, wheel starts 1 byte onwards
	lxi	h,wheel		; Space for wheel
	lxi	b,920h		; B=9 (chars), C=20 (case bit)
whlcpy:	ldax	d		; Get wheel character
	ora	c		; Make lowercase
	mov	m,a		; Store
	inx	d		; Increment both pointers
	inx	h
	dcr	b		; Decrement counter
	jnz	whlcpy		; While not zero, copy next character
	;;;	Open file in FCB1
	mvi	e,FCB1		; D is already 0
	mvi	c,fopen
	call	5		; Returns A=FF on error
	inr	a		; If incrementing A gives zero,
	jz	err		; then print error and stop
	lxi	h,word		; Copy into word
	;;;	Read a 128-byte block from the file
block:	push	h		; Keep word pointer
	lxi	d,FCB1		; Read from file
	mvi	c,fread
	call	5
	pop	h		; Restore word pointer
	dcr	a		; A=1 = EOF
	rz			; If so, stop.
	inr	a		; Otherwise, A<>0 = error
	jnz	err
	lxi	d,DTA		; Start reading at DTA
char:	ldax	d		; Get character
	mov	m,a		; Store in word
	cpi	26		; EOF reached?
	rz			; Then stop
	cpi	10		; End of line reached?
	jz	ckword		; Then we have a full word
	inx	h		; Increment word pointer
nxchar:	inr	e		; Increment DTA pointer (low byte)
	jz	block		; If rollover, get next block
	jmp	char		; Otherwise, handle next character in block
	;;;	Check if current word is valid
ckword:	push	d		; Keep block pointer
	lxi	d,wheel		; Copy the wheel
	lxi	h,wcpy
	mvi	c,9		; 9 characters
cpyw:	ldax	d		; Get character
	mov	m,a		; Store in copy
	inx	h		; Increment pointers
	inx	d
	dcr	c		; Decrement counters
	jnz	cpyw		; Done yet?
	lxi	d,word		; Read from current word
wrdch:	ldax	d		; Get character
	cpi	32		; Check if <32
	jc	wdone		; If so, the word is done
	lxi	h,wcpy		; Check against the wheel letters
	mvi	b,9
wlch:	cmp	m		; Did we find it?
	jz	findch
	inx	h		; If not, try next character in wheel
	dcr	b		; As long as there are characters
	jnz	wlch		; If no match, this word is invalid
wnext:	pop	d		; Restore block pointer
	lxi	h,word		; Start reading new word
	jmp	nxchar		; Continue with character following word
findch:	mvi	m,0		; Found a match - set char to 0
	inx	d		; And look at next character in word
	jmp	wrdch
wdone:	lda	wcpy+4		; Word is done - check if middle char used
	ana	a		; If not, the word is invalid
	jnz	wnext
	lxi	h,wcpy		; See how many characters used
	lxi	b,9		; C=9 (counter), B=0 (used)
whtest:	mov	a,m		; Get wheel character
	ana	a		; Is it zero?
	jnz	$+4		; If not, skip next instr
	inr	b		; If so, count it
	inx	h		; Next wheel character
	dcr	c		; Decrement counter
	jnz	whtest
	mvi	a,2		; At least 3 characters must be used
	cmp	b
	jnc	wnext		; If not, the word is invalid
	xchg			; If so, the word _is_ valid, pointer in HL
	mvi	m,13		; add CR
	inx	h
	mvi	m,10		; and LF
	inx	h
	mvi	m,'$'		; and the CP/M string terminator
	lxi	d,word		; Then print the word
	mvi	c,puts
	call	5
	jmp	wnext
err:	lxi	d,errs		; Print file error
	mvi	c,puts
	jz	5
errs:	db	'File error$'	; Error message
wheel:	ds	9		; Room for wheel
wcpy:	ds	9		; Copy of wheel (to mark characters used)
word:	equ	$		; Room for current word