Word wheel: Difference between revisions
Content added Content deleted
(Added Wren) |
(→{{header|JavaScript}}: Added a local file access version for macOS) |
||
Line 206: | Line 206: | ||
s <- readFile "unixdict.txt" |
s <- readFile "unixdict.txt" |
||
mapM_ putStrLn $ gridWords ["NDE", "OKG", "ELW"] (lines s)</lang> |
mapM_ putStrLn $ gridWords ["NDE", "OKG", "ELW"] (lines s)</lang> |
||
{{Out}} |
|||
<pre>eke |
|||
elk |
|||
keel |
|||
keen |
|||
keg |
|||
ken |
|||
keno |
|||
knee |
|||
kneel |
|||
knew |
|||
know |
|||
knowledge |
|||
kong |
|||
leek |
|||
week |
|||
wok |
|||
woke</pre> |
|||
=={{header|JavaScript}}== |
|||
A version using local access to the dictionary, through the the macOS JavaScript for Automation API. |
|||
{{Works with|JXA}} |
|||
<lang JavaScript>(() => { |
|||
'use strict'; |
|||
// main :: IO () |
|||
const main = () => |
|||
console.log(unlines( |
|||
gridWords(['NDE', 'OKG', 'ELW'])( |
|||
lines(readFile('unixdict.txt')) |
|||
) |
|||
)); |
|||
// gridWords :: [String] -> [String] -> [String] |
|||
const gridWords = grid => |
|||
lexemes => { |
|||
const |
|||
wheel = sort(toLower(concat(grid))), |
|||
wSet = new Set(wheel), |
|||
mid = wheel[4]; |
|||
return lexemes.filter(w => { |
|||
const cs = chars(w); |
|||
return 2 < cs.length && cs.every( |
|||
c => wSet.has(c) |
|||
) && elem('k')(cs) && ( |
|||
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)); |
|||
}; |
|||
// ----------------- GENERIC FUNCTIONS ----------------- |
|||
// chars :: String -> [Char] |
|||
const chars = s => |
|||
s.split(''); |
|||
// concat :: [[a]] -> [a] |
|||
// concat :: [String] -> String |
|||
const concat = xs => ( |
|||
ys => 0 < ys.length ? ( |
|||
ys.every(Array.isArray) ? ( |
|||
[] |
|||
) : '' |
|||
).concat(...ys) : ys |
|||
)(list(xs)); |
|||
// elem :: Eq a => a -> [a] -> Bool |
|||
const elem = x => |
|||
// True if xs contains an instance of x. |
|||
xs => xs.some(y => x === y); |
|||
// lines :: String -> [String] |
|||
const lines = s => |
|||
// A list of strings derived from a single |
|||
// newline-delimited string. |
|||
0 < s.length ? ( |
|||
s.split(/[\r\n]/) |
|||
) : []; |
|||
// list :: StringOrArrayLike b => b -> [a] |
|||
const list = xs => |
|||
// xs itself, if it is an Array, |
|||
// or an Array derived from xs. |
|||
Array.isArray(xs) ? ( |
|||
xs |
|||
) : Array.from(xs || []); |
|||
// readFile :: FilePath -> IO String |
|||
const readFile = fp => { |
|||
// The contents of a text file at the |
|||
// path file fp. |
|||
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 => list(xs).slice() |
|||
.sort((a, b) => a < b ? -1 : (a > b ? 1 : 0)); |
|||
// toLower :: String -> String |
|||
const toLower = s => |
|||
// Lower-case version of string. |
|||
s.toLocaleLowerCase(); |
|||
// unlines :: [String] -> String |
|||
const unlines = xs => |
|||
// A single string formed by the intercalation |
|||
// of a list of strings with the newline character. |
|||
xs.join('\n'); |
|||
// MAIN --- |
|||
return main(); |
|||
})();</lang> |
|||
{{Out}} |
{{Out}} |
||
<pre>eke |
<pre>eke |