Word wheel: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
(145 intermediate revisions by 33 users not shown)
Line 1:
{{draft task|Puzzles}}
 
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 3x33×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
Line 9:
or grid.
 
For example:
 
;An example: <big><b>
{| class="wikitable"
::::::: {| class="wikitable"
| N
| D
Line 23:
| L
| W
|}
</b></big>
 
;Task:
Write a program to solve the above "word wheel" puzzle.
 
Specifically:
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 "&nbsp; '''ndeokgelw"'''.
:* All words must contain the central letter "k"&nbsp; <big>'''K'''.</big>
:* 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
A "word" is defined to be any string contained in the file located at &nbsp; http://wiki.puzzlers.org/pub/wordlists/unixdict.txt.
dictionary please state which one you have used.
<br>If you prefer to use a different dictionary, &nbsp; 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.
 
 
{{Template:Strings}}
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">V GRID =
‘N D E
O K G
E L W’
 
F getwords()
V words = File(‘unixdict.txt’).read().lowercase().split("\n")
R words.filter(w -> w.len C 3..9)
 
F solve(grid, dictionary)
DefaultDict[Char, Int] gridcount
L(g) grid
gridcount[g]++
 
F check_word(word)
DefaultDict[Char, Int] lcount
L(l) word
lcount[l]++
L(l, c) lcount
I c > @gridcount[l]
R 1B
R 0B
 
V mid = grid[4]
R dictionary.filter(word -> @mid C word & !@check_word(word))
 
V chars = GRID.lowercase().split_py().join(‘’)
V found = solve(chars, dictionary' getwords())
print(found.join("\n"))</syntaxhighlight>
 
{{out}}
<pre>
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
 
=={{header|8080 Assembly}}==
 
This program runs under CP/M, and takes the dictionary file and wheel definition
as arguments. The file is processed block by block, so it can be arbitrarily large
(the given ~206kb <code>unixdict.txt</code> works fine).
 
<syntaxhighlight lang="8080asm">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</syntaxhighlight>
 
{{out}}
 
<pre>A>wheel unixdict.txt ndeokgelw
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
 
=={{header|APL}}==
{{works with|Dyalog APL}}
<syntaxhighlight lang="apl">wordwheel←{
words←((~∊)∘⎕TC⊆⊢) 80 ¯1⎕MAP ⍵
match←{
0=≢⍵:1
~(⊃⍵)∊⍺:0
⍺[(⍳⍴⍺)~⍺⍳⊃⍵]∇1↓⍵
}
middle←(⌈0.5×≢)⊃⊢
words←((middle ⍺)∊¨words)/words
words←(⍺∘match¨words)/words
(⍺⍺≤≢¨words)/words
}</syntaxhighlight>
{{out}}
<pre> 'ndeokgelw' (3 wordwheel) 'unixdict.txt'
eke elk keel keen keg ken keno knee kneel knew know knowledge kong leek week wok woke </pre>
=={{header|AppleScript}}==
<syntaxhighlight lang="applescript">use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
 
 
------------------------ WORD WHEEL ----------------------
 
-- wordWheelMatches :: NSString -> [String] -> String -> String
on wordWheelMatches(lexicon, wordWheelRows)
set wheelGroups to group(sort(characters of ¬
concat(wordWheelRows)))
script isWheelWord
on |λ|(w)
script available
on |λ|(a, b)
length of a ≤ length of b
end |λ|
end script
script used
on |λ|(grp)
w contains item 1 of grp
end |λ|
end script
all(my identity, ¬
zipWith(available, ¬
group(sort(characters of w)), ¬
filter(used, wheelGroups)))
end |λ|
end script
set matches to filter(isWheelWord, ¬
filteredLines(wordWheelPreFilter(wordWheelRows), lexicon))
(length of matches as text) & " matches:" & ¬
linefeed & linefeed & unlines(matches)
end wordWheelMatches
 
 
-- wordWheelPreFilter :: [String] -> String
on wordWheelPreFilter(wordWheelRows)
set pivot to item 2 of item 2 of wordWheelRows
set charSet to nub(concat(wordWheelRows))
"(2 < self.length) and (self contains '" & pivot & "') " & ¬
"and not (self matches '^.*[^" & charSet & "].*$') "
end wordWheelPreFilter
 
 
--------------------------- TEST -------------------------
on run
set fpWordList to scriptFolder() & "unixdict.txt"
if doesFileExist(fpWordList) then
wordWheelMatches(readFile(fpWordList), ¬
{"nde", "okg", "elw"})
else
display dialog "Word list not found in script folder:" & ¬
linefeed & tab & fpWordList
end if
end run
 
 
 
----------- GENERIC :: FILTERED LINES FROM FILE ----------
 
-- doesFileExist :: FilePath -> IO Bool
on doesFileExist(strPath)
set ca to current application
set oPath to (ca's NSString's stringWithString:strPath)'s ¬
stringByStandardizingPath
set {bln, int} to (ca's NSFileManager's defaultManager's ¬
fileExistsAtPath:oPath isDirectory:(reference))
bln and (int ≠ 1)
end doesFileExist
 
 
-- filteredLines :: String -> NString -> [a]
on filteredLines(predicateString, s)
-- A list of lines filtered by an NSPredicate string
set ca to current application
set predicate to ca's NSPredicate's predicateWithFormat:predicateString
set array to ca's NSArray's ¬
arrayWithArray:(s's componentsSeparatedByString:(linefeed))
(array's filteredArrayUsingPredicate:(predicate)) as list
end filteredLines
 
 
-- readFile :: FilePath -> IO NSString
on readFile(strPath)
set ca to current application
set e to reference
set {s, e} to (ca's NSString's ¬
stringWithContentsOfFile:((ca's NSString's ¬
stringWithString:strPath)'s ¬
stringByStandardizingPath) ¬
encoding:(ca's NSUTF8StringEncoding) |error|:(e))
if missing value is e then
s
else
(localizedDescription of e) as string
end if
end readFile
 
 
-- scriptFolder :: () -> IO FilePath
on scriptFolder()
-- The path of the folder containing this script
try
tell application "Finder" to ¬
POSIX path of ((container of (path to me)) as alias)
on error
display dialog "Script file must be saved"
end try
end scriptFolder
 
 
------------------------- GENERIC ------------------------
 
-- Tuple (,) :: a -> b -> (a, b)
on Tuple(a, b)
-- Constructor for a pair of values,
-- possibly of two different types.
{type:"Tuple", |1|:a, |2|:b, length:2}
end Tuple
 
 
-- all :: (a -> Bool) -> [a] -> Bool
on all(p, xs)
-- True if p holds for every value in xs
tell mReturn(p)
set lng to length of xs
repeat with i from 1 to lng
if not |λ|(item i of xs, i, xs) then return false
end repeat
true
end tell
end all
 
 
-- concat :: [[a]] -> [a]
-- concat :: [String] -> String
on concat(xs)
set lng to length of xs
if 0 < lng and string is class of (item 1 of xs) then
set acc to ""
else
set acc to {}
end if
repeat with i from 1 to lng
set acc to acc & item i of xs
end repeat
acc
end concat
 
 
-- eq (==) :: Eq a => a -> a -> Bool
on eq(a, b)
a = b
end eq
 
 
-- filter :: (a -> Bool) -> [a] -> [a]
on filter(p, xs)
tell mReturn(p)
set lst to {}
set lng to length of xs
repeat with i from 1 to lng
set v to item i of xs
if |λ|(v, i, xs) then set end of lst to v
end repeat
if {text, string} contains class of xs then
lst as text
else
lst
end if
end tell
end filter
 
 
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
 
 
-- group :: Eq a => [a] -> [[a]]
on group(xs)
script eq
on |λ|(a, b)
a = b
end |λ|
end script
groupBy(eq, xs)
end group
 
 
-- groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
on groupBy(f, xs)
-- Typical usage: groupBy(on(eq, f), xs)
set mf to mReturn(f)
script enGroup
on |λ|(a, x)
if length of (active of a) > 0 then
set h to item 1 of active of a
else
set h to missing value
end if
if h is not missing value and mf's |λ|(h, x) then
{active:(active of a) & {x}, sofar:sofar of a}
else
{active:{x}, sofar:(sofar of a) & {active of a}}
end if
end |λ|
end script
if length of xs > 0 then
set dct to foldl(enGroup, {active:{item 1 of xs}, sofar:{}}, rest of xs)
if length of (active of dct) > 0 then
sofar of dct & {active of dct}
else
sofar of dct
end if
else
{}
end if
end groupBy
 
 
-- identity :: a -> a
on identity(x)
-- The argument unchanged.
x
end identity
 
 
-- length :: [a] -> Int
on |length|(xs)
set c to class of xs
if list is c or string is c then
length of xs
else
(2 ^ 29 - 1) -- (maxInt - simple proxy for non-finite)
end if
end |length|
 
 
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
 
 
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function
-- lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn
 
 
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
-- The list obtained by applying f
-- to each element of xs.
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
 
 
-- nub :: [a] -> [a]
on nub(xs)
nubBy(eq, xs)
end nub
 
 
-- nubBy :: (a -> a -> Bool) -> [a] -> [a]
on nubBy(f, xs)
set g to mReturn(f)'s |λ|
script notEq
property fEq : g
on |λ|(a)
script
on |λ|(b)
not fEq(a, b)
end |λ|
end script
end |λ|
end script
script go
on |λ|(xs)
if (length of xs) > 1 then
set x to item 1 of xs
{x} & go's |λ|(filter(notEq's |λ|(x), items 2 thru -1 of xs))
else
xs
end if
end |λ|
end script
go's |λ|(xs)
end nubBy
 
 
 
-- sort :: Ord a => [a] -> [a]
on sort(xs)
((current application's NSArray's arrayWithArray:xs)'s ¬
sortedArrayUsingSelector:"compare:") as list
end sort
 
 
-- take :: Int -> [a] -> [a]
-- take :: Int -> String -> String
on take(n, xs)
if 0 < n then
items 1 thru min(n, length of xs) of xs
else
{}
end if
end take
 
 
-- unlines :: [String] -> String
on unlines(xs)
-- A single string formed by the intercalation
-- of a list of strings with the newline character.
set {dlm, my text item delimiters} to ¬
{my text item delimiters, linefeed}
set s to xs as text
set my text item delimiters to dlm
s
end unlines
 
 
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
set lng to min(|length|(xs), |length|(ys))
if 1 > lng then return {}
set xs_ to take(lng, xs) -- Allow for non-finite
set ys_ to take(lng, ys) -- generators like cycle etc
set lst to {}
tell mReturn(f)
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs_, item i of ys_)
end repeat
return lst
end tell
end zipWith</syntaxhighlight>
{{Out}}
<pre>17 matches:
 
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke</pre>
 
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">letters := ["N", "D", "E", "O", "K", "G", "E", "L", "W"]
 
FileRead, wList, % A_Desktop "\unixdict.txt"
result := ""
for word in Word_wheel(wList, letters, 3)
result .= word "`n"
MsgBox % result
return
 
Word_wheel(wList, letters, minL){
oRes := []
for i, w in StrSplit(wList, "`n", "`r")
{
if (StrLen(w) < minL)
continue
word := w
for i, l in letters
w := StrReplace(w, l,,, 1)
if InStr(word, letters[5]) && !StrLen(w)
oRes[word] := true
}
return oRes
}</syntaxhighlight>
{{out}}
<pre>eke
elk
k
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
ok
week
wok
woke</pre>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
# syntax: GAWK -f WORD_WHEEL.AWK letters unixdict.txt
# the required letter must be first
#
# example: GAWK -f WORD_WHEEL.AWK Kndeogelw unixdict.txt
#
BEGIN {
letters = tolower(ARGV[1])
required = substr(letters,1,1)
size = 3
ARGV[1] = ""
}
{ word = tolower($0)
leng_word = length(word)
if (word ~ required && leng_word >= size) {
hits = 0
for (i=1; i<=leng_word; i++) {
if (letters ~ substr(word,i,1)) {
hits++
}
}
if (leng_word == hits && hits >= size) {
for (i=1; i<=leng_word; i++) {
c = substr(word,i,1)
if (gsub(c,"&",word) > gsub(c,"&",letters)) {
next
}
}
words++
printf("%s ",word)
}
}
}
END {
printf("\nletters: %s, '%s' required, %d words >= %d characters\n",letters,required,words,size)
exit(0)
}
</syntaxhighlight>
{{out}}
<pre>
eke elk keel keen keg ken keno knee kneel knew know knowledge kong leek week wok woke
letters: kndeogelw, 'k' required, 17 words >= 3 characters
</pre>
 
=={{header|BASIC}}==
<syntaxhighlight lang="basic">10 DEFINT A-Z
20 DATA "ndeokgelw","unixdict.txt"
30 READ WH$, F$
40 OPEN "I",1,F$
50 IF EOF(1) THEN CLOSE 1: END
60 C$ = WH$
70 LINE INPUT #1, W$
80 FOR I=1 TO LEN(W$)
90 FOR J=1 TO LEN(C$)
100 IF MID$(W$,I,1)=MID$(C$,J,1) THEN MID$(C$,J,1)="@": GOTO 120
110 NEXT J: GOTO 50
120 NEXT I
130 IF MID$(C$,(LEN(C$)+1)/2,1)<>"@" GOTO 50
140 C=0: FOR I=1 TO LEN(C$): C=C-(MID$(C$,I,1)="@"): NEXT
150 IF C>=3 THEN PRINT W$,
160 GOTO 50</syntaxhighlight>
{{out}}
<pre>eke elk keel keen keg
ken keno knee kneel knew
know knowledge kong leek week
wok woke
</pre>
 
=={{header|BCPL}}==
<syntaxhighlight lang="bcpl">get "libhdr"
 
// Read word from selected input
let readword(v) = valof
$( let ch = ?
v%0 := 0
$( ch := rdch()
if ch = endstreamch then resultis false
if ch = '*N' then resultis true
v%0 := v%0 + 1
v%(v%0) := ch
$) repeat
$)
 
// Test word against wheel
let match(wheel, word) = valof
$( let wcopy = vec 2+9/BYTESPERWORD
for i = 0 to wheel%0 do wcopy%i := wheel%i
for i = 1 to word%0 do
$( let idx = ?
test valof
$( for j = 1 to wcopy%0 do
if word%i = wcopy%j then
$( idx := j
resultis true
$)
resultis false
$) then wcopy%idx := 0 // we've used this letter
else resultis false // word cannot be made
$)
resultis
wcopy%((wcopy%0+1)/2)=0 & // middle letter must be used
3 <= valof // at least 3 letters must be used
$( let count = 0
for i = 1 to wcopy%0 do
if wcopy%i=0 then count := count + 1
resultis count
$)
$)
 
// Test unixdict.txt against ndeokgelw
let start() be
$( let word = vec 2+64/BYTESPERWORD
let file = findinput("unixdict.txt")
let wheel = "ndeokgelw"
selectinput(file)
while readword(word) do
if match(wheel, word) do
writef("%S*N", word)
endread()
$)</syntaxhighlight>
{{out}}
<pre>eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke</pre>
 
=={{header|C}}==
<syntaxhighlight lang="c">#include <stdbool.h>
#include <stdio.h>
 
#define MAX_WORD 80
#define LETTERS 26
 
bool is_letter(char c) { return c >= 'a' && c <= 'z'; }
 
int index(char c) { return c - 'a'; }
 
void word_wheel(const char* letters, char central, int min_length, FILE* dict) {
int max_count[LETTERS] = { 0 };
for (const char* p = letters; *p; ++p) {
char c = *p;
if (is_letter(c))
++max_count[index(c)];
}
char word[MAX_WORD + 1] = { 0 };
while (fgets(word, MAX_WORD, dict)) {
int count[LETTERS] = { 0 };
for (const char* p = word; *p; ++p) {
char c = *p;
if (c == '\n') {
if (p >= word + min_length && count[index(central)] > 0)
printf("%s", word);
} else if (is_letter(c)) {
int i = index(c);
if (++count[i] > max_count[i]) {
break;
}
} else {
break;
}
}
}
}
 
int main(int argc, char** argv) {
const char* dict = argc == 2 ? argv[1] : "unixdict.txt";
FILE* in = fopen(dict, "r");
if (in == NULL) {
perror(dict);
return 1;
}
word_wheel("ndeokgelw", 'k', 3, in);
fclose(in);
return 0;
}</syntaxhighlight>
 
{{out}}
<pre>
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
 
=={{header|C++}}==
{{libheader|Boost}}
The puzzle parameters are hard-coded but could easily be replaced by e.g. command line arguments.
The puzzle parameters can be set with command line options. The default values are as per the task description.
<lang cpp>#include <array>
<syntaxhighlight lang="cpp">#include <array>
#include <iostream>
#include <fstream>
Line 44 ⟶ 930:
#include <string>
#include <vector>
#include <boost/program_options.hpp>
 
// A multiset specialized for strings consisting of lowercase
Line 49 ⟶ 936:
class letterset {
public:
letterset() {
count_.fill(0);
}
explicit letterset(const std::string& str) {
count_.fill(0);
for (char c : str) {
if add(c >= 'a' && c <= 'z');
++count_[c - 'a' + 1];
else
++count_[0];
}
}
bool contains(const letterset& set) const {
Line 66 ⟶ 952:
}
unsigned int count(char c) const {
ifreturn count_[index(c >= 'a' && c <= 'z')];
return count_[c - 'a' + 1];
return 0;
}
bool is_valid() const {
return count_[0] == 0;
}
void add(char c) {
++count_[index(c)];
}
private:
static bool is_letter(char c) { return c >= 'a' && c <= 'z'; }
static int index(char c) { return is_letter(c) ? c - 'a' + 1 : 0; }
// elements 1..26 contain the number of times each lowercase
// letter occurs in the word
Line 93 ⟶ 982:
}
 
using dictionary = std::vector<std::pair<std::string, letterset>>;
int main(int argc, char** argv) {
 
const int min_length = 3;
dictionary load_dictionary(const std::string& filename, int min_length,
const char* letters = "ndeokgelw";
int max_length) {
const char central_letter = 'k';
std::ifstream in(filename);
const char* dict(argc == 2 ? argv[1] : "unixdict.txt");
std::ifstreamif in(dict!in);
throw std::runtime_error("Cannot open file " + filename);
if (!in) {
std::cerr << "Cannot open file " << dict << '\n';
return 1;
}
letterset set(letters);
std::string word;
dictionary result;
std::map<size_t, std::vector<std::string>> words;
while (getline(in, word)) {
if (word.size() < min_length)
continue;
lettersetif subset(word.size() > max_length);
continue;
if (subset.count(central_letter) > 0 && set.contains(subset)) {
letterset set(word);
if (set.is_valid())
result.emplace_back(word, set);
}
return result;
}
 
void word_wheel(const dictionary& dict, const std::string& letters,
char central_letter) {
letterset set(letters);
if (central_letter == 0 && !letters.empty())
central_letter = letters.at(letters.size()/2);
std::map<size_t, std::vector<std::string>> words;
for (const auto& pair : dict) {
const auto& word = pair.first;
const auto& subset = pair.second;
if (subset.count(central_letter) > 0 && set.contains(subset))
words[word.size()].push_back(word);
}
}
size_t total = 0;
for (const auto& p : words) {
const auto& v = p.second;
auto n = v.size();
total += n;
std::cout << "Found " << n << " " << (n == 1 ? "word" : "words")
<< " of length " << p.first << ": "
<< join(v.begin(), v.end(), ", ") << '\n';
}
std::cout << "Number of words found: " << total << '\n';
return 0;
}
}</lang>
 
void find_max_word_count(const dictionary& dict, int word_length) {
size_t max_count = 0;
std::vector<std::pair<std::string, char>> max_words;
for (const auto& pair : dict) {
const auto& word = pair.first;
if (word.size() != word_length)
continue;
const auto& set = pair.second;
dictionary subsets;
for (const auto& p : dict) {
if (set.contains(p.second))
subsets.push_back(p);
}
letterset done;
for (size_t index = 0; index < word_length; ++index) {
char central_letter = word[index];
if (done.count(central_letter) > 0)
continue;
done.add(central_letter);
size_t count = 0;
for (const auto& p : subsets) {
const auto& subset = p.second;
if (subset.count(central_letter) > 0)
++count;
}
if (count > max_count) {
max_words.clear();
max_count = count;
}
if (count == max_count)
max_words.emplace_back(word, central_letter);
}
}
std::cout << "Maximum word count: " << max_count << '\n';
std::cout << "Words of " << word_length << " letters producing this count:\n";
for (const auto& pair : max_words)
std::cout << pair.first << " with central letter " << pair.second << '\n';
}
 
constexpr const char* option_filename = "filename";
constexpr const char* option_wheel = "wheel";
constexpr const char* option_central = "central";
constexpr const char* option_min_length = "min-length";
constexpr const char* option_part2 = "part2";
 
int main(int argc, char** argv) {
const int word_length = 9;
int min_length = 3;
std::string letters = "ndeokgelw";
std::string filename = "unixdict.txt";
char central_letter = 0;
bool do_part2 = false;
namespace po = boost::program_options;
po::options_description desc("Allowed options");
desc.add_options()
(option_filename, po::value<std::string>(), "name of dictionary file")
(option_wheel, po::value<std::string>(), "word wheel letters")
(option_central, po::value<char>(), "central letter (defaults to middle letter of word)")
(option_min_length, po::value<int>(), "minimum word length")
(option_part2, "include part 2");
 
try {
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, desc), vm);
po::notify(vm);
 
if (vm.count(option_filename))
filename = vm[option_filename].as<std::string>();
if (vm.count(option_wheel))
letters = vm[option_wheel].as<std::string>();
if (vm.count(option_central))
central_letter = vm[option_central].as<char>();
if (vm.count(option_min_length))
min_length = vm[option_min_length].as<int>();
if (vm.count(option_part2))
do_part2 = true;
 
auto dict = load_dictionary(filename, min_length, word_length);
// part 1
word_wheel(dict, letters, central_letter);
// part 2
if (do_part2) {
std::cout << '\n';
find_max_word_count(dict, word_length);
}
} catch (const std::exception& ex) {
std::cerr << ex.what() << '\n';
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}</syntaxhighlight>
 
{{out}}
Output including optional part 2:
<pre>
Found 5 words of length 3: eke, elk, keg, ken, wok
Line 130 ⟶ 1,127:
Found 1 word of length 5: kneel
Found 1 word of length 9: knowledge
Number of words found: 17
 
Maximum word count: 215
Words of 9 letters producing this count:
claremont with central letter a
spearmint with central letter a
</pre>
 
===Without external libraries===
<syntaxhighlight lang="c++">
#include <algorithm>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
 
int main() {
const std::string word_wheel_letters = "ndeokgelw";
const std::string middle_letter = word_wheel_letters.substr(4, 1);
 
std::vector<std::string> words;
std::fstream file_stream;
file_stream.open("../unixdict.txt");
std::string word;
while ( file_stream >> word ) {
words.emplace_back(word);
}
 
std::vector<std::string> correct_words;
for ( const std::string& word : words ) {
if ( 3 <= word.length() && word.length() <= 9 &&
word.find(middle_letter) != std::string::npos &&
word.find_first_not_of(word_wheel_letters) == std::string::npos ) {
 
correct_words.emplace_back(word);
}
}
 
for ( const std::string& correct_word : correct_words ) {
std::cout << correct_word << std::endl;
}
 
int32_t max_words_found = 0;
std::vector<std::string> best_words9;
std::vector<char> best_central_letters;
std::vector<std::string> words9;
for ( const std::string& word : words ) {
if ( word.length() == 9 ) {
words9.emplace_back(word);
}
}
 
for ( const std::string& word9 : words9 ) {
std::vector<char> distinct_letters(word9.begin(), word9.end());
std::sort(distinct_letters.begin(), distinct_letters.end());
distinct_letters.erase(std::unique(distinct_letters.begin(), distinct_letters.end()), distinct_letters.end());
 
for ( const char& letter : distinct_letters ) {
int32_t words_found = 0;
for ( const std::string& word : words ) {
if ( word.length() >= 3 && word.find(letter) != std::string::npos ) {
std::vector<char> letters = distinct_letters;
bool valid_word = true;
for ( const char& ch : word ) {
std::vector<char>::iterator iter = std::find(letters.begin(), letters.end(), ch);
int32_t index = ( iter == letters.end() ) ? -1 : std::distance(letters.begin(), iter);
if ( index == -1 ) {
valid_word = false;
break;
}
letters.erase(letters.begin() + index);
}
if ( valid_word ) {
words_found++;
}
}
}
 
if ( words_found > max_words_found ) {
max_words_found = words_found;
best_words9.clear();
best_words9.emplace_back(word9);
best_central_letters.clear();
best_central_letters.emplace_back(letter);
} else if ( words_found == max_words_found ) {
best_words9.emplace_back(word9);
best_central_letters.emplace_back(letter);
}
}
}
 
std::cout << "\n" << "Most words found = " << max_words_found << std::endl;
std::cout << "The nine letter words producing this total are:" << std::endl;
for ( uint64_t i = 0; i < best_words9.size(); ++i ) {
std::cout << best_words9[i] << " with central letter '" << best_central_letters[i] << "'" << std::endl;
}
}
</syntaxhighlight>
<pre>
eke
elk
keel
keen
keg
kellogg
ken
kennel
keno
knee
kneel
knell
knew
knoll
know
knowledge
known
kong
kowloon
leek
look
nook
onlook
week
weekend
wok
woke
 
Most words found = 215
The nine letter words producing this total are:
claremont with central letter 'a'
spearmint with central letter 'a'
</pre>
 
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{libheader| System.Classes}}
{{Trans|Wren}}
<syntaxhighlight lang="delphi">
program Word_wheel;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
System.SysUtils,
System.Classes;
 
function IsInvalid(s: string): Boolean;
var
c: char;
leters: set of char;
firstE: Boolean;
begin
Result := (s.Length < 3) or (s.IndexOf('k') = -1) or (s.Length > 9);
if not Result then
begin
leters := ['d', 'e', 'g', 'k', 'l', 'n', 'o', 'w'];
firstE := true;
for c in s do
begin
if c in leters then
if (c = 'e') and (firstE) then
firstE := false
else
Exclude(leters, AnsiChar(c))
else
exit(true);
end;
end;
end;
 
var
dict: TStringList;
i: Integer;
begin
dict := TStringList.Create;
dict.LoadFromFile('unixdict.txt');
 
for i := dict.count - 1 downto 0 do
if IsInvalid(dict[i]) then
dict.Delete(i);
 
Writeln('The following ', dict.Count, ' words are the solutions to the puzzle:');
Writeln(dict.Text);
 
dict.Free;
readln;
end.
 
</syntaxhighlight>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// Word Wheel: Nigel Galloway. May 25th., 2021
let fG k n g=g|>Seq.exists(fun(n,_)->n=k) && g|>Seq.forall(fun(k,g)->Map.containsKey k n && g<=n.[k])
let wW n g=let fG=fG(Seq.item 4 g)(g|>Seq.countBy id|>Map.ofSeq) in seq{use n=System.IO.File.OpenText(n) in while not n.EndOfStream do yield n.ReadLine()}|>Seq.filter(fun n->2<(Seq.length n)&&(Seq.countBy id>>fG)n)
wW "unixdict.txt" "ndeokgelw"|>Seq.iter(printfn "%s")
</syntaxhighlight>
{{out}}
<pre>
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
=={{header|Factor}}==
{{works with|Factor|0.99 2020-07-03}}
<langsyntaxhighlight lang="factor">USING: assocs io.encodings.ascii io.files kernel math
math.statistics prettyprint sequences sorting ;
 
Line 154 ⟶ 1,369:
[ words ] keepd [ can-make? ] curry filter ;
 
"ndeokgelw" "unixdict.txt" solve [ length ] sort-with .</langsyntaxhighlight>
{{out}}
<pre style="height:20ex">
Line 176 ⟶ 1,391:
"knowledge"
}
</pre>
 
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">
#include "file.bi"
 
Function String_Split(s_in As String,chars As String,result() As String) As Long
Dim As Long ctr,ctr2,k,n,LC=Len(chars)
Dim As boolean tally(Len(s_in))
#macro check_instring()
n=0
While n<Lc
If chars[n]=s_in[k] Then
tally(k)=true
If (ctr2-1) Then ctr+=1
ctr2=0
Exit While
End If
n+=1
Wend
#endmacro
#macro split()
If tally(k) Then
If (ctr2-1) Then ctr+=1:result(ctr)=Mid(s_in,k+2-ctr2,ctr2-1)
ctr2=0
End If
#endmacro
'================== LOOP TWICE =======================
For k =0 To Len(s_in)-1
ctr2+=1:check_instring()
Next k
if ctr=0 then
if len(s_in) andalso instr(chars,chr(s_in[0])) then ctr=1':beep
end if
If ctr Then Redim result(1 To ctr): ctr=0:ctr2=0 Else Return 0
For k =0 To Len(s_in)-1
ctr2+=1:split()
Next k
'===================== Last one ========================
If ctr2>0 Then
Redim Preserve result(1 To ctr+1)
result(ctr+1)=Mid(s_in,k+1-ctr2,ctr2)
End If
Return Ubound(result)
End Function
 
Function loadfile(file As String) As String
If Fileexists(file)=0 Then Print file;" not found":Sleep:End
Dim As Long f=Freefile
Open file For Binary Access Read As #f
Dim As String text
If Lof(f) > 0 Then
text = String(Lof(f), 0)
Get #f, , text
End If
Close #f
Return text
End Function
 
Function tally(SomeString As String,PartString As String) As Long
Dim As Long LenP=Len(PartString),count
Dim As Long position=Instr(SomeString,PartString)
If position=0 Then Return 0
While position>0
count+=1
position=Instr(position+LenP,SomeString,PartString)
Wend
Return count
End Function
 
Sub show(g As String,file As String,byref matches as long,minsize as long,mustdo as string)
Redim As String s()
Var L=lcase(loadfile(file))
g=lcase(g)
string_split(L,Chr(10),s())
For m As Long=minsize To len(g)
For n As Long=Lbound(s) To Ubound(s)
If Len(s(n))=m Then
For k As Long=0 To m-1
If Instr(g,Chr(s(n)[k]))=0 Then Goto lbl
Next k
If Instr(s(n),mustdo) Then
For j As Long=0 To Len(s(n))-1
If tally(s(n),Chr(s(n)[j]))>tally(g,Chr(s(n)[j])) Then Goto lbl
Next j
Print s(n)
matches+=1
End If
End If
lbl:
Next n
Next m
End Sub
 
dim as long matches
dim as double t=timer
show("ndeokgelw","unixdict.txt",matches,3,"k")
print
print "Overall time taken ";timer-t;" seconds"
print matches;" matches"
Sleep
</syntaxhighlight>
{{out}}
<pre>
eke
elk
keg
ken
wok
keel
keen
keno
knee
knew
know
kong
leek
week
woke
kneel
knowledge
 
Overall time taken 0.02187220007181168 seconds
17 matches
</pre>
 
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
#plist NSAppTransportSecurity @{NSAllowsArbitraryLoads:YES}
 
include "NSLog.incl"
 
local fn CountCharacterInString( string as CFStringRef, character as CFStringRef ) as NSUInteger
end fn = len(string) - len( fn StringByReplacingOccurrencesOfString( string, character, @"" ) )
 
local fn IsLegal( wordStr as CFStringRef ) as BOOL
NSUInteger i, count = len( wordStr )
CFStringRef letters = @"ndeokgelw"
if count < 3 || fn StringContainsString( wordStr, @"k" ) == NO then exit fn = NO
for i = 0 to count - 1
if fn CountCharacterInString( letters, mid( wordStr, i, 1 ) ) < fn CountCharacterInString( wordStr, mid( wordStr, i, 1 ) )
exit fn = NO
end if
next
end fn = YES
 
local fn ArrayOfDictionaryWords as CFArrayRef
CFURLRef url = fn URLWithString( @"http://wiki.puzzlers.org/pub/wordlists/unixdict.txt" )
CFStringRef string = lcase( fn StringWithContentsOfURL( url, NSUTF8StringEncoding, NULL ) )
CFArrayRef wordArr = fn StringComponentsSeparatedByCharactersInSet( string, fn CharacterSetNewlineSet )
end fn = wordArr
 
void local fn FindWheelWords
CFArrayRef wordArr = fn ArrayOfDictionaryWords
CFStringRef wordStr
CFMutableStringRef mutStr = fn MutableStringNew
for wordStr in wordArr
if fn IsLegal( wordStr ) then MutableStringAppendFormat( mutStr, fn StringWithFormat( @"%@\n", wordStr ) )
next
NSLog( @"%@", mutStr )
end fn
 
fn FindWheelWords
 
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
 
=={{header|Go}}==
{{trans|Wren}}
<syntaxhighlight lang="go">package main
 
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"sort"
"strings"
)
 
func main() {
b, err := ioutil.ReadFile("unixdict.txt")
if err != nil {
log.Fatal("Error reading file")
}
letters := "deegklnow"
wordsAll := bytes.Split(b, []byte{'\n'})
// get rid of words under 3 letters or over 9 letters
var words [][]byte
for _, word := range wordsAll {
word = bytes.TrimSpace(word)
le := len(word)
if le > 2 && le < 10 {
words = append(words, word)
}
}
var found []string
for _, word := range words {
le := len(word)
if bytes.IndexByte(word, 'k') >= 0 {
lets := letters
ok := true
for i := 0; i < le; i++ {
c := word[i]
ix := sort.Search(len(lets), func(i int) bool { return lets[i] >= c })
if ix < len(lets) && lets[ix] == c {
lets = lets[0:ix] + lets[ix+1:]
} else {
ok = false
break
}
}
if ok {
found = append(found, string(word))
}
}
}
fmt.Println("The following", len(found), "words are the solutions to the puzzle:")
fmt.Println(strings.Join(found, "\n"))
 
// optional extra
mostFound := 0
var mostWords9 []string
var mostLetters []byte
// extract 9 letter words
var words9 [][]byte
for _, word := range words {
if len(word) == 9 {
words9 = append(words9, word)
}
}
// iterate through them
for _, word9 := range words9 {
letterBytes := make([]byte, len(word9))
copy(letterBytes, word9)
sort.Slice(letterBytes, func(i, j int) bool { return letterBytes[i] < letterBytes[j] })
// get distinct bytes
distinctBytes := []byte{letterBytes[0]}
for _, b := range letterBytes[1:] {
if b != distinctBytes[len(distinctBytes)-1] {
distinctBytes = append(distinctBytes, b)
}
}
distinctLetters := string(distinctBytes)
for _, letter := range distinctLetters {
found := 0
letterByte := byte(letter)
for _, word := range words {
le := len(word)
if bytes.IndexByte(word, letterByte) >= 0 {
lets := string(letterBytes)
ok := true
for i := 0; i < le; i++ {
c := word[i]
ix := sort.Search(len(lets), func(i int) bool { return lets[i] >= c })
if ix < len(lets) && lets[ix] == c {
lets = lets[0:ix] + lets[ix+1:]
} else {
ok = false
break
}
}
if ok {
found = found + 1
}
}
}
if found > mostFound {
mostFound = found
mostWords9 = []string{string(word9)}
mostLetters = []byte{letterByte}
} else if found == mostFound {
mostWords9 = append(mostWords9, string(word9))
mostLetters = append(mostLetters, letterByte)
}
}
}
fmt.Println("\nMost words found =", mostFound)
fmt.Println("Nine letter words producing this total:")
for i := 0; i < len(mostWords9); i++ {
fmt.Println(mostWords9[i], "with central letter", string(mostLetters[i]))
}
}</syntaxhighlight>
 
{{out}}
<pre>
The following 17 words are the solutions to the puzzle:
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
 
Most words found = 215
Nine letter words producing this total:
claremont with central letter a
spearmint with central letter a
</pre>
 
=={{header|Haskell}}==
<syntaxhighlight lang="haskell">import Data.Char (toLower)
import Data.List (sort)
import System.IO (readFile)
 
------------------------ WORD WHEEL ----------------------
 
gridWords :: [String] -> [String] -> [String]
gridWords grid =
filter
( ((&&) . (2 <) . length)
<*> (((&&) . elem mid) <*> wheelFit wheel)
)
where
cs = toLower <$> concat grid
wheel = sort cs
mid = cs !! 4
 
wheelFit :: String -> String -> Bool
wheelFit wheel = go wheel . sort
where
go _ [] = True
go [] _ = False
go (w : ws) ccs@(c : cs)
| w == c = go ws cs
| otherwise = go ws ccs
 
--------------------------- TEST -------------------------
main :: IO ()
main =
readFile "unixdict.txt"
>>= ( mapM_ putStrLn
. gridWords ["NDE", "OKG", "ELW"]
. lines
)</syntaxhighlight>
{{Out}}
<pre>eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke</pre>
 
=={{header|J}}==
<syntaxhighlight lang="j">require'stats'
wwhe=: {{
ref=. /:~each words=. cutLF tolower fread 'unixdict.txt'
y=.,y assert. 9=#y
ch0=. 4{y
chn=. (<<<4){y
r=. ''
for_i.2}.i.9 do.
target=. <"1 ~./:~"1 ch0,.(i comb 8){chn
;:inv r=. r,words #~ ref e. target
end.
}}</syntaxhighlight>
 
Task example:<syntaxhighlight lang="j"> wwhe'ndeokgelw'
eke elk keg ken wok keel keen keno knee knew know kong leek week woke kneel knowledge</syntaxhighlight>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
 
public final class WordWheelExtended {
 
public static void main(String[] args) throws IOException {
String wordWheel = "N D E"
+ "O K G"
+ "E L W";
String url = "http://wiki.puzzlers.org/pub/wordlists/unixdict.txt";
InputStream stream = URI.create(url).toURL().openStream();
BufferedReader reader = new BufferedReader( new InputStreamReader(stream) );
List<String> words = reader.lines().toList();
reader.close();
String allLetters = wordWheel.toLowerCase().replace(" ", "");
String middleLetter = allLetters.substring(4, 5);
Predicate<String> firstFilter = word -> word.contains(middleLetter) && 2 < word.length() && word.length() < 10;
Predicate<String> secondFilter = word -> word.chars().allMatch( ch -> allLetters.indexOf(ch) >= 0 );
Predicate<String> correctWords = firstFilter.and(secondFilter);
words.stream().filter(correctWords).forEach(System.out::println);
int maxWordsFound = 0;
List<String> bestWords9 = new ArrayList<String>();
List<Character> bestCentralLetters = new ArrayList<Character>();
List<String> words9 = words.stream().filter( word -> word.length() == 9 ).toList();
 
for ( String word9 : words9 ) {
List<Character> distinctLetters = word9.chars().mapToObj( i -> (char) i ).distinct().toList();
for ( char letter : distinctLetters ) {
int wordsFound = 0;
for ( String word : words ) {
if ( word.length() >= 3 && word.indexOf(letter) >= 0 ) {
List<Character> letters = new ArrayList<Character>(distinctLetters);
boolean validWord = true;
for ( char ch : word.toCharArray() ) {
final int index = letters.indexOf(ch);
if ( index == -1 ) {
validWord = false;
break;
}
letters.remove(index);
}
if ( validWord ) {
wordsFound += 1;
}
}
}
if ( wordsFound > maxWordsFound ) {
maxWordsFound = wordsFound;
bestWords9.clear();
bestWords9.add(word9);
bestCentralLetters.clear();
bestCentralLetters.add(letter);
} else if ( wordsFound == maxWordsFound ) {
bestWords9.add(word9);
bestCentralLetters.add(letter);
}
}
}
System.out.println(System.lineSeparator() + "Most words found = " + maxWordsFound);
System.out.println("The nine letter words producing this total are:");
for ( int i = 0; i < bestWords9.size(); i++ ) {
System.out.println(bestWords9.get(i) + " with central letter '" + bestCentralLetters.get(i) + "'");
}
}
 
}
</syntaxhighlight>
<pre>
eke
elk
keel
keen
keg
kellogg
ken
kennel
keno
knee
kneel
knell
knew
knoll
know
knowledge
known
kong
kowloon
leek
look
nook
onlook
week
weekend
wok
woke
 
Most words found = 215
The nine letter words producing this total are:
claremont with central letter 'a'
spearmint with central letter 'a'
</pre>
 
=={{header|JavaScript}}==
A version using local access to the dictionary, through the macOS JavaScript for Automation API.
{{Works with|JXA}}
<syntaxhighlight lang="javascript">(() => {
"use strict";
 
// ------------------- WORD WHEEL --------------------
 
// gridWords :: [String] -> [String] -> [String]
const gridWords = grid =>
lexemes => {
const
wheel = sort(toLower(grid.join(""))),
wSet = new Set(wheel),
mid = wheel[4];
 
return lexemes.filter(w => {
const cs = [...w];
 
return 2 < cs.length && cs.every(
c => wSet.has(c)
) && cs.some(x => mid === x) && (
wheelFit(wheel, cs)
);
});
};
 
 
// wheelFit :: [Char] -> [Char] -> Bool
const wheelFit = (wheel, word) => {
const go = (ws, cs) =>
0 === cs.length ? (
true
) : 0 === ws.length ? (
false
) : ws[0] === cs[0] ? (
go(ws.slice(1), cs.slice(1))
) : go(ws.slice(1), cs);
 
return go(wheel, sort(word));
};
 
 
// ---------------------- TEST -----------------------
// main :: IO ()
const main = () =>
gridWords(["NDE", "OKG", "ELW"])(
lines(readFile("unixdict.txt"))
)
.join("\n");
 
 
// ---------------- GENERIC FUNCTIONS ----------------
 
// lines :: String -> [String]
const lines = s =>
// A list of strings derived from a single string
// which is delimited by \n or by \r\n or \r.
Boolean(s.length) ? (
s.split(/\r\n|\n|\r/u)
) : [];
 
 
// readFile :: FilePath -> IO String
const readFile = fp => {
// The contents of a text file at the
// given file path.
const
e = $(),
ns = $.NSString
.stringWithContentsOfFileEncodingError(
$(fp).stringByStandardizingPath,
$.NSUTF8StringEncoding,
e
);
 
return ObjC.unwrap(
ns.isNil() ? (
e.localizedDescription
) : ns
);
};
 
 
// sort :: Ord a => [a] -> [a]
const sort = xs =>
Array.from(xs).sort();
 
 
// toLower :: String -> String
const toLower = s =>
// Lower-case version of string.
s.toLocaleLowerCase();
 
 
// MAIN ---
return main();
})();</syntaxhighlight>
{{Out}}
<pre>eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke</pre>
 
=={{header|jq}}==
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq, and with fq''' provided `keys_unsorted` is replaced `by keys`
<syntaxhighlight lang=jq>
# remove words with fewer than 3 or more than 9 letters
def words: inputs | select(length | . > 2 and . < 10);
 
# The central letter in `puzzle` should be the central letter of the word wheel
def solve(puzzle):
def chars: explode[] | [.] | implode;
def profile(s): reduce s as $c (null; .[$c] += 1);
profile(puzzle[]) as $profile
| def ok($prof): all($prof|keys_unsorted[]; . as $k | $prof[$k] <= $profile[$k]);
(puzzle | .[ (length - 1) / 2]) as $central
| words
| select(index($central) and ok( profile(chars) )) ;
 
"The solutions to the puzzle are as follows:",
solve( ["d", "e", "e", "g", "k", "l", "n", "o", "w"] )
</syntaxhighlight>
'''Invocation''': < unixdict.txt jq -Rnr -f word-wheel.jq
{{output}}
<pre>
The solutions to the puzzle are as follows:
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
 
=={{header|Julia}}==
<langsyntaxhighlight lang="julia">using Combinatorics
 
const tfile = download("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt")
Line 200 ⟶ 2,097:
 
println(wordwheel("ndeokgelw", "k"))
</langsyntaxhighlight>{{out}}
<pre>
["ken", "keg", "eke", "elk", "wok", "keno", "knee", "keen", "knew", "kong", "know", "woke", "keel", "leek", "week", "kneel", "knowledge"]
</pre>
===Faster but less general version===
<syntaxhighlight lang="julia">const tfile = download("http://wiki.puzzlers.org/pub/wordlists/unixdict.txt")
const wordarraylist = [[string(c) for c in w] for w in split(read(tfile, String), r"\s+")]
 
function wordwheel2(wheel, central)
warr, maxlen = [string(c) for c in wheel], length(wheel)
returnarraylist = filter(a -> 2 < length(a) <= maxlen && central in a &&
all(c -> sum(x -> x == c, a) <= sum(x -> x == c, warr), a), wordarraylist)
return join.(returnarraylist)
end
 
println(wordwheel2("ndeokgelw", "k"))
</syntaxhighlight>{{out}}
<pre>
["eke", "elk", "keel", "keen", "keg", "ken", "keno", "knee", "kneel", "knew", "know", "knowledge", "kong", "leek", "week", "wok", "woke"]
</pre>
 
=={{header|Lua}}==
<syntaxhighlight lang="lua">LetterCounter = {
new = function(self, word)
local t = { word=word, letters={} }
for ch in word:gmatch(".") do t.letters[ch] = (t.letters[ch] or 0) + 1 end
return setmetatable(t, self)
end,
contains = function(self, other)
for k,v in pairs(other.letters) do
if (self.letters[k] or 0) < v then return false end
end
return true
end
}
LetterCounter.__index = LetterCounter
 
grid = "ndeokgelw"
midl = grid:sub(5,5)
ltrs = LetterCounter:new(grid)
file = io.open("unixdict.txt", "r")
for word in file:lines() do
if #word >= 3 and word:find(midl) and ltrs:contains(LetterCounter:new(word)) then
print(word)
end
end</syntaxhighlight>
{{out}}
<pre>eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">ClearAll[possible]
possible[letters_List][word_String] := Module[{c1, c2, m},
c1 = Counts[Characters@word];
c2 = Counts[letters];
m = Merge[{c1, c2}, Identity];
Length[Select[Select[m, Length /* GreaterThan[1]], Apply[Greater]]] == 0
]
chars = Characters@"ndeokgelw";
words = Import["http://wiki.puzzlers.org/pub/wordlists/unixdict.txt", "String"];
words = StringSplit[ToLowerCase[words], "\n"];
words //= Select[StringLength /* GreaterEqualThan[3]];
words //= Select[StringContainsQ["k"]];
words //= Select[StringMatchQ[Repeated[Alternatives @@ chars]]];
words //= Select[possible[chars]];
words</syntaxhighlight>
{{out}}
<pre>{eke,elk,keel,keen,keg,ken,keno,knee,kneel,knew,know,knowledge,kong,leek,week,wok,woke}</pre>
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import strutils, sugar, tables
 
const Grid = """N D E
O K G
E L W"""
 
let letters = Grid.toLowerAscii.splitWhitespace.join()
 
let words = collect(newSeq):
for word in "unixdict.txt".lines:
if word.len in 3..9:
word
 
let midLetter = letters[4]
 
let gridCount = letters.toCountTable
for word in words:
block checkWord:
if midLetter in word:
for ch, count in word.toCountTable.pairs:
if count > gridCount[ch]:
break checkWord
echo word</syntaxhighlight>
 
{{out}}
<pre>eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke</pre>
 
=={{header|Pascal}}==
{{works with|Free Pascal}}
<syntaxhighlight lang="pascal">
program WordWheel;
 
{$mode objfpc}{$H+}
 
uses
SysUtils;
 
const
WheelSize = 9;
MinLength = 3;
WordListFN = 'unixdict.txt';
 
procedure search(Wheel : string);
var
Allowed, Required, Available, w : string;
Len, i, p : integer;
WordFile : TextFile;
Match : boolean;
begin
AssignFile(WordFile, WordListFN);
try
Reset(WordFile);
except
writeln('Could not open dictionary file: ' + WordListFN);
exit;
end;
Allowed := LowerCase(Wheel);
Required := copy(Allowed, 5, 1); { central letter is required }
while not eof(WordFile) do
begin
readln(WordFile, w);
Len := length(w);
if (Len < MinLength) or (Len > WheelSize) then continue;
if pos(Required, w) = 0 then continue;
Available := Allowed;
Match := True;
for i := 1 to Len do
begin
p := pos(w[i], Available);
if p > 0 then
{ prevent re-use of letter }
delete(Available, p, 1)
else
begin
Match := False;
break;
end;
end;
if Match then
writeln(w);
end;
CloseFile(WordFile);
end;
 
{ exercise the procedure }
begin
search('NDE' + 'OKG' + 'ELW');
end.
</syntaxhighlight>
{{out}}
<pre>
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
 
=={{header|Perl}}==
UPDATED: this version builds a single regex that will select all valid words
straight from the file string.
<syntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict; # https://rosettacode.org/wiki/Word_wheel
use warnings;
 
$_ = <<END;
N D E
O K G
E L W
END
 
my $file = do { local(@ARGV, $/) = 'unixdict.txt'; <> };
my $length = my @letters = lc =~ /\w/g;
my $center = $letters[@letters / 2];
my $toomany = (join '', sort @letters) =~ s/(.)\1*/
my $count = length "$1$&"; "(?!(?:.*$1){$count})" /ger;
my $valid = qr/^(?=.*$center)$toomany([@letters]{3,$length}$)$/m;
 
my @words = $file =~ /$valid/g;
 
print @words . " words for\n$_\n@words\n" =~ s/.{60}\K /\n/gr;</syntaxhighlight>
{{out}}
<pre>
17 words for
N D E
O K G
E L W
 
eke elk keel keen keg ken keno knee kneel knew know knowledge
kong leek week wok woke
</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1.0.1"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (fixed another glitch in unique())</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">wheel</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"ndeokgelw"</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">musthave</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">wheel</span><span style="color: #0000FF;">[</span><span style="color: #000000;">5</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">unix_dict</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">word9</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #000080;font-style:italic;">-- (for the optional extra part)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">found</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lw</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">lw</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">3</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">lw</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">9</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">word9</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word9</span><span style="color: #0000FF;">,</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">musthave</span><span style="color: #0000FF;">,</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">remaining</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">wheel</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">lw</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lw</span><span style="color: #0000FF;">],</span><span style="color: #000000;">remaining</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">remaining</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'\0'</span> <span style="color: #000080;font-style:italic;">-- (prevent re-use)</span>
<span style="color: #000000;">lw</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">lw</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">found</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">found</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">word</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">jbw</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">join_by</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">found</span><span style="color: #0000FF;">],</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">9</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n "</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"The following %d words were found:\n %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">found</span><span style="color: #0000FF;">,</span><span style="color: #000000;">jbw</span><span style="color: #0000FF;">})</span>
<span style="color: #000080;font-style:italic;">-- optional extra</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (works but no progress/blank screen for 2min 20s)
-- (the "working" won't show, even w/o the JS check)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">mostFound</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">mostWheels</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
<span style="color: #000000;">mustHaves</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word9</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">try_wheel</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">word9</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">try_wheel</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">9</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">musthaves</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">unique</span><span style="color: #0000FF;">(</span><span style="color: #000000;">try_wheel</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">musthaves</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">found</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word9</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">word</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">word9</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">musthaves</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">rest</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">try_wheel</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">ix</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">[</span><span style="color: #000000;">c</span><span style="color: #0000FF;">],</span><span style="color: #000000;">rest</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">ix</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">exit</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">rest</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ix</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">'\0'</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">found</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">ok</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span> <span style="color: #000080;font-style:italic;">-- (wouldn't show up anyway)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"working (%s)\r"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">try_wheel</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">found</span><span style="color: #0000FF;">></span><span style="color: #000000;">mostFound</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">mostFound</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">found</span>
<span style="color: #000000;">mostWheels</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">try_wheel</span><span style="color: #0000FF;">}</span>
<span style="color: #000000;">mustHaves</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">musthaves</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]}</span>
<span style="color: #008080;">elsif</span> <span style="color: #000000;">found</span><span style="color: #0000FF;">==</span><span style="color: #000000;">mostFound</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">mostWheels</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mostWheels</span><span style="color: #0000FF;">,</span><span style="color: #000000;">try_wheel</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mustHaves</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mustHaves</span><span style="color: #0000FF;">,</span><span style="color: #000000;">musthaves</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Most words found = %d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">mostFound</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Nine letter words producing this total:\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mostWheels</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s with central letter '%c'\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">mostWheels</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">mustHaves</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</syntaxhighlight>-->
{{out}}
<small>(Only the first three lines are shown under pwa/p2js)</small>
<pre>
The following 17 words were found:
eke elk keel keen keg ken keno knee kneel
knew know knowledge kong leek week wok woke
 
Most words found = 215
Nine letter words producing this total:
claremont with central letter 'a'
spearmint with central letter 'a'
</pre>
 
=={{header|Picat}}==
<syntaxhighlight lang="picat">main =>
MinLen = 3,
MaxLen = 9,
Chars = "ndeokgelw",
MustContain = 'k',
 
WordList = "unixdict.txt",
Words = read_file_lines(WordList),
Res = word_wheel(Chars,Words,MustContain,MinLen, MaxLen),
println(Res),
println(len=Res.len),
nl.
 
word_wheel(Chars,Words,MustContain,MinLen,MaxLen) = Res.reverse =>
Chars := to_lowercase(Chars),
D = make_hash(Chars),
Res = [],
foreach(W in Words, W.len >= MinLen, W.len <= MaxLen, membchk(MustContain,W))
WD = make_hash(W),
Check = true,
foreach(C in keys(WD), break(Check == false))
if not D.has_key(C) ; WD.get(C,0) > D.get(C,0) then
Check := false
end
end,
if Check == true then
Res := [W|Res]
end
end.
 
% Returns a map of the elements and their occurrences
% in the list L.
make_hash(L) = D =>
D = new_map(),
foreach(E in L)
D.put(E,D.get(E,0)+1)
end.</syntaxhighlight>
 
{{out}}
<pre>[eke,elk,keel,keen,keg,ken,keno,knee,kneel,knew,know,knowledge,kong,leek,week,wok,woke]
len = 17</pre>
 
'''Optimal word(s)''':
<syntaxhighlight lang="picat">main =>
WordList = "unixdict.txt",
MinLen = 3,
MaxLen = 9,
Words = [Word : Word in read_file_lines(WordList), Word.len >= MinLen, Word.len <= MaxLen],
TargetWords = [Word : Word in Words, Word.len == MaxLen],
MaxResWord = [],
MaxResLen = 0,
foreach(Word in TargetWords)
foreach(MustContain in Word.remove_dups)
Res = word_wheel(Word,Words,MustContain,MinLen, MaxLen),
Len = Res.len,
if Len >= MaxResLen then
if Len == MaxResLen then
MaxResWord := MaxResWord ++ [[word=Word,char=MustContain]]
else
MaxResWord := [[word=Word,char=MustContain]],
MaxResLen := Len
end
end
end
end,
println(maxLResen=MaxResLen),
println(maxWord=MaxResWord).</syntaxhighlight>
 
{{out}}
<pre>
maxReLen = 215
maxWord = [[word = claremont,char = a],[word = spearmint,char = a]]
</pre>
 
=={{header|PureBasic}}==
<syntaxhighlight lang="purebasic">Procedure.b check_word(word$)
Shared letters$
If Len(word$)<3 Or FindString(word$,"k")<1
ProcedureReturn #False
EndIf
For i=1 To Len(word$)
If CountString(letters$,Mid(word$,i,1))<CountString(word$,Mid(word$,i,1))
ProcedureReturn #False
EndIf
Next
ProcedureReturn #True
EndProcedure
 
If ReadFile(0,"./Data/unixdict.txt")
txt$=LCase(ReadString(0,#PB_Ascii|#PB_File_IgnoreEOL))
CloseFile(0)
EndIf
 
If OpenConsole()
letters$="ndeokgelw"
wordcount=1
Repeat
buf$=StringField(txt$,wordcount,~"\n")
wordcount+1
If check_word(buf$)=#False
Continue
EndIf
PrintN(buf$) : r+1
Until buf$=""
PrintN("- Finished: "+Str(r)+" words found -")
Input()
EndIf
End</syntaxhighlight>
{{out}}
<pre>eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
- Finished: 17 words found -
</pre>
 
=={{header|Python}}==
<syntaxhighlight lang="python">import urllib.request
from collections import Counter
 
Line 219 ⟶ 2,582:
 
def getwords(url='http://wiki.puzzlers.org/pub/wordlists/unixdict.txt'):
"Return sorted lowercased words of 3 to 9 characters"
words = urllib.request.urlopen(url).read().decode().strip().lower().split()
return sorted(set(w for w in words if 2 < len(w) < 10))
 
def solve(grid, dictionary):
Line 233 ⟶ 2,596:
chars = ''.join(GRID.strip().lower().split())
found = solve(chars, dictionary=getwords())
print('\n'.join(found))</langsyntaxhighlight>
 
{{out}}
Line 253 ⟶ 2,616:
wok
woke</pre>
 
 
Or, using a local copy of the dictionary, and a recursive test of wheel fit:
<syntaxhighlight lang="python">'''Word wheel'''
 
from os.path import expanduser
 
 
# gridWords :: [String] -> [String] -> [String]
def gridWords(grid):
'''The subset of words in ws which contain the
central letter of the grid, and can be completed
by single uses of some or all of the remaining
letters in the grid.
'''
def go(ws):
cs = ''.join(grid).lower()
wheel = sorted(cs)
wset = set(wheel)
mid = cs[4]
return [
w for w in ws
if 2 < len(w) and (mid in w) and (
all(c in wset for c in w)
) and wheelFit(wheel, w)
]
return go
 
 
# wheelFit :: String -> String -> Bool
def wheelFit(wheel, word):
'''True if a given word can be constructed
from (single uses of) some subset of
the letters in the wheel.
'''
def go(ws, cs):
return True if not cs else (
False if not ws else (
go(ws[1:], cs[1:]) if ws[0] == cs[0] else (
go(ws[1:], cs)
)
)
)
return go(wheel, sorted(word))
 
 
# -------------------------- TEST --------------------------
# main :: IO ()
def main():
'''Word wheel matches for a given grid in a copy of
http://wiki.puzzlers.org/pub/wordlists/unixdict.txt
'''
print('\n'.join(
gridWords(['NDE', 'OKG', 'ELW'])(
readFile('~/unixdict.txt').splitlines()
)
))
 
 
# ------------------------ GENERIC -------------------------
 
# readFile :: FilePath -> IO String
def readFile(fp):
'''The contents of any file at the path
derived by expanding any ~ in fp.
'''
with open(expanduser(fp), 'r', encoding='utf-8') as f:
return f.read()
 
 
# MAIN ---
if __name__ == '__main__':
main()</syntaxhighlight>
{{Out}}
<pre>eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke</pre>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="Quackery"> [ over find swap found ] is has ( $ c --> b )
 
[ over find
split 1 split
swap drop join ] is remove ( $ c --> $ )
 
$ "rosetta/unixdict.txt" sharefile
drop nest$
[] swap
witheach
[ dup size 3 < iff drop done
dup size 9 > iff drop done
dup char k has not iff drop done
dup $ "ndeokgelw"
witheach remove
$ "" != iff drop done
nested join ]
30 wrap$</syntaxhighlight>
 
{{out}}
 
<pre>eke elk keel keen keg ken keno knee
kneel knew know knowledge kong leek week
wok woke
</pre>
 
=={{header|q}}==
<syntaxhighlight lang="q">ce:count each
lc:ce group@ / letter count
dict:"\n"vs .Q.hg "http://wiki.puzzlers.org/pub/wordlists/unixdict.txt"
// dictionary of 3-9 letter words
d39:{x where(ce x)within 3 9}{x where all each x in .Q.a}dict
 
solve:{[grid;dict]
i:where(grid 4)in'dict;
dict i where all each 0<=(lc grid)-/:lc each dict i }[;d39]</syntaxhighlight>
<syntaxhighlight lang="q">q)`$solve "ndeokglew"
`eke`elk`keel`keen`keg`ken`keno`knee`kneel`knew`know`knowledge`kong`leek`week`wok`woke</syntaxhighlight>
A naive solution to the second question is simple
<syntaxhighlight lang="q">bust:{[dict]
grids:distinct raze(til 9)rotate\:/:dict where(ce dict)=9;
wc:(count solve@)each grids;
grids where wc=max wc }</syntaxhighlight>
but inefficient. Better:
<syntaxhighlight lang="q">best:{[dict]
dlc:lc each dict; / letter counts of dictionary words
ig:where(ce dict)=9; / find grids (9-letter words)
igw:where each(all'')0<=(dlc ig)-/:\:dlc; / find words composable from each grid (length ig)
grids:raze(til 9)rotate\:/:dict ig; / 9 permutations of each grid
iaz:(.Q.a)!where each .Q.a in'\:dict; / find words containing a, b, c etc
ml:4 rotate'dict ig; / mid letters for each grid
wc:ce raze igw inter/:'iaz ml; / word counts for grids
distinct grids where wc=max wc } / grids with most words</syntaxhighlight>
<syntaxhighlight lang="q">q)show w:best d39
"ntclaremo"
"tspearmin"
 
q)ce solve each w
215 215</syntaxhighlight>
Full discussion at [https://code.kx.com/q/learn/pb/word-wheel/ code.kx.com]
 
=={{header|Raku}}==
Line 260 ⟶ 2,777:
Defaults to task specified wheel, unixdict.txt, minimum 3 letters.
 
Using [https://modules.raku.org/search/?q=Terminal%3A%3ABoxer Terminal::Boxer] from the Raku ecosystem.
<lang perl6>my %*SUB-MAIN-OPTS = :named-anywhere;
 
<syntaxhighlight lang="raku" line>use Terminal::Boxer;
 
my %*SUB-MAIN-OPTS = :named-anywhere;
 
unit sub MAIN ($wheel = 'ndeokgelw', :$dict = './unixdict.txt', :$min = 3);
Line 274 ⟶ 2,795:
};
 
say "Using $dict, minimum $min letters.";
print { qq:to/END/;
 
Using $dict, minimum $min letters.
print rs-box :3col, :3cw, :indent("\t"), $wheel.comb».uc;
\t┌───┬───┬───┐
 
\t│ $^a │ $^b │ $^c │
say "{sum %words.values».elems} words found";
\t├───┼───┼───┤
\t│ $^d │ $^e │ $^f │
\t├───┼───┼───┤
\t│ $^g │ $^h │ $^i │
\t└───┴───┴───┘
END
}( |$wheel.comb».uc );
 
printf "%d letters: %s\n", .key, .value.sort.join(', ') for %words.sort;</syntaxhighlight>
</lang>
 
{{out}}
;Using defaults
 
<syntaxhighlight lang="text">raku word-wheel.raku</langsyntaxhighlight>
<pre>Using ./unixdict.txt, minimum 3 letters.
╭───┬───┬───╮
┌───┬───┬───┐
│ N │ D │ E │
├───┼───┼───┤
Line 300 ⟶ 2,814:
├───┼───┼───┤
│ E │ L │ W │
╰───┴───┴───╯
└───┴───┴───┘
17 words found
3 letters: eke, elk, keg, ken, wok
4 letters: keel, keen, keno, knee, knew, know, kong, leek, week, woke
5 letters: kneel
9 letters: knowledge</pre>
</pre>
 
;Larger dictionary
Using the much larger dictionary '''words.txt''' file from '''https://github.com/dwyl/english-words'''
 
<syntaxhighlight lang="text">raku word-wheel.raku --dict=./words.txt</langsyntaxhighlight>
 
<pre>Using ./words.txt, minimum 3 letters.
╭───┬───┬───╮
┌───┬───┬───┐
│ N │ D │ E │
├───┼───┼───┤
Line 319 ⟶ 2,833:
├───┼───┼───┤
│ E │ L │ W │
╰───┴───┴───╯
└───┴───┴───┘
86 words found
3 letters: dkg, dkl, eek, egk, eke, ekg, elk, gok, ked, kee, keg, kel, ken, keo, kew, kln, koe, kol, kon, lek, lgk, nek, ngk, oke, owk, wok
4 letters: deek, deke, doek, doke, donk, eked, elke, elko, geek, genk, gonk, gowk, keel, keen, keld, kele, kend, keno, keon, klee, knee, knew, know, koel, koln, kone, kong, kwon, leek, leke, loke, lonk, okee, oken, week, welk, woke, wolk, wonk
Line 327 ⟶ 2,842:
9 letters: knowledge</pre>
 
;Top 5 maximum word wheels with at least one 9 letter word
;Exercise adjustable parameters
 
Using unixdict.txt:
<lang>raku word-wheel.raku iuymslleb --dict=./words.txt --min=4</lang>
 
<pre>Using ./words.txt, minimum 4 letters.
<pre>Wheel words
┌───┬───┬───┐
eimnaprst: 215
│ I │ U │ Y │
celmanort: 215
├───┼───┼───┤
ceimanrst: 210
│ M │ S │ L │
elmnaoprt: 208
├───┼───┼───┤
ahlneorst: 201</pre>
│ L │ E │ B │
 
└───┴───┴───┘
Using words.txt:
4 letters: bels, beys, bise, blus, bmus, bsem, bsie, bslm, bsme, bums, busy, buys, byes, eisb, elis, ells, elms, elsi, elsy, elys, emus, emys, ills, ilse, imsl, isle, islm, islu, ismy, leis, leys, libs, lies, lise, lues, luis, lums, lyes, lyse, mels, mibs, mils, mise, misy, msie, musb, muse, sbli, sell, semi, siey, sile, sill, sime, sium, slbm, sleb, sley, slim, slub, slue, slum, suey, suiy, sull, sumi, sumy, syli, syll, uims
<pre>Wheel words
5 letters: belis, bells, belus, bemis, biles, bills, bisme, blues, bulls, bulse, busey, buyse, eblis, ellis, embus, emuls, eulis, ileus, illus, ilyse, isbel, iseum, lesiy, lesli, lesly, lieus, liles, limbs, limes, limsy, lisle, lubes, luise, lusby, lyles, melis, mells, miles, mills, misly, mlles, mules, mulls, mulse, musie, musil, myles, mysel, sebum, selby, selim, selli, selly, sibel, sible, sibyl, silly, silyl, simul, slily, slime, slimy, smell, smile, smily, sully, sybil, syble, yells, yills, ylems, yules, yusem
meilanrst: 1329
6 letters: bellis, bisley, bluesy, blueys, bluism, blumes, bulies, bullis, busily, elymus, embusy, illyes, imbues, libels, libuse, limbus, limeys, milles, milsey, muesli, muleys, musily, mysell, sibell, sibley, simule, slimly, smelly, smiley, umbels, umbles
deilanrst: 1313
7 letters: besully, bullies, bullism, elysium, illumes, mulleys, sibylle, silybum, sublime, sybille
ceilanrst: 1301
8 letters: bullyism, semibull
peilanrst: 1285
9 letters: sublimely</pre>
geilanrst: 1284</pre>
 
=={{header|REXX}}==
Quite a bit of boilerplate was included in this REXX example.
 
No assumption was made as the "case" of the words (upper/lower/mixed case). &nbsp; Duplicate
words were detected and
<br>eliminated &nbsp; ('''god''' and '''God'''), &nbsp; as well as words that didn't contain
all Roman (Latin) letters.
 
The number of minimum letters can be specified, &nbsp; as well as the dictionary fileID and
the letters in the word wheel (grid).
 
Additional information is also provided concerning how many words have been skipped due to
the various filters.
<syntaxhighlight lang="rexx">/*REXX pgm finds (dictionary) words which can be found in a specified word wheel (grid).*/
parse arg grid minL iFID . /*obtain optional arguments from the CL*/
if grid==''|grid=="," then grid= 'ndeokgelw' /*Not specified? Then use the default.*/
if minL==''|minL=="," then minL= 3 /* " " " " " " */
if iFID==''|iFID=="," then iFID= 'UNIXDICT.TXT' /* " " " " " " */
oMinL= minL; minL= abs(minL) /*if negative, then don't show a list. */
gridU= grid; upper gridU /*get an uppercase version of the grid.*/
Lg= length(grid); Hg= Lg % 2 + 1 /*get length of grid & the middle char.*/
ctr= substr(grid, Hg, 1); upper ctr /*get uppercase center letter in grid. */
wrds= 0 /*# words that are in the dictionary. */
wees= 0 /*" " " " too short. */
bigs= 0 /*" " " " too long. */
dups= 0 /*" " " " duplicates. */
ills= 0 /*" " " contain "not" letters.*/
good= 0 /*" " " contain center letter. */
nine= 0 /*" wheel─words that contain 9 letters.*/
say ' Reading the file: ' iFID /*align the text. */
@.= . /*uppercase non─duplicated dict. words.*/
$= /*the list of dictionary words in grid.*/
do recs=0 while lines(iFID)\==0 /*process all words in the dictionary. */
u= space( linein(iFID), 0); upper u /*elide blanks; uppercase the word. */
L= length(u) /*obtain the length of the word. */
if @.u\==. then do; dups= dups+1; iterate; end /*is this a duplicate? */
if L<minL then do; wees= wees+1; iterate; end /*is the word too short? */
if L>Lg then do; bigs= bigs+1; iterate; end /*is the word too long? */
if \datatype(u,'M') then do; ills= ills+1; iterate; end /*has word non─letters? */
@.u= /*signify that U is a dictionary word*/
wrds= wrds + 1 /*bump the number of "good" dist. words*/
if pos(ctr, u)==0 then iterate /*word doesn't have center grid letter.*/
good= good + 1 /*bump # center─letter words in dict. */
if verify(u, gridU)\==0 then iterate /*word contains a letter not in grid. */
if pruned(u, gridU) then iterate /*have all the letters not been found? */
if L==9 then nine= nine + 1 /*bump # words that have nine letters. */
$= $ u /*add this word to the "found" list. */
end /*recs*/
say
say ' number of records (words) in the dictionary: ' right( commas(recs), 9)
say ' number of ill─formed words in the dictionary: ' right( commas(ills), 9)
say ' number of duplicate words in the dictionary: ' right( commas(dups), 9)
say ' number of too─small words in the dictionary: ' right( commas(wees), 9)
say ' number of too─long words in the dictionary: ' right( commas(bigs), 9)
say ' number of acceptable words in the dictionary: ' right( commas(wrds), 9)
say ' number center─letter words in the dictionary: ' right( commas(good), 9)
say ' the minimum length of words that can be used: ' right( commas(minL), 9)
say ' the word wheel (grid) being used: ' grid
say ' center of the word wheel (grid) being used: ' right('↑', Hg)
say; #= words($); $= strip($)
say ' number of word wheel words in the dictionary: ' right( commas(# ), 9)
say ' number of nine-letter wheel words found: ' right( commas(nine), 9)
if #==0 | oMinL<0 then exit #
say
say ' The list of word wheel words found:'; say copies('─', length($)); say lower($)
exit # /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
lower: arg aa; @='abcdefghijklmnopqrstuvwxyz'; @u=@; upper @u; return translate(aa,@,@U)
commas: parse arg _; do jc=length(_)-3 to 1 by -3; _=insert(',', _, jc); end; return _
/*──────────────────────────────────────────────────────────────────────────────────────*/
pruned: procedure; parse arg aa,gg /*obtain word to be tested, & the grid.*/
do n=1 for length(aa); p= pos( substr(aa,n,1), gg); if p==0 then return 1
gg= overlay(., gg, p) /*"rub out" the found character in grid*/
end /*n*/; return 0 /*signify that the AA passed the test*/</syntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Reading the file: UNIXDICT.TXT
 
number of records (lines) in the dictionary: 25,105
number of ill─formed words in the dictionary: 123
number of duplicate words in the dictionary: 0
number of too─small words in the dictionary: 159
number of too─long words in the dictionary: 4,158
number of acceptable words in the dictionary: 20,664
number center─letter words in the dictionary: 1,630
the minimum length of words that can be used: 3
the word wheel (grid) being used: ndeokgelw
center of the word wheel (grid) being used: ↑
 
number of word wheel words in the dictionary: 17
number of nine-letter wheel words found: 1
 
The list of word wheel words found:
─────────────────────────────────────────────────────────────────────────────────────
eke elk keel keen keg ken keno knee kneel knew know knowledge kong leek week wok woke
</pre>
<small>Note: &nbsp; my "personal" dictionary that I built &nbsp; (over &nbsp; <strike>915,000</strike> &nbsp; 947,359 &nbsp; words), &nbsp; there are &nbsp; 178 &nbsp; words that are in the (above) word wheel.</small>
 
{{out|output|text=&nbsp; when using the inputs: &nbsp; &nbsp; <tt> satRELinp &nbsp; -3 </tt>}}
 
(I am trying for a maximum word wheel count for the &nbsp; UNIXDICT &nbsp; dictionary;
<br>the negative minimum word length indicates to &nbsp; not &nbsp; list the words found.)
<br>Thanks to userid &nbsp; [[User:Paddy3118|Paddy3118]], &nbsp; a better grid was found.
<pre>
Reading the file: UNIXDICT.TXT
 
number of records (lines) in the dictionary: 25,105
number of ill─formed words in the dictionary: 123
number of duplicate words in the dictionary: 0
number of too─small words in the dictionary: 159
number of too─long words in the dictionary: 4,158
number of acceptable words in the dictionary: 20,664
number center─letter words in the dictionary: 11,623
the minimum length of words that can be used: 3
the word wheel (grid) being used: satRELinp
center of the word wheel (grid) being used: ↑
 
number of word wheel words in the dictionary: 234
number of nine-letter wheel words found: 0
</pre>
 
{{out|output|text=&nbsp; when using the inputs: &nbsp; &nbsp; <tt> setRALinp &nbsp; -3 </tt>}}
 
Thanks to userid &nbsp; [[User:Simonjsaunders|Simonjsaunders]], &nbsp; a better grid was found.
<pre>
Reading the file: UNIXDICT.TXT
 
number of records (words) in the dictionary: 25,104
number of ill─formed words in the dictionary: 123
number of duplicate words in the dictionary: 0
number of too─small words in the dictionary: 159
number of too─long words in the dictionary: 4,158
number of acceptable words in the dictionary: 20,664
number center─letter words in the dictionary: 10,369
the minimum length of words that can be used: 3
the word wheel (grid) being used: setRALinp
center of the word wheel (grid) being used: ↑
 
number of word wheel words in the dictionary: 248
number of nine-letter wheel words found: 0
</pre>
 
=={{header|Ruby}}==
<syntaxhighlight lang="ruby">wheel = "ndeokgelw"
middle, wheel_size = wheel[4], wheel.size
 
res = File.open("unixdict.txt").each_line.select do |word|
w = word.chomp
next unless w.size.between?(3, wheel_size)
next unless w.match?(middle)
wheel.each_char{|c| w.sub!(c, "") } #sub! substitutes only the first occurrence (gsub would substitute all)
w.empty?
end
 
puts res
</syntaxhighlight>
{{out}}
<pre>eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
 
=={{header|Transd}}==
<syntaxhighlight lang="scheme">#lang transd
 
MainModule: {
maxwLen: 9,
minwLen: 3,
dict: Vector<String>(),
subWords: Vector<String>(),
 
procGrid: (λ grid String() cent String() subs Bool()
(with cnt 0 (sort grid)
(for w in dict where (and (neq (index-of w cent) -1)
(match w "^[[:alpha:]]+$")) do
(if (is-subset grid (sort (cp w))) (+= cnt 1)
(if subs (append subWords w))
)
)
(ret cnt)
)),
 
_start: (λ locals: res 0 maxRes 0
(with fs FileStream()
(open-r fs "/mnt/proj/res/unixdict.txt")
(for w in (read-lines fs)
where (within (size w) minwLen maxwLen) do
(append dict w))
)
 
(lout "Main part of task:\n")
(procGrid "ndeokgelw" "k" true)
(lout "Number of words: " (size subWords) ";\nword list: " subWords)
 
(lout "\n\nOptional part of task:\n")
(for w in dict where (eq (size w) maxwLen) do
(for centl in (split (unique (sort (cp w))) "") do
(if (>= (= res (procGrid (cp w) centl false)) maxRes) (= maxRes res)
(lout "New max. number: " maxRes ", word: " w ", central letter: " centl)
) ) ) )
}</syntaxhighlight>
{{out}}
<pre>
Main part of task:
 
Number of words: 17;
word list: ["eke", "elk", "keel", "keen", "keg", "ken", "keno", "knee", "kneel", "knew", "know", "knowledge", "kong", "leek", "week", "wok", "woke"]
 
 
Optional part of task:
 
New max. number: 100, word: abdominal, central letter: a
New max. number: 117, word: abernathy, central letter: a
New max. number: 119, word: abhorrent, central letter: r
New max. number: 121, word: absorbent, central letter: e
New max. number: 123, word: adsorbate, central letter: a
New max. number: 125, word: adventure, central letter: e
New max. number: 155, word: advertise, central letter: e
New max. number: 161, word: alongside, central letter: a
New max. number: 170, word: alongside, central letter: l
New max. number: 182, word: ancestral, central letter: a
New max. number: 182, word: arclength, central letter: a
New max. number: 185, word: beplaster, central letter: e
New max. number: 215, word: claremont, central letter: a
New max. number: 215, word: spearmint, central letter: a
</pre>
 
=={{header|VBScript}}==
<syntaxhighlight lang="vb">
Const wheel="ndeokgelw"
 
Sub print(s):
On Error Resume Next
WScript.stdout.WriteLine (s)
If err= &h80070006& Then WScript.Echo " Please run this script with CScript": WScript.quit
End Sub
 
Dim oDic
Set oDic = WScript.CreateObject("scripting.dictionary")
Dim cnt(127)
Dim fso
Set fso = WScript.CreateObject("Scripting.Filesystemobject")
Set ff=fso.OpenTextFile("unixdict.txt")
i=0
print "reading words of 3 or more letters"
While Not ff.AtEndOfStream
x=LCase(ff.ReadLine)
If Len(x)>=3 Then
If Not odic.exists(x) Then oDic.Add x,0
End If
Wend
print "remaining words: "& oDic.Count & vbcrlf
ff.Close
Set ff=Nothing
Set fso=Nothing
 
Set re=New RegExp
print "removing words with chars not in the wheel"
re.pattern="[^"& wheel &"]"
For Each w In oDic.Keys
If re.test(w) Then oDic.remove(w)
Next
print "remaining words: "& oDic.Count & vbcrlf
 
print "ensuring the mandatory letter "& Mid(wheel,5,1) & " is present"
re.Pattern=Mid(wheel,5,1)
For Each w In oDic.Keys
If Not re.test(w) Then oDic.remove(w)
Next
print "remaining words: "& oDic.Count & vbcrlf
 
print "checking number of chars"
 
Dim nDic
Set nDic = WScript.CreateObject("scripting.dictionary")
For i=1 To Len(wheel)
x=Mid(wheel,i,1)
If nDic.Exists(x) Then
a=nDic(x)
nDic(x)=Array(a(0)+1,0)
Else
nDic.add x,Array(1,0)
End If
Next
 
For Each w In oDic.Keys
For Each c In nDic.Keys
ndic(c)=Array(nDic(c)(0),0)
Next
For ii = 1 To len(w)
c=Mid(w,ii,1)
a=nDic(c)
If (a(0)=a(1)) Then
oDic.Remove(w):Exit For
End If
nDic(c)=Array(a(0),a(1)+1)
Next
Next
 
print "Remaining words "& oDic.count
For Each w In oDic.Keys
print w
Next
</syntaxhighlight>
{{out}}
<small>
<pre>
reading words of 3 or more letters
remaining words: 24945
 
removing words with chars not in the wheel
remaining words: 163
 
ensuring the mandatory letter k is present
remaining words: 27
 
checking number of chars
Remaining words 17
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
</small>
 
=={{header|Wren}}==
{{libheader|Wren-sort}}
{{libheader|Wren-seq}}
<syntaxhighlight lang="wren">import "io" for File
import "./sort" for Sort, Find
import "./seq" for Lst
 
var letters = ["d", "e", "e", "g", "k", "l", "n", "o","w"]
 
var words = File.read("unixdict.txt").split("\n")
// get rid of words under 3 letters or over 9 letters
words = words.where { |w| w.count > 2 && w.count < 10 }.toList
var found = []
for (word in words) {
if (word.indexOf("k") >= 0) {
var lets = letters.toList
var ok = true
for (c in word) {
var ix = Find.first(lets, c)
if (ix == - 1) {
ok = false
break
}
lets.removeAt(ix)
}
if (ok) found.add(word)
}
}
 
System.print("The following %(found.count) words are the solutions to the puzzle:")
System.print(found.join("\n"))
 
// optional extra
var mostFound = 0
var mostWords9 = []
var mostLetters = []
// iterate through all 9 letter words in the dictionary
for (word9 in words.where { |w| w.count == 9 }) {
letters = word9.toList
Sort.insertion(letters)
// get distinct letters
var distinctLetters = Lst.distinct(letters)
// place each distinct letter in the middle and see what we can do with the rest
for (letter in distinctLetters) {
found = 0
for (word in words) {
if (word.indexOf(letter) >= 0) {
var lets = letters.toList
var ok = true
for (c in word) {
var ix = Find.first(lets, c)
if (ix == - 1) {
ok = false
break
}
lets.removeAt(ix)
}
if (ok) found = found + 1
}
}
if (found > mostFound) {
mostFound = found
mostWords9 = [word9]
mostLetters = [letter]
} else if (found == mostFound) {
mostWords9.add(word9)
mostLetters.add(letter)
}
}
}
System.print("\nMost words found = %(mostFound)")
System.print("Nine letter words producing this total:")
for (i in 0...mostWords9.count) {
System.print("%(mostWords9[i]) with central letter '%(mostLetters[i])'")
}</syntaxhighlight>
 
{{out}}
<pre>
The following 17 words are the solutions to the puzzle:
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
 
Most words found = 215
Nine letter words producing this total:
claremont with central letter 'a'
spearmint with central letter 'a'
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang="xpl0">string 0; \use zero-terminated strings
int I, Set, HasK, HasOther, HasDup, ECnt, Ch;
char Word(25);
def LF=$0A, CR=$0D, EOF=$1A;
[FSet(FOpen("unixdict.txt", 0), ^I);
OpenI(3);
repeat I:= 0; HasK:= false; HasOther:= false;
ECnt:= 0; Set:= 0; HasDup:= false;
loop [repeat Ch:= ChIn(3) until Ch # CR; \remove possible CR
if Ch=LF or Ch=EOF then quit;
Word(I):= Ch;
I:= I+1;
if Ch = ^k then HasK:= true;
case Ch of ^k,^n,^d,^e,^o,^g,^l,^w: [] \assume all lowercase
other HasOther:= true;
if Ch = ^e then ECnt:= ECnt+1
else [if Set & 1<<(Ch-^a) then HasDup:= true;
Set:= Set ! 1<<(Ch-^a);
];
];
Word(I):= 0; \terminate string
if I>=3 & HasK & ~HasOther & ~HasDup & ECnt<=2 then
[Text(0, Word); CrLf(0);
];
until Ch = EOF;
]</syntaxhighlight>
 
{{out}}
<pre>
eke
elk
keel
keen
keg
ken
keno
knee
kneel
knew
know
knowledge
kong
leek
week
wok
woke
</pre>
9,486

edits