Anagram generator: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
(J)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(20 intermediate revisions by 7 users not shown)
Line 1:
{{draft task}}
 
There are already [[Anagrams|other]] [[Anagrams/Deranged_anagrams|tasks]] relating to ''finding'' '''existing''' [[wp:Anagram|anagrams]]. This one is about '''creating''' them.
Line 34:
Implementation:
 
<langsyntaxhighlight Jlang="j">anagen=: {{
seed=:. (tolower y)([-.-.)a.{~97+i.26
letters=:. ~.seed
list=:. <;._2 tolower fread x
ok1=:. */@e.&letters every list
ref=:. #/.~seed
counts=:. <: #/.~@(letters,])every ok1#list
ok2=:. counts */ .<:ref
c=:. ok2#counts
maybe=:. i.1,~#c
while. (0=#r)*#maybe do.
assertdone=. *(+/(({:$"2 maybe){.99 252c)*/ e.,maybe=ref
done=: (+/"2 maybe{c)*/ .=ref
if. 1 e. done do.
r=. (;:inv ((done#maybe) { ok2#I.ok1){L:0 1 <;._2 fread x)-.tolower y
if. #r=. r #~ -. r -:"1&tolower y do. r return. end.
end.
stepmaybe=:. ; c {{
<(#~ n */ .<:"1~ [: +/"2 {&m) y,"1 0 ({:y)}.i.#m
}} ref"1(-.done)#maybe
maybe=: ; c step ref"1(-.done)#maybe
end.
EMPTY
}}</langsyntaxhighlight>
 
Conceptually, we're working with a graph here -- given a seed word, we have sequence of letters and a count of each of those letters which we must supply. Given a list of words whose letters do not exceed that count, we extend that list with an additional word, discarding word sequences which go over the letter count. We would repeat as necessary until we satisfy the needed letter counts. Also, we inspect the "final result" and remove our seed word or phrase from it (if it was present -- and if that would have been our only result we would extend our under budget word sequences until they satisfy our letter counts). It seems like two words is usually sufficient here.
 
To limit our resource consumption, we turn this conceptual graph into a directed graph by requiring that the words in our anagram sequence appear in alphabetic order (we could go back and permute each word sequence if we wanted to pad our results).
 
We could further improve performance (and typically generate fewer example anagrams) if we required our initial word choice to include "rarely used letters" and then alternated between increasing alphabetic order and decreasing alphabetic order when adding words to the potential anagrams. This approach would reduce the size of intermediate results which would [usually] significantly increase search speed. But it might require backtracking if our initial choices were unfortunate.
 
Examples:
 
<langsyntaxhighlight Jlang="j"> 'unixdict.txt' anagen 'Rosettacode'
cetera stood
coat oersted
Line 87 ⟶ 91:
downcast eliot
downstate loci
edison walcott</lang>
'unixdict.txt' anagen 'Pizza party time'
aim pizza pretty
airy pizza tempt
amaze ritz tippy
ami pizza pretty
amity pert pizza
amp pizzeria tty
armpit pizza yet
army petit pizza
emit party pizza
imp pizza treaty
impart pizza yet
irma petty pizza
item party pizza
m patty pizzeria
map pizzeria tty
marietta z zippy
mart piety pizza
mary petit pizza
mat pizza pyrite
mater pity pizza
mayer pitt pizza
maze trait zippy
meaty pizza trip
mi piazza pretty
mira petty pizza
mire patty pizza
mite party pizza
mitt piazza prey
mitt piazza pyre
mizar tate zippy
mizar teat zippy
mizar tippy zeta
mt piazza pyrite
myra petit pizza
pam pizzeria tty
party pizza time
patty pizza rime
petty piazza rim
piazza pity term
piazza prime tty
piazza trim type
piety pizza tram
pizza pyrite tam</syntaxhighlight>
 
=={{header|jq}}==
 
This entry provides a number of anagram-related functions, all based
on the profiling of words by the frequency counts of their constituent
letters. The emphasis is on a reasonable level efficiency within the context of general-purpose utility
functions.
 
In general, a streaming approach is taken, in part for speed and to minimize
memory requirements, and in part to highlight jq's support
for streaming.
 
Phrasal anagrams are not limited by a predetermined length,
and are computed as a stream consisting of a sorted list
of words, e.g. for "firefox", one phrasal anagram would be presented as:
<pre>
["off","re","xi"]
</pre>
 
In order to motivate the helper functions, consider first the task
of generating anagrams of a word, $word. In this case,
we have only to construct a listing of relevant words,
which can be done by calling our "dictionary" construction
function:
<pre>
dict(inputs; $word; $word|length)
</pre>
Here, the last argument ensures that only words having the same length
as the target word are selected.
 
Next, consider the task of generating anagrammatic phrases wherein
each word has a minimum length of 2. This would be accomplished by:
<pre>
dict(inputs; $word; 2)
| anagram_phrases($letters)
</pre>
'''Use of gojq'''
 
The program presented here has been tested using both jq, the C-based implementation,
and gojq, the Go implementation of jq, but in the latter case
with the additional definition:
<pre>
def keys_unsorted: keys;
</pre>
 
'''Generic Functions'''
<syntaxhighlight lang=jq>
 
def count(stream): reduce stream as $x (0; .+1);
 
# remove adjacent duplicates
def once(stream):
foreach stream as $x ({prev: null};
if $x == .prev then .emit = null else .emit = $x | .prev = $x end;
select(.emit).emit);
 
# one-for-one subtraction
# if . and $y are arrays, then emit the array difference, respecting multiplicity;
# similarly if both are strings, emit a string representing the difference.
def minus($y):
if type == "array"
then reduce $y[] as $x (.;
index($x) as $ix
| if $ix then .[:$ix] + .[$ix+1:] else . end)
else explode | minus($y|explode) | implode
end;
 
# bag of words
def bow(stream):
reduce stream as $word ({}; .[($word|tostring)] += 1);
</syntaxhighlight>
'''Anagrams'''
<syntaxhighlight lang=jq>
# Input: a string
def profile: bow( explode[] | [.] | implode);
 
# Comparison of profiles
# . and $p2 should be profiles
def le($p2):
. as $p1
| all( keys_unsorted[]; $p1[.] <= $p2[.]);
 
def eq($p2):
. as $p1
| all( keys_unsorted + ($p2|keys_unsorted) | unique[]; $p1[.] == $p2[.]);
 
# Construct a list of relevant words using the given stream.
# $min is the a-priori minimum word length and
# so if $min is the length of $word, we are looking for exact anagrams:
def dict(stream; $word; $min):
($word|length) as $length
| ($word|profile) as $profile
| if $length == $min
then [stream | select(profile|eq($profile))]
else [stream
| select(length >= $min and
length <= $length and
(profile|le($profile)))]
end ;
 
# Input: an array of admissible words.
# Output: a stream of anagrams of $word
def anagram($word):
($word|profile) as $profile
| .[]
| select(profile|eq($profile));
 
# Input: an array of admissible words.
# Output: a stream of subanagrams of $word
# regarding each occurrence of a letter as distinct from all others
def subanagrams($word):
($word|profile) as $profile
| .[]
| select(profile|le($profile));
 
# input: an array to be extended with an additional dictionary word.
# output: a stream of arrays with additional words
# selected from the characters in the string $letters.
# The input array should be in alphabetical order; if it is,
# so will the output array.
def extend($letters; $dict):
if $letters == "" then .
else . as $in
| ($dict|subanagrams($letters)) as $w
| select(if ($in|length) > 0 then $in[-1] <= $w else true end)
| ($letters | minus($w)) as $remaining
| ($in + [$w]) | extend($remaining; $dict)
end;
 
def anagram_phrases($letters):
. as $dict
| once([] | extend($letters; $dict));
 
# Global: $anagram $word $min
def main:
if $anagram
then dict(inputs; $word; $word|length)[]
else dict(inputs; $word; $min)
| anagram_phrases($word)
end ;
 
main
</syntaxhighlight>
'''Invocation template'''
<pre>
< unixdict.txt jq -ncrR --arg word WORD --argjson anagram BOOLEAN --argjson min MIN -f anagram-generator.jq
</pre>
 
where:
* WORD is a string (normally, a word)
* BOOLEAN determines whether anagrams or anagrammatic phrases are sought
* MIN is the minimum length of admissible words to be used if $anagram is false
 
 
'''Examples'''
 
Anagram
<pre>
# Invocation:
< unixdict.txt jq -nrR --arg word read --argjson anagram true --argjson min 3 -f anagram-generator.jq
dare
dear
erda
read
</pre>
 
Anagrammatic phrases
<pre>
# Invocation:
< unixdict.txt jq -ncR --arg word firefox --argjson anagram false --argjson min 2 -f anagram-generator.jq
["ex","fir","of"]
["ex","for","if"]
["ex","fro","if"]
["ex","ir","off"]
["ex","off","ri"]
["fe","fir","ox"]
["fe","fix","or"]
["fe","for","ix"]
["fe","for","xi"]
["fe","fox","ir"]
["fe","fox","ri"]
["fe","fro","ix"]
["fe","fro","xi"]
["fifo","rex"]
["fire","fox"]
["fix","fore"]
["fix","of","re"]
["fox","if","re"]
["if","of","rex"]
["ix","off","re"]
["ix","offer"]
["off","re","xi"]
["offer","xi"]
</pre>
 
=={{header|Julia}}==
<syntaxhighlight lang="julia">const unixwords = split(read("unixdict.txt", String) |> lowercase, r"\s+")
 
function findphrases(anastring::AbstractString, choices, sizelong = 4, n_shortpermitted = 1)
anadict = Dict{Char, Int}()
for c in lowercase(anastring)
if 'a' <= c <= 'z'
anadict[c] = get(anadict, c, 0) + 1
end
end
phrases = String[]
function addword(remaining, phrase, numshort)
for w in unixwords
len = length(w)
numshort < 1 && len < sizelong && continue
any(c -> get(remaining, c, 0) < count(==(c), w), w) && @goto nextword
cdict = copy(remaining)
for c in w
cdict[c] -= 1
end
if all(==(0), values(cdict))
return strip(phrase * " " * w)
elseif (newphrase = addword(cdict, phrase * " " * w, numshort - (len < sizelong))) != nothing
push!(phrases, newphrase)
print(length(phrases), "\b\b\b\b\b\b\b\b\b")
end
@label nextword
end
return nothing
end
addword(anadict, "", n_shortpermitted)
return phrases
end
 
for s in ["Rosetta code", "Joe Biden", "wherrera"]
println("\nFrom '$s':")
foreach(println, findphrases(s, unixwords, 4, 0) |> unique |> sort!)
end
</syntaxhighlight>{{out}}
<pre>
From 'Rosetta code':
cetera stood
coat oersted
coda rosette
code rosetta
coed rosetta
create stood
derate scoot
doctor tease
oersted coat
rosetta code
rosette coda
scoot derate
stood cetera
tease doctor
 
From 'Joe Biden':
done jibe
jibe done
node jibe
 
From 'wherrera':
herr ware
rare wehr
rear wehr
ware herr
wear herr
wehr rare
</pre>
 
=={{header|Nim}}==
{{trans|Julia}}
<syntaxhighlight lang="Nim">import std/[algorithm, sequtils, strutils, tables]
 
proc readWords(filename: string): seq[string] {.compileTime.} =
result = filename.staticRead().splitLines().map(toLowerAscii)
 
const UnixWords = readWords("unixdict.txt")
 
func findPhrases(anaString: string; choices: seq[string];
sizeLong = 4; nShortPermitted = 1): seq[string] =
var anaDict: CountTable[char]
for c in anaString.toLowerAscii:
if c in 'a'..'z':
anadict.inc(c)
var phrases: seq[string]
 
func addWord(remaining: CountTable[char]; phrase: string; numShort: int): string =
for word in UnixWords:
block Search:
if numShort < 1 and word.len < sizeLong:
break Search
if anyIt(word, remaining.getOrDefault(it) < word.count(it)):
break Search
var cdict = remaining
for c in word: cdict.inc(c, -1)
if allIt(cdict.values.toSeq, it == 0):
return strip(phrase & ' ' & word)
let newPhrase = addWord(cdict, phrase & ' ' & word, numshort - ord(word.len < sizeLong))
if newPhrase.len > 0:
phrases.add newPhrase
 
discard addWord(anaDict, "", nShortPermitted)
result = move(phrases)
 
for s in ["Rosetta code", "Joe Biden", "wherrera"]:
echo "From '$#':" % s
for phrase in findPhrases(s, UnixWords, 4, 0).sorted.deduplicate(true):
echo phrase
echo()
</syntaxhighlight>
 
{{out}}
<pre>From 'Rosetta code':
cetera stood
coat oersted
coda rosette
code rosetta
coed rosetta
create stood
derate scoot
doctor tease
oersted coat
rosetta code
rosette coda
scoot derate
stood cetera
tease doctor
 
From 'Joe Biden':
done jibe
jibe done
node jibe
 
From 'wherrera':
herr ware
rare wehr
rear wehr
ware herr
wear herr
wehr rare
</pre>
 
=={{header|Phix}}==
Couldn't really think of a better way than just building a dirty great filter list to get rid of the less interesting answers....
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">bo_ring</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"al"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"alex"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"am"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"an"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"and"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"anent"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ann"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ant"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ar"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ares"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"art"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"at"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ax"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"axle"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"dan"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"dar"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"darn"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"dart"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"de"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"den"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"dent"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"dna"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"drag"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"du"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"dun"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"dunn"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"ed"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"edt"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"eh"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"el"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"em"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"en"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"end"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"eng"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"erg"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"eros"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"est"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"et"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"eta"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ex"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"ga"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"gad"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"gar"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"garth"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ge"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ghent"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"gnat"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"gnu"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"grad"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"gu"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ha"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"had"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"han"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"hand"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"hart"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"hat"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"he"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"hut"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"la"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"lam"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"lao"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"lax"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"lee"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"leo"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"lo"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"lot"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"ma"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"max"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"mao"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"mo"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"moe"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"mel"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"met"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"mt"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"nat"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"nd"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ne"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ned"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"nh"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"nne"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"nu"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"opel"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"opt"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ott"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ox"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pa"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pax"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pee"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pl"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"pm"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"po"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"poe"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rag"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ran"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rand"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"rant"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rat"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rd"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"re"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"red"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ret"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"rna"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ruth"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"sa"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"sat"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"se"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"sort"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"st"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"ta"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tad"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tag"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tam"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tamp"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tao"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"taos"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tan"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tang"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tangent"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tanh"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"tar"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tat"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tater"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tau"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tax"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ted"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tel"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ten"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tenant"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tent"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tern"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"than"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"that"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"the"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"then"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tn"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tnt"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"to"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"top"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tor"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tort"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tot"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"trag"</span><span style="color: #0000FF;">,</span>
<span style="color: #008000;">"tsar"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tun"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tuna"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tung"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"tx"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"un"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ut"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"wa"</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">az</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">word</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)>=</span><span style="color: #008000;">'a'</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)<=</span><span style="color: #008000;">'z'</span> <span style="color: #008080;">and</span> <span style="color: #008080;">not</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;">bo_ring</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">words</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">filter</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">unix_dict</span><span style="color: #0000FF;">(),</span><span style="color: #000000;">az</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">wdsaz</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">({</span><span style="color: #7060A8;">apply</span><span style="color: #0000FF;">(</span><span style="color: #000000;">words</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">sort</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</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: #004080;">sequence</span> <span style="color: #000000;">seen</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">w</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">found</span><span style="color: #0000FF;">={})</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">found</span><span style="color: #0000FF;">={}</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">seen</span> <span style="color: #0000FF;">=</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;">"%s:\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">w</span><span style="color: #0000FF;">})</span>
<span style="color: #000000;">w</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">lower</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">binary_search</span><span style="color: #0000FF;">({</span><span style="color: #000000;">w</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span><span style="color: #000000;">wdsaz</span><span style="color: #0000FF;">))</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">wdsaz</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{</span><span style="color: #004080;">string</span> <span style="color: #000000;">ax</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">wdx</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">wdsaz</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: #000000;">ax</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">w</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</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: #004080;">sequence</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">e</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">j</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ax</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">j</span><span style="color: #0000FF;"><</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #000000;">ax</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]></span><span style="color: #000000;">w</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">do</span> <span style="color: #000000;">j</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;">j</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #000000;">ax</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">w</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</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;">e</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">j</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ax</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">aw</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">words</span><span style="color: #0000FF;">[</span><span style="color: #000000;">wdx</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">filter</span><span style="color: #0000FF;">(</span><span style="color: #000000;">e</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"!="</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</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;">e</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">found</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">found</span><span style="color: #0000FF;">),</span><span style="color: #000000;">aw</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">sf</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sf</span><span style="color: #0000FF;">,</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">seen</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">seen</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sf</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;">" %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #008000;">", "</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;">if</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">test</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">extract</span><span style="color: #0000FF;">(</span><span style="color: #000000;">w</span><span style="color: #0000FF;">,</span><span style="color: #000000;">e</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">found</span><span style="color: #0000FF;">),</span><span style="color: #000000;">aw</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;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #7060A8;">papply</span><span style="color: #0000FF;">({</span><span style="color: #008000;">"Rosetta"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"PureFox"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"PeteLomax"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Wherrera"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"Thundergnat"</span><span style="color: #0000FF;">},</span><span style="color: #000000;">test</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Rosetta:
treat, so
sea, trot
east, rot
seat, rot
state, or
taste, or
oar, test
oat, rest
star, toe
as, otter
PureFox:
peru, fox
pure, fox
rex, of, up
PeteLomax:
exalt, poem
latex, poem
apex, motel
axe, elm, pot
axe, let, mop
axe, me, plot
atom, expel
moat, expel
Wherrera:
rare, wehr
rear, wehr
ware, herr
wear, herr
Thundergnat:
ad, tenth, rung
dragnet, hunt
dang, net, hurt
hard, gent, nut
gannett, hurd
agent, dr, hunt
hang, tend, rut
nag, tend, hurt
nag, thud, rent
rang, thud, net
ah, tend, grunt
ah, dr, gent, nut
haunt, dr, gent
tart, dung, hen
</pre>
 
=={{header|Raku}}==
Using the unixdict.txt word file by default.
 
<syntaxhighlight lang="raku" perl6line>unit sub MAIN ($in is copy = '', :$dict = 'unixdict.txt');
 
say 'Enter a word or phrase to be anagramed. (Loading dictionary)' unless $in.chars;
Line 131 ⟶ 623:
}
}
}</langsyntaxhighlight>
{{out|Truncated to only show the best few as subjectively determined by me}}
''Punctuation, capitalization and (in some cases) word order manually massaged.''
Line 147 ⟶ 639:
I contest waldo
nose to wildcat</pre>
 
=={{header|Wren}}==
{{libheader|Wren-str}}
{{libheader|Wren-perm}}
{{libheader|Wren-seq}}
{{libheader|Wren-sort}}
To avoid any subjectivity, this just produces all two word anagrams of a word or phrase.
 
Alternatives formed by simply changing the order of the two words have been suppressed.
<syntaxhighlight lang="wren">import "io" for File
import "./str" for Str, Char
import "./perm" for Comb
import "./seq" for Lst
import "./sort" for Sort
 
var wordList = "unixdict.txt" // local copy
var words = File.read(wordList).split("\n").map { |w| w.trim() }
var wordMap = {}
for (word in words) {
var letters = word.toList
Sort.insertion(letters)
var sortedWord = letters.join()
if (wordMap.containsKey(sortedWord)) {
wordMap[sortedWord].add(word)
} else {
wordMap[sortedWord] = [word]
}
}
 
var anagramGenerator = Fn.new { |text|
var letters = Str.lower(text).toList
// remove any non-letters
for (i in letters.count-1..0) {
if (!Char.isLetter(letters[i])) letters.removeAt(i)
}
var lc = letters.count
if (lc < 2) return
var h = (lc/2).floor
var tried = {}
for (n in h..1) {
var sameLength = (lc == 2 * n)
for (letters1 in Comb.list(letters, n)) {
Sort.insertion(letters1)
letters1 = letters1.join()
if (tried[letters1]) continue
tried[letters1] = true
var anagrams = wordMap[letters1]
if (anagrams) {
var letters2 = Lst.except(letters, letters1.toList)
Sort.insertion(letters2)
letters2 = letters2.join()
if (sameLength) {
if (tried[letters2]) continue
tried[letters2] = true
}
var anagrams2 = wordMap[letters2]
if (anagrams2) {
for (word1 in anagrams) {
for (word2 in anagrams2) {
System.print(" " + word1 + " " + word2)
}
}
}
}
}
}
}
 
var tests = ["Rosettacode", "PureFox", "Petelomax", "Wherrera", "Thundergnat", "ClintEastwood"]
for (i in 0...tests.count) {
System.print("\n%(tests[i]):")
anagramGenerator.call(tests[i])
}</syntaxhighlight>
 
{{out}}
<pre>
Rosettacode:
scoot derate
stood cetera
stood create
tease doctor
code rosetta
coed rosetta
coat oersted
coda rosette
sao detector
tee ostracod
tad creosote
se doctorate
 
PureFox:
fox peru
fox pure
 
Petelomax:
poem exalt
poem latex
apex motel
alex tempo
axle tempo
atom expel
moat expel
pax omelet
lao exempt
to example
 
Wherrera:
wehr rare
wehr rear
ware herr
wear herr
 
Thundergnat:
ghent tundra
hunt dragnet
gnat thunder
tang thunder
hurd gannett
hurd tangent
 
ClintEastwood:
edison walcott
atwood stencil
clint eastwood
eliot downcast
clio downstate
coil downstate
loci downstate
</pre>
9,476

edits