Changeable words: Difference between revisions
Add Factor |
No edit summary |
||
(27 intermediate revisions by 19 users not shown) | |||
Line 18: | Line 18: | ||
* [[Levenshtein distance]] |
* [[Levenshtein distance]] |
||
<br><br> |
<br><br> |
||
=={{header|11l}}== |
|||
{{trans|Nim}} |
|||
{{trans|Go}} |
|||
<syntaxhighlight lang="11l">V words = File(‘unixdict.txt’).read().split("\n").filter(word -> word.len > 11) |
|||
F hamming_dist(word1, word2) |
|||
I word1.len != word2.len |
|||
R 0 |
|||
V count = 0 |
|||
L(i) 0 .< word1.len |
|||
I word1[i] != word2[i] |
|||
count++ |
|||
I count == 2 |
|||
L.break // don't care about counts > 2 |
|||
R count |
|||
print("List of changeable words:\n") |
|||
V count = 0 |
|||
L(i) 0 .< words.len |
|||
V word1 = words[i] |
|||
L(j) i + 1 .< words.len |
|||
V word2 = words[j] |
|||
I hamming_dist(word1, word2) == 1 |
|||
print(word1‘ <-> ’word2) |
|||
count += 2 |
|||
print("\nFound "count‘ changeable words.’)</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
List of changeable words: |
|||
aristotelean <-> aristotelian |
|||
claustrophobia <-> claustrophobic |
|||
committeeman <-> committeemen |
|||
committeewoman <-> committeewomen |
|||
complementary <-> complimentary |
|||
confirmation <-> conformation |
|||
congresswoman <-> congresswomen |
|||
councilwoman <-> councilwomen |
|||
craftsperson <-> draftsperson |
|||
eavesdropped <-> eavesdropper |
|||
frontiersman <-> frontiersmen |
|||
handicraftsman <-> handicraftsmen |
|||
incommutable <-> incomputable |
|||
installation <-> instillation |
|||
kaleidescope <-> kaleidoscope |
|||
neuroanatomy <-> neuroanotomy |
|||
newspaperman <-> newspapermen |
|||
nonagenarian <-> nonogenarian |
|||
onomatopoeia <-> onomatopoeic |
|||
philanthrope <-> philanthropy |
|||
prescription <-> proscription |
|||
schizophrenia <-> schizophrenic |
|||
shakespearean <-> shakespearian |
|||
spectroscope <-> spectroscopy |
|||
underclassman <-> underclassmen |
|||
upperclassman <-> upperclassmen |
|||
Found 52 changeable words. |
|||
</pre> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
< |
<syntaxhighlight lang="ada">with Ada.Text_Io; |
||
with Ada.Strings.Fixed; |
with Ada.Strings.Fixed; |
||
with Ada.Containers.Indefinite_Vectors; |
with Ada.Containers.Indefinite_Vectors; |
||
Line 71: | Line 132: | ||
end loop; |
end loop; |
||
end loop; |
end loop; |
||
end Changeable;</ |
end Changeable;</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 77: | Line 138: | ||
claustrophobia <-> claustrophobic |
claustrophobia <-> claustrophobic |
||
committeeman <-> committeemen |
committeeman <-> committeemen |
||
committeewoman <-> committeewomen |
|||
committeeperson <-> committeepeople |
|||
complementary <-> complimentary |
complementary <-> complimentary |
||
confirmation <-> conformation |
confirmation <-> conformation |
||
congresswoman <-> congresswomen |
|||
congressperson <-> congresspeople |
|||
councilwoman <-> councilwomen |
|||
craftsperson <-> draftsperson |
craftsperson <-> draftsperson |
||
eavesdropped <-> eavesdropper |
eavesdropped <-> eavesdropper |
||
Line 101: | Line 162: | ||
upperclassman <-> upperclassmen |
upperclassman <-> upperclassmen |
||
</pre> |
</pre> |
||
=={{header|ALGOL 68}}== |
|||
Brute force - tries each possible changed word. |
|||
<syntaxhighlight lang="algol68"> |
|||
# find words where changing one letter results in another word # |
|||
# only words of 12 or more characters are to be considered # |
|||
IF FILE input file; |
|||
STRING file name = "unixdict.txt"; |
|||
open( input file, file name, stand in channel ) /= 0 |
|||
THEN |
|||
# failed to open the file # |
|||
print( ( "Unable to open """ + file name + """", newline ) ) |
|||
ELSE |
|||
# file opened OK # |
|||
BOOL at eof := FALSE; |
|||
# set the EOF handler for the file - notes eof has been reached and # |
|||
# returns TRUE so processing can continue # |
|||
on logical file end( input file, ( REF FILE f )BOOL: at eof := TRUE ); |
|||
# table of possible words - there are around 1000 12+ character words # |
|||
[ 1 : 2 000 ]STRING words; # in unixdict.txt # |
|||
# in-place quick sort an array of strings # |
|||
PROC s quicksort = ( REF[]STRING a, INT lb, ub )VOID: |
|||
IF ub > lb |
|||
THEN |
|||
# more than one element, so must sort # |
|||
INT left := lb; |
|||
INT right := ub; |
|||
# choosing the middle element of the array as the pivot # |
|||
STRING pivot := a[ left + ( ( right + 1 ) - left ) OVER 2 ]; |
|||
WHILE |
|||
WHILE IF left <= ub THEN a[ left ] < pivot ELSE FALSE FI |
|||
DO |
|||
left +:= 1 |
|||
OD; |
|||
WHILE IF right >= lb THEN a[ right ] > pivot ELSE FALSE FI |
|||
DO |
|||
right -:= 1 |
|||
OD; |
|||
left <= right |
|||
DO |
|||
STRING t := a[ left ]; |
|||
a[ left ] := a[ right ]; |
|||
a[ right ] := t; |
|||
left +:= 1; |
|||
right -:= 1 |
|||
OD; |
|||
s quicksort( a, lb, right ); |
|||
s quicksort( a, left, ub ) |
|||
FI # s quicksort # ; |
|||
# returns the length of s # |
|||
OP LENGTH = ( STRING s )INT: 1 + ( UPB s - LWB s ); |
|||
# returns TRUE if words[ low : high ] contains s, FALSE otherwise # |
|||
PROC is word = ( STRING s, INT low, high )BOOL: |
|||
IF high < low THEN FALSE |
|||
ELSE INT mid = ( low + high ) OVER 2; |
|||
IF words[ mid ] > s THEN is word( s, low, mid - 1 ) |
|||
ELIF words[ mid ] = s THEN TRUE |
|||
ELSE is word( s, mid + 1, high ) |
|||
FI |
|||
FI # is word # ; |
|||
INT w count := 0; # store the 12 character words # |
|||
WHILE |
|||
STRING word; |
|||
get( input file, ( word, newline ) ); |
|||
NOT at eof |
|||
DO |
|||
IF LENGTH word > 11 THEN |
|||
words[ w count +:= 1 ] := word |
|||
FI |
|||
OD; |
|||
close( input file ); |
|||
s quicksort( words, 1, w count ); # sort the words # |
|||
FOR i TO w count DO # find the changeable words # |
|||
STRING word = words[ i ]; |
|||
STRING c word := word; |
|||
FOR i FROM LWB word TO UPB word DO |
|||
FOR c FROM ABS word[ i ] + 1 TO ABS "z" DO |
|||
c word[ i ] := REPR c; |
|||
IF is word( c word, 1, w count ) THEN |
|||
FOR p FROM LENGTH word TO 15 DO print( ( " " ) ) OD; |
|||
print( ( word, " <-> ", c word, newline ) ) |
|||
FI |
|||
OD; |
|||
c word[ i ] := word[ i ] |
|||
OD |
|||
OD |
|||
FI |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
aristotelean <-> aristotelian |
|||
claustrophobia <-> claustrophobic |
|||
committeeman <-> committeemen |
|||
committeewoman <-> committeewomen |
|||
complementary <-> complimentary |
|||
confirmation <-> conformation |
|||
congresswoman <-> congresswomen |
|||
councilwoman <-> councilwomen |
|||
craftsperson <-> draftsperson |
|||
eavesdropped <-> eavesdropper |
|||
frontiersman <-> frontiersmen |
|||
handicraftsman <-> handicraftsmen |
|||
incommutable <-> incomputable |
|||
installation <-> instillation |
|||
kaleidescope <-> kaleidoscope |
|||
neuroanatomy <-> neuroanotomy |
|||
newspaperman <-> newspapermen |
|||
nonagenarian <-> nonogenarian |
|||
onomatopoeia <-> onomatopoeic |
|||
philanthrope <-> philanthropy |
|||
prescription <-> proscription |
|||
schizophrenia <-> schizophrenic |
|||
shakespearean <-> shakespearian |
|||
spectroscope <-> spectroscopy |
|||
underclassman <-> underclassmen |
|||
upperclassman <-> upperclassmen |
|||
</pre> |
|||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="rebol">wordset: map read.lines relative "unixdict.txt" => strip |
|||
wordset: select wordset 'word -> 12 =< size word |
|||
results: new [] |
|||
loop wordset 'a [ |
|||
loop select wordset 'word [equal? size a size word] 'b [ |
|||
if a <> b [ |
|||
if 1 = levenshtein a b [ |
|||
'results ++ @[sort @[a b]] |
|||
] |
|||
] |
|||
] |
|||
] |
|||
loop unique results 'result -> |
|||
print join.with:" - " result</syntaxhighlight> |
|||
{{out}} |
|||
<pre>aristotelean - aristotelian |
|||
claustrophobia - claustrophobic |
|||
committeeman - committeemen |
|||
committeewoman - committeewomen |
|||
complementary - complimentary |
|||
confirmation - conformation |
|||
congresswoman - congresswomen |
|||
councilwoman - councilwomen |
|||
craftsperson - draftsperson |
|||
eavesdropped - eavesdropper |
|||
frontiersman - frontiersmen |
|||
handicraftsman - handicraftsmen |
|||
incommutable - incomputable |
|||
installation - instillation |
|||
kaleidescope - kaleidoscope |
|||
neuroanatomy - neuroanotomy |
|||
newspaperman - newspapermen |
|||
nonagenarian - nonogenarian |
|||
onomatopoeia - onomatopoeic |
|||
philanthrope - philanthropy |
|||
prescription - proscription |
|||
schizophrenia - schizophrenic |
|||
shakespearean - shakespearian |
|||
spectroscope - spectroscopy |
|||
underclassman - underclassmen |
|||
upperclassman - upperclassmen</pre> |
|||
=={{header|AutoHotkey}}== |
|||
<syntaxhighlight lang="autohotkey">FileRead, db, % A_Desktop "\unixdict.txt" |
|||
oWord := [], Found := [] |
|||
for i, word in StrSplit(db, "`n", "`r") |
|||
if (StrLen(word) > 11) |
|||
oWord[word] := true |
|||
for word1 in oWord |
|||
for word2 in oWord |
|||
if Changeable(word1, word2) && !Found[word2] |
|||
found[word1] := true, result .= word1 . "`t<-> " word2 "`n" |
|||
MsgBox, 262144, , % result |
|||
return |
|||
Changeable(s1, s2) { |
|||
if (StrLen(s1) <> StrLen(s2)) |
|||
return 0 |
|||
for i, v in StrSplit(s1) |
|||
if (v = SubStr(s2, i, 1)) |
|||
num++ |
|||
return (StrLen(s1) - num = 1) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>aristotelean <-> aristotelian |
|||
claustrophobia <-> claustrophobic |
|||
committeeman <-> committeemen |
|||
committeewoman <-> committeewomen |
|||
complementary <-> complimentary |
|||
confirmation <-> conformation |
|||
congresswoman <-> congresswomen |
|||
councilwoman <-> councilwomen |
|||
craftsperson <-> draftsperson |
|||
eavesdropped <-> eavesdropper |
|||
frontiersman <-> frontiersmen |
|||
handicraftsman <-> handicraftsmen |
|||
incommutable <-> incomputable |
|||
installation <-> instillation |
|||
kaleidescope <-> kaleidoscope |
|||
neuroanatomy <-> neuroanotomy |
|||
newspaperman <-> newspapermen |
|||
nonagenarian <-> nonogenarian |
|||
onomatopoeia <-> onomatopoeic |
|||
philanthrope <-> philanthropy |
|||
prescription <-> proscription |
|||
schizophrenia <-> schizophrenic |
|||
shakespearean <-> shakespearian |
|||
spectroscope <-> spectroscopy |
|||
underclassman <-> underclassmen |
|||
upperclassman <-> upperclassmen</pre> |
|||
=={{header|AWK}}== |
=={{header|AWK}}== |
||
<syntaxhighlight lang="awk"> |
|||
<lang AWK> |
|||
# syntax: GAWK -f CHANGEABLE_WORDS.AWK unixdict.txt |
# syntax: GAWK -f CHANGEABLE_WORDS.AWK unixdict.txt |
||
# |
# |
||
Line 150: | Line 430: | ||
exit(0) |
exit(0) |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 159: | Line 439: | ||
committeeman committeemen |
committeeman committeemen |
||
committeemen committeeman |
committeemen committeeman |
||
committeewoman committeewomen |
|||
committeeperson committeepeople |
|||
committeewomen committeewoman |
|||
committeepeople committeeperson |
|||
complementary complimentary |
complementary complimentary |
||
complimentary complementary |
complimentary complementary |
||
confirmation conformation |
confirmation conformation |
||
conformation confirmation |
conformation confirmation |
||
congresswoman congresswomen |
|||
congressperson congresspeople |
|||
congresswomen congresswoman |
|||
congresspeople congressperson |
|||
councilwoman councilwomen |
|||
councilperson councilpeople |
|||
councilwomen councilwoman |
|||
councilpeople councilperson |
|||
craftsperson draftsperson |
craftsperson draftsperson |
||
draftsperson craftsperson |
draftsperson craftsperson |
||
Line 208: | Line 488: | ||
=={{header|C}}== |
=={{header|C}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
#include <string.h> |
#include <string.h> |
||
Line 293: | Line 573: | ||
free(dictionary); |
free(dictionary); |
||
return EXIT_SUCCESS; |
return EXIT_SUCCESS; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 304: | Line 584: | ||
5: committeeman -> committeemen |
5: committeeman -> committeemen |
||
6: committeemen -> committeeman |
6: committeemen -> committeeman |
||
7: |
7: committeewoman -> committeewomen |
||
8: |
8: committeewomen -> committeewoman |
||
9: complementary -> complimentary |
9: complementary -> complimentary |
||
10: complimentary -> complementary |
10: complimentary -> complementary |
||
11: confirmation -> conformation |
11: confirmation -> conformation |
||
12: conformation -> confirmation |
12: conformation -> confirmation |
||
13: |
13: congresswoman -> congresswomen |
||
14: |
14: congresswomen -> congresswoman |
||
15: |
15: councilwoman -> councilwomen |
||
16: |
16: councilwomen -> councilwoman |
||
17: craftsperson -> draftsperson |
17: craftsperson -> draftsperson |
||
18: draftsperson -> craftsperson |
18: draftsperson -> craftsperson |
||
Line 351: | Line 631: | ||
52: upperclassmen -> upperclassman |
52: upperclassmen -> upperclassman |
||
</pre> |
</pre> |
||
=={{header|C++}}== |
=={{header|C++}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="cpp">#include <cstdlib> |
||
#include <fstream> |
#include <fstream> |
||
#include <iomanip> |
#include <iomanip> |
||
Line 401: | Line 680: | ||
} |
} |
||
return EXIT_SUCCESS; |
return EXIT_SUCCESS; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 412: | Line 691: | ||
5: committeeman -> committeemen |
5: committeeman -> committeemen |
||
6: committeemen -> committeeman |
6: committeemen -> committeeman |
||
7: |
7: committeewoman -> committeewomen |
||
8: |
8: committeewomen -> committeewoman |
||
9: complementary -> complimentary |
9: complementary -> complimentary |
||
10: complimentary -> complementary |
10: complimentary -> complementary |
||
11: confirmation -> conformation |
11: confirmation -> conformation |
||
12: conformation -> confirmation |
12: conformation -> confirmation |
||
13: |
13: congresswoman -> congresswomen |
||
14: |
14: congresswomen -> congresswoman |
||
15: |
15: councilwoman -> councilwomen |
||
16: |
16: councilwomen -> councilwoman |
||
17: craftsperson -> draftsperson |
17: craftsperson -> draftsperson |
||
18: draftsperson -> craftsperson |
18: draftsperson -> craftsperson |
||
Line 460: | Line 739: | ||
</pre> |
</pre> |
||
=={{header|Delphi}}== |
|||
{{works with|Delphi|6.0}} |
|||
{{libheader|Classes,SysUtils,StdCtrls}} |
|||
<syntaxhighlight lang="Delphi"> |
|||
var Dict: TStringList; {List holds dictionary} |
|||
procedure DoChangeWords(Memo: TMemo); |
|||
{Do change word problem} |
|||
var I,J,K,Inx,Cnt: integer; |
|||
var S: string; |
|||
procedure Display(OldStr,NewStr: string); |
|||
{Display both the original word and the modified word} |
|||
begin |
|||
Inc(Cnt); |
|||
Memo.Lines.Add(IntToStr(Cnt)+': '+OldStr+' '+NewStr); |
|||
end; |
|||
begin |
|||
Cnt:=0; |
|||
{Check every word in the dictionary} |
|||
for I:=0 to Dict.Count-1 do |
|||
begin |
|||
{Only check words at least 12 chars long} |
|||
if Length(Dict[I])>=12 then |
|||
begin |
|||
{Test a specific position in the word} |
|||
for J:=1 to Length(Dict[I]) do |
|||
begin |
|||
{try all combinations of alpha chars in the position} |
|||
for K:=byte('a') to byte('z') do |
|||
begin |
|||
{skip if the char is already in the position} |
|||
if Dict[I][J]=char(K) then continue; |
|||
{Get a new copy of the word to modify} |
|||
S:=Dict[I]; |
|||
{Modify the position} |
|||
S[J]:=char(K); |
|||
{Is it in the dictionary? } |
|||
Inx:=Dict.IndexOf(S); |
|||
{Display it if it is} |
|||
if Inx>=0 then Display(Dict[I],S); |
|||
end; |
|||
end; |
|||
end; |
|||
end; |
|||
end; |
|||
initialization |
|||
{Create/load dictionary} |
|||
Dict:=TStringList.Create; |
|||
Dict.LoadFromFile('unixdict.txt'); |
|||
Dict.Sorted:=True; |
|||
finalization |
|||
Dict.Free; |
|||
end. |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1: aristotelean aristotelian |
|||
2: aristotelian aristotelean |
|||
3: claustrophobia claustrophobic |
|||
4: claustrophobic claustrophobia |
|||
5: committeeman committeemen |
|||
6: committeemen committeeman |
|||
7: committeewoman committeewomen |
|||
8: committeewomen committeewoman |
|||
9: complementary complimentary |
|||
10: complimentary complementary |
|||
11: confirmation conformation |
|||
12: conformation confirmation |
|||
13: congresswoman congresswomen |
|||
14: congresswomen congresswoman |
|||
15: councilwoman councilwomen |
|||
16: councilwomen councilwoman |
|||
17: craftsperson draftsperson |
|||
18: draftsperson craftsperson |
|||
19: eavesdropped eavesdropper |
|||
20: eavesdropper eavesdropped |
|||
21: frontiersman frontiersmen |
|||
22: frontiersmen frontiersman |
|||
23: handicraftsman handicraftsmen |
|||
24: handicraftsmen handicraftsman |
|||
25: incommutable incomputable |
|||
26: incomputable incommutable |
|||
27: installation instillation |
|||
28: instillation installation |
|||
29: kaleidescope kaleidoscope |
|||
30: kaleidoscope kaleidescope |
|||
31: neuroanatomy neuroanotomy |
|||
32: neuroanotomy neuroanatomy |
|||
33: newspaperman newspapermen |
|||
34: newspapermen newspaperman |
|||
35: nonagenarian nonogenarian |
|||
36: nonogenarian nonagenarian |
|||
37: onomatopoeia onomatopoeic |
|||
38: onomatopoeic onomatopoeia |
|||
39: philanthrope philanthropy |
|||
40: philanthropy philanthrope |
|||
41: prescription proscription |
|||
42: proscription prescription |
|||
43: schizophrenia schizophrenic |
|||
44: schizophrenic schizophrenia |
|||
45: shakespearean shakespearian |
|||
46: shakespearian shakespearean |
|||
47: spectroscope spectroscopy |
|||
48: spectroscopy spectroscope |
|||
49: underclassman underclassmen |
|||
50: underclassmen underclassman |
|||
51: upperclassman upperclassmen |
|||
52: upperclassmen upperclassman |
|||
</pre> |
|||
=={{header|F_Sharp|F#}}== |
|||
<syntaxhighlight lang="fsharp"> |
|||
// Changeable words: Nigel Galloway. June 14th., 2021 |
|||
let fN g=Seq.fold2(fun z n g->z+if n=g then 0 else 1) 0 g |
|||
let rec fG n g=match g with h::t->fG(n@(t|>List.choose(fun g->match fN g h with 1->Some(h,g)|_->None))) t|_->n |
|||
seq{use n=System.IO.File.OpenText("unixdict.txt") in while not n.EndOfStream do yield n.ReadLine()}|>Seq.filter(fun n->n.Length>11) |
|||
|>List.ofSeq|>List.groupBy(fun n->n.Length)|>Seq.collect(fun(_,n)->fG [] n)|>Seq.iter(fun(n,g)->printfn "%s <=> %s" n g) |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
claustrophobia <=> claustrophobic |
|||
committeewoman <=> committeewomen |
|||
handicraftsman <=> handicraftsmen |
|||
aristotelean <=> aristotelian |
|||
committeeman <=> committeemen |
|||
confirmation <=> conformation |
|||
councilwoman <=> councilwomen |
|||
craftsperson <=> draftsperson |
|||
eavesdropped <=> eavesdropper |
|||
frontiersman <=> frontiersmen |
|||
incommutable <=> incomputable |
|||
installation <=> instillation |
|||
kaleidescope <=> kaleidoscope |
|||
neuroanatomy <=> neuroanotomy |
|||
newspaperman <=> newspapermen |
|||
nonagenarian <=> nonogenarian |
|||
onomatopoeia <=> onomatopoeic |
|||
philanthrope <=> philanthropy |
|||
prescription <=> proscription |
|||
spectroscope <=> spectroscopy |
|||
complementary <=> complimentary |
|||
congresswoman <=> congresswomen |
|||
schizophrenia <=> schizophrenic |
|||
shakespearean <=> shakespearian |
|||
underclassman <=> underclassmen |
|||
upperclassman <=> upperclassmen |
|||
</pre> |
|||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
{{works with|Factor|0.99 2021-02-05}} |
{{works with|Factor|0.99 2021-02-05}} |
||
< |
<syntaxhighlight lang="factor">USING: assocs combinators.short-circuit formatting |
||
io.encodings.ascii io.files kernel math math.combinatorics |
io.encodings.ascii io.files kernel math math.combinatorics |
||
math.distances sequences ; |
math.distances sequences ; |
||
Line 472: | Line 907: | ||
[ length 11 > ] filter |
[ length 11 > ] filter |
||
2 [ first2 changeable? ] filter-combinations |
2 [ first2 changeable? ] filter-combinations |
||
[ "%s <-> %s\n" printf ] assoc-each</ |
[ "%s <-> %s\n" printf ] assoc-each</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 478: | Line 913: | ||
claustrophobia <-> claustrophobic |
claustrophobia <-> claustrophobic |
||
committeeman <-> committeemen |
committeeman <-> committeemen |
||
committeewoman <-> committeewomen |
|||
committeeperson <-> committeepeople |
|||
complementary <-> complimentary |
complementary <-> complimentary |
||
confirmation <-> conformation |
confirmation <-> conformation |
||
congresswoman <-> congresswomen |
|||
congressperson <-> congresspeople |
|||
councilwoman <-> councilwomen |
|||
councilperson <-> councilpeople |
|||
craftsperson <-> draftsperson |
craftsperson <-> draftsperson |
||
eavesdropped <-> eavesdropper |
eavesdropped <-> eavesdropper |
||
Line 502: | Line 937: | ||
upperclassman <-> upperclassmen |
upperclassman <-> upperclassmen |
||
</pre> |
</pre> |
||
=={{header|FreeBASIC}}== |
=={{header|FreeBASIC}}== |
||
Brute force method, reuses some code from [[Odd_words#FreeBASIC]]. |
Brute force method, reuses some code from [[Odd_words#FreeBASIC]]. |
||
< |
<syntaxhighlight lang="freebasic"> |
||
#define NULL 0 |
#define NULL 0 |
||
Line 561: | Line 995: | ||
next i |
next i |
||
curr = curr->nxt |
curr = curr->nxt |
||
wend</ |
wend</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 570: | Line 1,004: | ||
committeeman ---> committeemen |
committeeman ---> committeemen |
||
committeemen ---> committeeman |
committeemen ---> committeeman |
||
committeewoman ---> committeewomen |
|||
committeewomen ---> committeewoman |
|||
complementary ---> complimentary |
complementary ---> complimentary |
||
complimentary ---> complementary |
complimentary ---> complementary |
||
confirmation ---> conformation |
confirmation ---> conformation |
||
conformation ---> confirmation |
conformation ---> confirmation |
||
congresswoman ---> congresswomen |
|||
congresswomen ---> congresswoman |
|||
councilwoman ---> councilwomen |
|||
councilwomen ---> councilwoman |
|||
craftsperson ---> draftsperson |
craftsperson ---> draftsperson |
||
draftsperson ---> craftsperson |
draftsperson ---> craftsperson |
||
Line 616: | Line 1,050: | ||
upperclassman ---> upperclassmen |
upperclassman ---> upperclassmen |
||
upperclassmen ---> upperclassman</pre> |
upperclassmen ---> upperclassman</pre> |
||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
#plist NSAppTransportSecurity @{NSAllowsArbitraryLoads:YES} |
|||
include "NSLog.incl" |
|||
local fn Words as CFArrayRef |
|||
CFURLRef url = fn URLWithString( @"http://wiki.puzzlers.org/pub/wordlists/unixdict.txt" ) |
|||
CFStringRef string = fn StringWithContentsOfURL( url, NSUTF8StringEncoding, NULL ) |
|||
CFArrayRef array = fn StringComponentsSeparatedByCharactersInSet( string, fn CharacterSetNewlineSet ) |
|||
CFMutableArrayRef words = fn MutableArrayWithCapacity(0) |
|||
for string in array |
|||
if ( len(string) > 11 ) |
|||
MutableArrayAddObject( words, string ) |
|||
end if |
|||
next |
|||
end fn = words |
|||
void local fn DoIt |
|||
dispatchglobal |
|||
CFArrayRef words = fn Words |
|||
CFStringRef wd1, wd2 |
|||
long length, i, j |
|||
unichar chr |
|||
for wd1 in words |
|||
length = len(wd1) |
|||
for i = 0 to length - 1 |
|||
chr = fn StringCharacterAtIndex( wd1, i ) |
|||
for j = 97 to 122 |
|||
if ( j == chr ) then continue |
|||
wd2 = fn StringWithFormat( @"%@%c%@", left(wd1,i), j, right(wd1,length-i-1) ) |
|||
if ( fn ArrayContainsObject( words, wd2 ) ) |
|||
NSLog(@"%@\t%@",wd1,wd2) |
|||
end if |
|||
next |
|||
next |
|||
next |
|||
dispatchend |
|||
end fn |
|||
fn DoIt |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre style="height:30ex"> |
|||
aristotelean aristotelian |
|||
aristotelian aristotelean |
|||
claustrophobia claustrophobic |
|||
claustrophobic claustrophobia |
|||
committeeman committeemen |
|||
committeemen committeeman |
|||
committeewoman committeewomen |
|||
committeewomen committeewoman |
|||
complementary complimentary |
|||
complimentary complementary |
|||
confirmation conformation |
|||
conformation confirmation |
|||
congresswoman congresswomen |
|||
congresswomen congresswoman |
|||
councilwoman councilwomen |
|||
councilwomen councilwoman |
|||
craftsperson draftsperson |
|||
draftsperson craftsperson |
|||
eavesdropped eavesdropper |
|||
eavesdropper eavesdropped |
|||
frontiersman frontiersmen |
|||
frontiersmen frontiersman |
|||
handicraftsman handicraftsmen |
|||
handicraftsmen handicraftsman |
|||
incommutable incomputable |
|||
incomputable incommutable |
|||
installation instillation |
|||
instillation installation |
|||
kaleidescope kaleidoscope |
|||
kaleidoscope kaleidescope |
|||
neuroanatomy neuroanotomy |
|||
neuroanotomy neuroanatomy |
|||
newspaperman newspapermen |
|||
newspapermen newspaperman |
|||
nonagenarian nonogenarian |
|||
nonogenarian nonagenarian |
|||
onomatopoeia onomatopoeic |
|||
onomatopoeic onomatopoeia |
|||
philanthrope philanthropy |
|||
philanthropy philanthrope |
|||
prescription proscription |
|||
proscription prescription |
|||
schizophrenia schizophrenic |
|||
schizophrenic schizophrenia |
|||
shakespearean shakespearian |
|||
shakespearian shakespearean |
|||
spectroscope spectroscopy |
|||
spectroscopy spectroscope |
|||
underclassman underclassmen |
|||
underclassmen underclassman |
|||
upperclassman upperclassmen |
|||
upperclassmen upperclassman |
|||
</pre> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
{{trans|Wren}} |
{{trans|Wren}} |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 671: | Line 1,209: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 682: | Line 1,220: | ||
5: committeeman -> committeemen |
5: committeeman -> committeemen |
||
6: committeemen -> committeeman |
6: committeemen -> committeeman |
||
7: |
7: committeewoman -> committeewomen |
||
8: |
8: committeewomen -> committeewoman |
||
9: complementary -> complimentary |
9: complementary -> complimentary |
||
10: complimentary -> complementary |
10: complimentary -> complementary |
||
11: confirmation -> conformation |
11: confirmation -> conformation |
||
12: conformation -> confirmation |
12: conformation -> confirmation |
||
13: |
13: congresswoman -> congresswomen |
||
14: |
14: congresswomen -> congresswoman |
||
15: |
15: councilwoman -> councilwomen |
||
16: |
16: councilwomen -> councilwoman |
||
17: craftsperson -> draftsperson |
17: craftsperson -> draftsperson |
||
18: draftsperson -> craftsperson |
18: draftsperson -> craftsperson |
||
Line 729: | Line 1,267: | ||
52: upperclassmen -> upperclassman |
52: upperclassmen -> upperclassman |
||
</pre> |
</pre> |
||
=={{header|J}}== |
|||
<syntaxhighlight lang="j"> ;:inv ({~ ~.@($ /:~"1@#: I.@,)@(1=+/ .~: ::0:&>/~))(#~ 11<#@>) cutLF fread'unixdict.txt' |
|||
aristotelean aristotelian |
|||
claustrophobia claustrophobic |
|||
committeeman committeemen |
|||
committeewoman committeewomen |
|||
complementary complimentary |
|||
confirmation conformation |
|||
congresswoman congresswomen |
|||
councilwoman councilwomen |
|||
craftsperson draftsperson |
|||
eavesdropped eavesdropper |
|||
frontiersman frontiersmen |
|||
handicraftsman handicraftsmen |
|||
incommutable incomputable |
|||
installation instillation |
|||
kaleidescope kaleidoscope |
|||
neuroanatomy neuroanotomy |
|||
newspaperman newspapermen |
|||
nonagenarian nonogenarian |
|||
onomatopoeia onomatopoeic |
|||
philanthrope philanthropy |
|||
prescription proscription |
|||
schizophrenia schizophrenic |
|||
shakespearean shakespearian |
|||
spectroscope spectroscopy |
|||
underclassman underclassmen |
|||
upperclassman upperclassmen</syntaxhighlight> |
|||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="java">import java.io.*; |
||
import java.util.*; |
import java.util.*; |
||
Line 775: | Line 1,340: | ||
return count; |
return count; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 786: | Line 1,351: | ||
5: committeeman -> committeemen |
5: committeeman -> committeemen |
||
6: committeemen -> committeeman |
6: committeemen -> committeeman |
||
7: |
7: committeewoman -> committeewomen |
||
8: |
8: committeewomen -> committeewoman |
||
9: complementary -> complimentary |
9: complementary -> complimentary |
||
10: complimentary -> complementary |
10: complimentary -> complementary |
||
11: confirmation -> conformation |
11: confirmation -> conformation |
||
12: conformation -> confirmation |
12: conformation -> confirmation |
||
13: |
13: congresswoman -> congresswomen |
||
14: |
14: congresswomen -> congresswoman |
||
15: |
15: councilwoman -> councilwomen |
||
16: |
16: councilwomen -> councilwoman |
||
17: craftsperson -> draftsperson |
17: craftsperson -> draftsperson |
||
18: draftsperson -> craftsperson |
18: draftsperson -> craftsperson |
||
Line 833: | Line 1,398: | ||
52: upperclassmen -> upperclassman |
52: upperclassmen -> upperclassman |
||
</pre> |
</pre> |
||
=={{header|jq}}== |
|||
{{works with|jq}} |
|||
'''Works with gojq, the Go implementation of jq''' |
|||
<syntaxhighlight lang="jq"># Emit a stream of words "greater than" the input word that differ by just one character. |
|||
def changeable_to($dict): |
|||
. as $w |
|||
| range(0;length) as $i |
|||
| (.[$i:$i+1]|explode[]) as $j |
|||
| [range($j+1;123) | [.] | implode] as $alphas # 122 is "z" |
|||
| .[:$i] + $alphas[] + .[$i+1:] |
|||
| select($dict[.]); |
|||
INDEX( inputs; . ) |
|||
| . as $dict |
|||
| keys_unsorted[] # or keys[] for gojq |
|||
| select(length>11) |
|||
| . as $w |
|||
| [changeable_to($dict)] | unique[] |
|||
| "\($w) <=> \(.)"</syntaxhighlight> |
|||
Invocation: jq -n -rR -f changeable-words.jq unixdict.txt |
|||
{{out}} |
|||
<pre> |
|||
aristotelean <=> aristotelian |
|||
claustrophobia <=> claustrophobic |
|||
committeeman <=> committeemen |
|||
committeewoman <=> committeewomen |
|||
complementary <=> complimentary |
|||
confirmation <=> conformation |
|||
congresswoman <=> congresswomen |
|||
councilwoman <=> councilwomen |
|||
craftsperson <=> draftsperson |
|||
eavesdropped <=> eavesdropper |
|||
frontiersman <=> frontiersmen |
|||
handicraftsman <=> handicraftsmen |
|||
incommutable <=> incomputable |
|||
installation <=> instillation |
|||
kaleidescope <=> kaleidoscope |
|||
neuroanatomy <=> neuroanotomy |
|||
newspaperman <=> newspapermen |
|||
nonagenarian <=> nonogenarian |
|||
onomatopoeia <=> onomatopoeic |
|||
philanthrope <=> philanthropy |
|||
prescription <=> proscription |
|||
schizophrenia <=> schizophrenic |
|||
shakespearean <=> shakespearian |
|||
spectroscope <=> spectroscopy |
|||
underclassman <=> underclassmen |
|||
upperclassman <=> upperclassmen |
|||
</pre> |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
See [[Alternade_words#Julia]] for the foreachword function. |
See [[Alternade_words#Julia]] for the foreachword function. |
||
< |
<syntaxhighlight lang="julia">const alts = Set{String}() |
||
function ischangeable(w, d) |
function ischangeable(w, d) |
||
alternatives = [w[1:p[1]-1] * p[2] * w[p[1]+1:end] for p in Iterators.product(1:length(w), 'a':'z')] |
alternatives = [w[1:p[1]-1] * p[2] * w[p[1]+1:end] for p in Iterators.product(1:length(w), 'a':'z')] |
||
Line 852: | Line 1,465: | ||
foreachword("unixdict.txt", ischangeable, minlen = 12, colwidth=40, numcols=2) |
foreachword("unixdict.txt", ischangeable, minlen = 12, colwidth=40, numcols=2) |
||
</ |
</syntaxhighlight>{{out}} |
||
<pre> |
<pre> |
||
Word source: unixdict.txt |
Word source: unixdict.txt |
||
aristotelean <=> aristotelian claustrophobia <=> claustrophobic |
aristotelean <=> aristotelian claustrophobia <=> claustrophobic |
||
committeeman <=> committeemen |
committeeman <=> committeemen committeewoman <=> committeewomen |
||
complementary <=> complimentary confirmation <=> conformation |
complementary <=> complimentary confirmation <=> conformation |
||
congresswoman <=> congresswomen councilwoman <=> councilwomen |
|||
craftsperson <=> draftsperson eavesdropped <=> eavesdropper |
craftsperson <=> draftsperson eavesdropped <=> eavesdropper |
||
frontiersman <=> frontiersmen handicraftsman <=> handicraftsmen |
frontiersman <=> frontiersmen handicraftsman <=> handicraftsmen |
||
Line 869: | Line 1,482: | ||
shakespearean <=> shakespearian spectroscope <=> spectroscopy |
shakespearean <=> shakespearian spectroscope <=> spectroscopy |
||
underclassman <=> underclassmen upperclassman <=> upperclassmen |
underclassman <=> underclassmen upperclassman <=> upperclassmen |
||
</pre> |
|||
=={{header|Nim}}== |
|||
Using the standard module <code>std/editdistance</code> to get the distance between two words. |
|||
<syntaxhighlight lang="nim">import std/editdistance, sugar |
|||
# Build list of words with length >= 12. |
|||
let words = collect(newSeq): |
|||
for word in "unixdict.txt".lines: |
|||
if word.len >= 12: |
|||
word |
|||
echo "List of changeable words:\n" |
|||
var count = 0 |
|||
for i in 0..<words.high: |
|||
let word1 = words[i] |
|||
for j in i+1..words.high: |
|||
let word2 = words[j] |
|||
if word1.len == word2.len and editDistance(word1, word2) == 1: |
|||
echo word1, " <-> ", word2 |
|||
inc count, 2 |
|||
echo "\nFound ", count, " changeable words."</syntaxhighlight> |
|||
{{out}} |
|||
<pre>List of changeable words: |
|||
aristotelean <-> aristotelian |
|||
claustrophobia <-> claustrophobic |
|||
committeeman <-> committeemen |
|||
committeewoman <-> committeewomen |
|||
complementary <-> complimentary |
|||
confirmation <-> conformation |
|||
congresswoman <-> congresswomen |
|||
councilwoman <-> councilwomen |
|||
craftsperson <-> draftsperson |
|||
eavesdropped <-> eavesdropper |
|||
frontiersman <-> frontiersmen |
|||
handicraftsman <-> handicraftsmen |
|||
incommutable <-> incomputable |
|||
installation <-> instillation |
|||
kaleidescope <-> kaleidoscope |
|||
neuroanatomy <-> neuroanotomy |
|||
newspaperman <-> newspapermen |
|||
nonagenarian <-> nonogenarian |
|||
onomatopoeia <-> onomatopoeic |
|||
philanthrope <-> philanthropy |
|||
prescription <-> proscription |
|||
schizophrenia <-> schizophrenic |
|||
shakespearean <-> shakespearian |
|||
spectroscope <-> spectroscopy |
|||
underclassman <-> underclassmen |
|||
upperclassman <-> upperclassmen |
|||
Found 52 changeable words.</pre> |
|||
=={{header|Pascal}}== |
|||
==={{header|Free Pascal}}=== |
|||
<syntaxhighlight lang="pascal"> |
|||
{$mode ObjFPC}{$H+} |
|||
uses |
|||
Classes, SysUtils; |
|||
const |
|||
FNAME = 'unixdict.txt'; |
|||
function OneCharDifference(s1, s2: string): boolean; |
|||
var |
|||
i, diffCount: integer; |
|||
begin |
|||
diffCount := 0; |
|||
if Length(s1) <> Length(s2) then |
|||
Exit(false); |
|||
for i := 1 to Length(s1) do |
|||
begin |
|||
if s1[i] <> s2[i] then |
|||
Inc(diffCount); |
|||
if diffCount > 1 then |
|||
Exit(false); |
|||
end; |
|||
Result := diffCount = 1; |
|||
end; |
|||
procedure PurgeList(var list: TStringList); |
|||
{ Remove every word that doesn't have at least 12 characters } |
|||
var |
|||
i: Integer; |
|||
begin |
|||
for i := Pred(list.Count) downto 0 do |
|||
if Length(list[i]) < 12 then |
|||
list.Delete(i); |
|||
end; |
|||
var |
|||
list: TStringList; |
|||
i, j: Integer; |
|||
begin |
|||
list := TStringList.Create; |
|||
try |
|||
list.LoadFromFile(FNAME); |
|||
PurgeList(list); |
|||
for i := 0 to list.Count - 2 do |
|||
for j := i + 1 to list.Count - 1 do |
|||
if OneCharDifference(list[i], list[j]) then |
|||
writeln(list[i]:15, ' <-> ', list[j]); |
|||
finally |
|||
list.Free; |
|||
end; |
|||
end. |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
aristotelean <-> aristotelian |
|||
claustrophobia <-> claustrophobic |
|||
committeeman <-> committeemen |
|||
committeewoman <-> committeewomen |
|||
complementary <-> complimentary |
|||
confirmation <-> conformation |
|||
congresswoman <-> congresswomen |
|||
councilwoman <-> councilwomen |
|||
craftsperson <-> draftsperson |
|||
eavesdropped <-> eavesdropper |
|||
frontiersman <-> frontiersmen |
|||
handicraftsman <-> handicraftsmen |
|||
incommutable <-> incomputable |
|||
installation <-> instillation |
|||
kaleidescope <-> kaleidoscope |
|||
neuroanatomy <-> neuroanotomy |
|||
newspaperman <-> newspapermen |
|||
nonagenarian <-> nonogenarian |
|||
onomatopoeia <-> onomatopoeic |
|||
philanthrope <-> philanthropy |
|||
prescription <-> proscription |
|||
schizophrenia <-> schizophrenic |
|||
shakespearean <-> shakespearian |
|||
spectroscope <-> spectroscopy |
|||
underclassman <-> underclassmen |
|||
upperclassman <-> upperclassmen |
|||
</pre> |
</pre> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">#!/usr/bin/perl |
||
use strict; |
use strict; |
||
Line 888: | Line 1,639: | ||
} |
} |
||
push @{ $words[length] }, $_; |
push @{ $words[length] }, $_; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 894: | Line 1,645: | ||
claustrophobia <-> claustrophobic |
claustrophobia <-> claustrophobic |
||
committeeman <-> committeemen |
committeeman <-> committeemen |
||
committeewoman <-> committeewomen |
|||
complementary <-> complimentary |
complementary <-> complimentary |
||
confirmation <-> conformation |
confirmation <-> conformation |
||
congresswoman <-> congresswomen |
|||
councilwoman <-> councilwomen |
|||
craftsperson <-> draftsperson |
craftsperson <-> draftsperson |
||
eavesdropped <-> eavesdropper |
eavesdropped <-> eavesdropper |
||
Line 917: | Line 1,668: | ||
underclassman <-> underclassmen |
underclassman <-> underclassmen |
||
upperclassman <-> upperclassmen |
upperclassman <-> upperclassmen |
||
</pre> |
</pre> Alternatively: |
||
<syntaxhighlight lang="perl">#!/usr/bin/perl |
|||
use strict; # https://rosettacode.org/wiki/Changeable_words |
|||
=={{header|Phix}}== |
|||
use warnings; |
|||
<lang Phix>function changeable(string a, b) |
|||
return length(a)=length(b) and sum(sq_ne(a,b))=1 |
|||
end function |
|||
local $_ = do {local(@ARGV, $/) = 'unixdict.txt'; <> =~ s/^.{0,11}\n//gmr }; |
|||
function over11(string word) return length(word)>11 end function |
|||
my $count = 0; |
|||
sequence words = filter(get_text("demo/unixdict.txt",GT_LF_STRIPPED),over11), |
|||
printf "%3d: %15s <-> %s\n", ++$count, $1, $4 |
|||
res = {} |
|||
while /^ ((\N*)\N(\N*)) \n(?=.*^ (\2\N\3) \n)/gmsx;</syntaxhighlight> |
|||
for i=1 to length(words) do |
|||
{{out}} |
|||
for j=i+1 to length(words) do |
|||
<pre> |
|||
if changeable(words[i],words[j]) then |
|||
1: aristotelean <-> aristotelian |
|||
res = append(res,words[i]&" <=> "&words[j]) |
|||
2: claustrophobia <-> claustrophobic |
|||
end if |
|||
3: committeeman <-> committeemen |
|||
end for |
|||
4: committeewoman <-> committeewomen |
|||
end for |
|||
5: complementary <-> complimentary |
|||
printf(1,"%d changeable words found:\n%s\n",{length(res),join(shorten(res,"",3),"\n")})</lang> |
|||
6: confirmation <-> conformation |
|||
7: congresswoman <-> congresswomen |
|||
8: councilwoman <-> councilwomen |
|||
9: craftsperson <-> draftsperson |
|||
10: eavesdropped <-> eavesdropper |
|||
11: frontiersman <-> frontiersmen |
|||
12: handicraftsman <-> handicraftsmen |
|||
13: incommutable <-> incomputable |
|||
14: installation <-> instillation |
|||
15: kaleidescope <-> kaleidoscope |
|||
16: neuroanatomy <-> neuroanotomy |
|||
17: newspaperman <-> newspapermen |
|||
18: nonagenarian <-> nonogenarian |
|||
19: onomatopoeia <-> onomatopoeic |
|||
20: philanthrope <-> philanthropy |
|||
21: prescription <-> proscription |
|||
22: schizophrenia <-> schizophrenic |
|||
23: shakespearean <-> shakespearian |
|||
24: spectroscope <-> spectroscopy |
|||
25: underclassman <-> underclassmen |
|||
26: upperclassman <-> upperclassmen |
|||
</pre> |
|||
=={{header|Phix}}== |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">changeable</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">sum</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_ne</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">))=</span><span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">over11</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;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">word</span><span style="color: #0000FF;">)></span><span style="color: #000000;">11</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;">over11</span><span style="color: #0000FF;">),</span> |
|||
<span style="color: #000000;">res</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;">words</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</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: #008080;">if</span> <span style="color: #000000;">changeable</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: #000000;">words</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: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</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: #008000;">" <=> "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">words</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;">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;">"%d changeable words found:\n%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">shorten</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">),</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)})</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 946: | Line 1,737: | ||
upperclassman <=> upperclassmen |
upperclassman <=> upperclassmen |
||
</pre> |
</pre> |
||
=={{header|Prolog}}== |
=={{header|Prolog}}== |
||
{{works with|SWI Prolog}} |
{{works with|SWI Prolog}} |
||
{{trans|Go}} |
{{trans|Go}} |
||
< |
<syntaxhighlight lang="prolog">:- dynamic dictionary_word/1. |
||
main:- |
main:- |
||
Line 1,000: | Line 1,790: | ||
Count1 is Count + 1, |
Count1 is Count + 1, |
||
Count1 < 2, |
Count1 < 2, |
||
hamming_distance(Chars1, Chars2, Dist, Count1).</ |
hamming_distance(Chars1, Chars2, Dist, Count1).</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,011: | Line 1,801: | ||
5: committeeman -> committeemen |
5: committeeman -> committeemen |
||
6: committeemen -> committeeman |
6: committeemen -> committeeman |
||
7: |
7: committeewoman -> committeewomen |
||
8: |
8: committeewomen -> committeewoman |
||
9: complementary -> complimentary |
9: complementary -> complimentary |
||
10: complimentary -> complementary |
10: complimentary -> complementary |
||
11: confirmation -> conformation |
11: confirmation -> conformation |
||
12: conformation -> confirmation |
12: conformation -> confirmation |
||
13: |
13: congresswoman -> congresswomen |
||
14: |
14: congresswomen -> congresswoman |
||
15: |
15: councilwoman -> councilwomen |
||
16: |
16: councilwomen -> councilwoman |
||
17: craftsperson -> draftsperson |
17: craftsperson -> draftsperson |
||
18: draftsperson -> craftsperson |
18: draftsperson -> craftsperson |
||
Line 1,058: | Line 1,848: | ||
52: upperclassmen -> upperclassman |
52: upperclassmen -> upperclassman |
||
</pre> |
</pre> |
||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">from collections import defaultdict, Counter |
||
Line 1,099: | Line 1,888: | ||
print(f"\n{len(cwords)} words that are from changing a char from other words:") |
print(f"\n{len(cwords)} words that are from changing a char from other words:") |
||
for v in sorted(cwords): |
for v in sorted(cwords): |
||
print(f" {v[0]:12} From {', '.join(v[1:])}")</ |
print(f" {v[0]:12} From {', '.join(v[1:])}")</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,114: | Line 1,903: | ||
claustrophobia From claustrophobic |
claustrophobia From claustrophobic |
||
committeeman From committeemen |
committeeman From committeemen |
||
committeewoman From committeewomen |
|||
complementary From complimentary |
complementary From complimentary |
||
confirmation From conformation |
confirmation From conformation |
||
congresswoman From congresswomen |
|||
councilwoman From councilwomen |
|||
craftsperson From draftsperson |
craftsperson From draftsperson |
||
eavesdropped From eavesdropper |
eavesdropped From eavesdropper |
||
Line 1,137: | Line 1,926: | ||
underclassman From underclassmen |
underclassman From underclassmen |
||
upperclassman From upperclassmen</pre> |
upperclassman From upperclassmen</pre> |
||
=={{header|Quackery}}== |
|||
<syntaxhighlight lang="Quackery"> [ over size |
|||
over size != iff |
|||
[ 2drop false ] |
|||
done |
|||
0 unrot |
|||
witheach |
|||
[ over i^ peek |
|||
!= rot + swap |
|||
over 2 = if |
|||
conclude ] |
|||
drop 1 = ] is 1diff ( $ $ --> b ) |
|||
$ "rosetta/unixdict.txt" |
|||
sharefile drop nest$ |
|||
[] swap witheach |
|||
[ dup size 11 > iff |
|||
[ nested join ] |
|||
else drop ] |
|||
[ behead over witheach |
|||
[ 2dup |
|||
1diff iff |
|||
[ over echo$ |
|||
sp echo$ cr ] |
|||
else drop ] |
|||
drop |
|||
dup size 1 = until ] |
|||
drop</syntaxhighlight> |
|||
{{out}} |
|||
<pre>aristotelean aristotelian |
|||
claustrophobia claustrophobic |
|||
committeeman committeemen |
|||
committeewoman committeewomen |
|||
complementary complimentary |
|||
confirmation conformation |
|||
congresswoman congresswomen |
|||
councilwoman councilwomen |
|||
craftsperson draftsperson |
|||
eavesdropped eavesdropper |
|||
frontiersman frontiersmen |
|||
handicraftsman handicraftsmen |
|||
incommutable incomputable |
|||
installation instillation |
|||
kaleidescope kaleidoscope |
|||
neuroanatomy neuroanotomy |
|||
newspaperman newspapermen |
|||
nonagenarian nonogenarian |
|||
onomatopoeia onomatopoeic |
|||
philanthrope philanthropy |
|||
prescription proscription |
|||
schizophrenia schizophrenic |
|||
shakespearean shakespearian |
|||
spectroscope spectroscopy |
|||
underclassman underclassmen |
|||
upperclassman upperclassmen</pre> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
Line 1,142: | Line 1,990: | ||
Get the best of both worlds by doing an initial filter with Sorensen, then get exact results with Levenshtein. |
Get the best of both worlds by doing an initial filter with Sorensen, then get exact results with Levenshtein. |
||
<lang |
<syntaxhighlight lang="raku" line>use Text::Levenshtein; |
||
use Text::Sorensen :sorensen; |
use Text::Sorensen :sorensen; |
||
Line 1,160: | Line 2,008: | ||
%skip{$_}++ for @sorensens[@levenshtein]; |
%skip{$_}++ for @sorensens[@levenshtein]; |
||
": {$this.fmt('%14s')} <-> ", @sorensens[@levenshtein].join: ', '; |
": {$this.fmt('%14s')} <-> ", @sorensens[@levenshtein].join: ', '; |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> 1: aristotelean <-> aristotelian |
<pre> 1: aristotelean <-> aristotelian |
||
2: claustrophobia <-> claustrophobic |
2: claustrophobia <-> claustrophobic |
||
3: committeeman <-> committeemen |
3: committeeman <-> committeemen |
||
4: |
4: committeewoman <-> committeewomen |
||
5: complimentary <-> complementary |
5: complimentary <-> complementary |
||
6: confirmation <-> conformation |
6: confirmation <-> conformation |
||
7: |
7: congresswoman <-> congresswomen |
||
8: |
8: councilwoman <-> councilwomen |
||
9: draftsperson <-> craftsperson |
9: draftsperson <-> craftsperson |
||
10: eavesdropped <-> eavesdropper |
10: eavesdropped <-> eavesdropper |
||
Line 1,188: | Line 2,036: | ||
25: underclassman <-> underclassmen |
25: underclassman <-> underclassmen |
||
26: upperclassman <-> upperclassmen</pre> |
26: upperclassman <-> upperclassmen</pre> |
||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
This REXX version doesn't care what order the words in the dictionary are in, nor does it care what |
This REXX version doesn't care what order the words in the dictionary are in, nor does it care what |
||
Line 1,194: | Line 2,041: | ||
It also allows the minimum length to be specified on the command line (CL) as well as the dictionary file identifier. |
It also allows the minimum length to be specified on the command line (CL) as well as the dictionary file identifier. |
||
< |
<syntaxhighlight lang="rexx">/*REXX program finds changeable words (within an identified dict.), changing any letter.*/ |
||
parse arg minL iFID . /*obtain optional arguments from the CL*/ |
parse arg minL iFID . /*obtain optional arguments from the CL*/ |
||
if minL=='' | minL=="," then minL= 12 /*Not specified? Then use the default.*/ |
if minL=='' | minL=="," then minL= 12 /*Not specified? Then use the default.*/ |
||
Line 1,230: | Line 2,077: | ||
#= # - 1 /*adjust word count because of DO loop.*/ |
#= # - 1 /*adjust word count because of DO loop.*/ |
||
say copies('─', 30) # "words ("n 'usable words) in the dictionary file: ' iFID |
say copies('─', 30) # "words ("n 'usable words) in the dictionary file: ' iFID |
||
return</ |
return</syntaxhighlight> |
||
{{out|output|text= when using the default inputs:}} |
{{out|output|text= when using the default inputs:}} |
||
<pre> |
<pre> |
||
Line 1,240: | Line 2,087: | ||
committeeman committeemen |
committeeman committeemen |
||
committeemen committeeman |
committeemen committeeman |
||
committeewoman committeewomen |
|||
committeewomen committeewoman |
|||
complementary complimentary |
complementary complimentary |
||
complimentary complementary |
complimentary complementary |
||
confirmation conformation |
confirmation conformation |
||
conformation confirmation |
conformation confirmation |
||
congresswoman congresswomen |
|||
congresswomen congresswoman |
|||
councilwoman councilwomen |
|||
councilwomen councilwoman |
|||
craftsperson draftsperson |
craftsperson draftsperson |
||
draftsperson craftsperson |
draftsperson craftsperson |
||
Line 1,288: | Line 2,135: | ||
────────────────────────────── 52 changeable words found with a minimum length of 12 |
────────────────────────────── 52 changeable words found with a minimum length of 12 |
||
</pre> |
</pre> |
||
=={{header|Ring}}== |
=={{header|Ring}}== |
||
< |
<syntaxhighlight lang="ring"> |
||
cStr = read("unixdict.txt") |
cStr = read("unixdict.txt") |
||
wordList = str2list(cStr) |
wordList = str2list(cStr) |
||
Line 1,326: | Line 2,172: | ||
see "done..." + nl |
see "done..." + nl |
||
</syntaxhighlight> |
|||
</lang> |
|||
Output: |
Output: |
||
<pre> |
<pre> |
||
Line 1,337: | Line 2,183: | ||
5. committeeman >> committeemen |
5. committeeman >> committeemen |
||
6. committeemen >> committeeman |
6. committeemen >> committeeman |
||
7. committeewoman >> committeewomen |
|||
7. committeeperson >> committeepeople |
|||
8. committeewomen >> committeewoman |
|||
8. committeepeople >> committeeperson |
|||
9. complementary >> complimentary |
9. complementary >> complimentary |
||
10. complimentary >> complementary |
10. complimentary >> complementary |
||
11. confirmation >> conformation |
11. confirmation >> conformation |
||
12. conformation >> confirmation |
12. conformation >> confirmation |
||
13. |
13. congresswoman >> congresswomen |
||
14. |
14. congresswomen >> congresswoman |
||
15. |
15. councilwoman >> councilwomen |
||
16. |
16. councilwomen >> councilwoman |
||
17. craftsperson >> draftsperson |
17. craftsperson >> draftsperson |
||
18. draftsperson >> craftsperson |
18. draftsperson >> craftsperson |
||
Line 1,385: | Line 2,231: | ||
done... |
done... |
||
</pre> |
</pre> |
||
=={{header|Ruby}}== |
|||
<syntaxhighlight lang="ruby">words = File.open("unixdict.txt").readlines.map(&:chomp).select{|w| w.size > 11 } |
|||
size_groups = words.group_by(&:size).sort.map(&:last) |
|||
res = size_groups.flat_map do |group| |
|||
group.combination(2).select{|word1, word2| word1.chars.zip(word2.chars).one?{|c1, c2| c1 != c2} } |
|||
end |
|||
puts "Found #{res.size} changeable word pairs:" |
|||
res.each{|w1, w2|puts "#{w1} - #{w2}" } |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Found 26 changeable word pairs: |
|||
aristotelean - aristotelian |
|||
committeeman - committeemen |
|||
confirmation - conformation |
|||
councilwoman - councilwomen |
|||
craftsperson - draftsperson |
|||
eavesdropped - eavesdropper |
|||
frontiersman - frontiersmen |
|||
incommutable - incomputable |
|||
installation - instillation |
|||
kaleidescope - kaleidoscope |
|||
neuroanatomy - neuroanotomy |
|||
newspaperman - newspapermen |
|||
nonagenarian - nonogenarian |
|||
onomatopoeia - onomatopoeic |
|||
philanthrope - philanthropy |
|||
prescription - proscription |
|||
spectroscope - spectroscopy |
|||
complementary - complimentary |
|||
congresswoman - congresswomen |
|||
schizophrenia - schizophrenic |
|||
shakespearean - shakespearian |
|||
underclassman - underclassmen |
|||
upperclassman - upperclassmen |
|||
claustrophobia - claustrophobic |
|||
committeewoman - committeewomen |
|||
handicraftsman - handicraftsmen |
|||
</pre> |
|||
=={{header|Sidef}}== |
|||
{{trans|Perl}} |
|||
<syntaxhighlight lang="ruby">var file = File("unixdict.txt") |
|||
if (!file.exists) { |
|||
require('LWP::Simple') |
|||
say ":: Retrieving #{file} from internet..." |
|||
%S<LWP::Simple>.mirror( |
|||
'https://web.archive.org/web/20180611003215if_/' + |
|||
'http://www.puzzlers.org:80/pub/wordlists/unixdict.txt', |
|||
'unixdict.txt') |
|||
} |
|||
var words = file.read.words |
|||
var bucket = Hash() |
|||
var count = 0 |
|||
words.each {|word| |
|||
var len = word.len |
|||
len > 11 || next |
|||
bucket{len} := [] |
|||
bucket{len}.each{|prev| |
|||
if (prev ^ word -> count("\0") == len-1) { |
|||
printf("%2d: %20s <-> %s\n", ++count, prev, word) |
|||
} |
|||
} |
|||
bucket{len} << word |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
1: aristotelean <-> aristotelian |
|||
2: claustrophobia <-> claustrophobic |
|||
3: committeeman <-> committeemen |
|||
4: committeewoman <-> committeewomen |
|||
5: complementary <-> complimentary |
|||
6: confirmation <-> conformation |
|||
7: congresswoman <-> congresswomen |
|||
8: councilwoman <-> councilwomen |
|||
9: craftsperson <-> draftsperson |
|||
10: eavesdropped <-> eavesdropper |
|||
11: frontiersman <-> frontiersmen |
|||
12: handicraftsman <-> handicraftsmen |
|||
13: incommutable <-> incomputable |
|||
14: installation <-> instillation |
|||
15: kaleidescope <-> kaleidoscope |
|||
16: neuroanatomy <-> neuroanotomy |
|||
17: newspaperman <-> newspapermen |
|||
18: nonagenarian <-> nonogenarian |
|||
19: onomatopoeia <-> onomatopoeic |
|||
20: philanthrope <-> philanthropy |
|||
21: prescription <-> proscription |
|||
22: schizophrenia <-> schizophrenic |
|||
23: shakespearean <-> shakespearian |
|||
24: spectroscope <-> spectroscopy |
|||
25: underclassman <-> underclassmen |
|||
26: upperclassman <-> upperclassmen |
|||
</pre> |
|||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
{{libheader|Wren-fmt}} |
{{libheader|Wren-fmt}} |
||
Using the Hamming Distance between two equal length strings which needs to be 1 here: |
Using the Hamming Distance between two equal length strings which needs to be 1 here: |
||
< |
<syntaxhighlight lang="wren">import "io" for File |
||
import "/fmt" for Fmt |
import "./fmt" for Fmt |
||
var hammingDist = Fn.new { |s1, s2| |
var hammingDist = Fn.new { |s1, s2| |
||
Line 1,420: | Line 2,365: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,431: | Line 2,376: | ||
5: committeeman -> committeemen |
5: committeeman -> committeemen |
||
6: committeemen -> committeeman |
6: committeemen -> committeeman |
||
7: |
7: committeewoman -> committeewomen |
||
8: |
8: committeewomen -> committeewoman |
||
9: complementary -> complimentary |
9: complementary -> complimentary |
||
10: complimentary -> complementary |
10: complimentary -> complementary |
||
11: confirmation -> conformation |
11: confirmation -> conformation |
||
12: conformation -> confirmation |
12: conformation -> confirmation |
||
13: |
13: congresswoman -> congresswomen |
||
14: |
14: congresswomen -> congresswoman |
||
15: |
15: councilwoman -> councilwomen |
||
16: |
16: councilwomen -> councilwoman |
||
17: craftsperson -> draftsperson |
17: craftsperson -> draftsperson |
||
18: draftsperson -> craftsperson |
18: draftsperson -> craftsperson |
||
Line 1,480: | Line 2,425: | ||
=={{header|XPL0}}== |
=={{header|XPL0}}== |
||
< |
<syntaxhighlight lang="xpl0">string 0; \use zero-terminated strings |
||
int Dict(26000); \pointers to words (enough for unixdict.txt) |
int Dict(26000); \pointers to words (enough for unixdict.txt) |
||
int DictSize; \actual number of pointers in Dict |
int DictSize; \actual number of pointers in Dict |
||
Line 1,553: | Line 2,498: | ||
DI:= DI+1; |
DI:= DI+1; |
||
until DI >= DictSize; |
until DI >= DictSize; |
||
]</ |
]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 1,563: | Line 2,508: | ||
5 committeeman committeemen |
5 committeeman committeemen |
||
6 committeemen committeeman |
6 committeemen committeeman |
||
7 |
7 committeewoman committeewomen |
||
8 |
8 committeewomen committeewoman |
||
9 complementary complimentary |
9 complementary complimentary |
||
10 complimentary complementary |
10 complimentary complementary |
||
11 confirmation conformation |
11 confirmation conformation |
||
12 conformation confirmation |
12 conformation confirmation |
||
13 |
13 congresswoman congresswomen |
||
14 |
14 congresswomen congresswoman |
||
15 |
15 councilwoman councilwomen |
||
16 |
16 councilwomen councilwoman |
||
17 craftsperson draftsperson |
17 craftsperson draftsperson |
||
18 draftsperson craftsperson |
18 draftsperson craftsperson |
Latest revision as of 16:16, 3 April 2024
- Task
Using the dictionary unixdict.txt, change one letter in a word, and if the changed word occurs in the dictionary,
then display the original word and the changed word here (on this page).
The length of any word shown should have a length > 11.
- Note
- A copy of the specific unixdict.txt linked to should be used for consistency of results.
- Words > 11 are required, ie of 12 characters or more.
- Metrics
- Counting
- Word frequency
- Letter frequency
- Jewels and stones
- I before E except after C
- Bioinformatics/base count
- Count occurrences of a substring
- Count how many vowels and consonants occur in a string
- Remove/replace
- XXXX redacted
- Conjugate a Latin verb
- Remove vowels from a string
- String interpolation (included)
- Strip block comments
- Strip comments from a string
- Strip a set of characters from a string
- Strip whitespace from a string -- top and tail
- Strip control codes and extended characters from a string
- Anagrams/Derangements/shuffling
- Word wheel
- ABC problem
- Sattolo cycle
- Knuth shuffle
- Ordered words
- Superpermutation minimisation
- Textonyms (using a phone text pad)
- Anagrams
- Anagrams/Deranged anagrams
- Permutations/Derangements
- Find/Search/Determine
- ABC words
- Odd words
- Word ladder
- Semordnilap
- Word search
- Wordiff (game)
- String matching
- Tea cup rim text
- Alternade words
- Changeable words
- State name puzzle
- String comparison
- Unique characters
- Unique characters in each string
- Extract file extension
- Levenshtein distance
- Palindrome detection
- Common list elements
- Longest common suffix
- Longest common prefix
- Compare a list of strings
- Longest common substring
- Find common directory path
- Words from neighbour ones
- Change e letters to i in words
- Non-continuous subsequences
- Longest common subsequence
- Longest palindromic substrings
- Longest increasing subsequence
- Words containing "the" substring
- Sum of the digits of n is substring of n
- Determine if a string is numeric
- Determine if a string is collapsible
- Determine if a string is squeezable
- Determine if a string has all unique characters
- Determine if a string has all the same characters
- Longest substrings without repeating characters
- Find words which contains all the vowels
- Find words which contain the most consonants
- Find words which contains more than 3 vowels
- Find words whose first and last three letters are equal
- Find words with alternating vowels and consonants
- Formatting
- Substring
- Rep-string
- Word wrap
- String case
- Align columns
- Literals/String
- Repeat a string
- Brace expansion
- Brace expansion using ranges
- Reverse a string
- Phrase reversals
- Comma quibbling
- Special characters
- String concatenation
- Substring/Top and tail
- Commatizing numbers
- Reverse words in a string
- Suffixation of decimal numbers
- Long literals, with continuations
- Numerical and alphabetical suffixes
- Abbreviations, easy
- Abbreviations, simple
- Abbreviations, automatic
- Song lyrics/poems/Mad Libs/phrases
- Mad Libs
- Magic 8-ball
- 99 bottles of beer
- The Name Game (a song)
- The Old lady swallowed a fly
- The Twelve Days of Christmas
- Tokenize
- Text between
- Tokenize a string
- Word break problem
- Tokenize a string with escaping
- Split a character string based on change of character
- Sequences
- Reference
11l
V words = File(‘unixdict.txt’).read().split("\n").filter(word -> word.len > 11)
F hamming_dist(word1, word2)
I word1.len != word2.len
R 0
V count = 0
L(i) 0 .< word1.len
I word1[i] != word2[i]
count++
I count == 2
L.break // don't care about counts > 2
R count
print("List of changeable words:\n")
V count = 0
L(i) 0 .< words.len
V word1 = words[i]
L(j) i + 1 .< words.len
V word2 = words[j]
I hamming_dist(word1, word2) == 1
print(word1‘ <-> ’word2)
count += 2
print("\nFound "count‘ changeable words.’)
- Output:
List of changeable words: aristotelean <-> aristotelian claustrophobia <-> claustrophobic committeeman <-> committeemen committeewoman <-> committeewomen complementary <-> complimentary confirmation <-> conformation congresswoman <-> congresswomen councilwoman <-> councilwomen craftsperson <-> draftsperson eavesdropped <-> eavesdropper frontiersman <-> frontiersmen handicraftsman <-> handicraftsmen incommutable <-> incomputable installation <-> instillation kaleidescope <-> kaleidoscope neuroanatomy <-> neuroanotomy newspaperman <-> newspapermen nonagenarian <-> nonogenarian onomatopoeia <-> onomatopoeic philanthrope <-> philanthropy prescription <-> proscription schizophrenia <-> schizophrenic shakespearean <-> shakespearian spectroscope <-> spectroscopy underclassman <-> underclassmen upperclassman <-> upperclassmen Found 52 changeable words.
Ada
with Ada.Text_Io;
with Ada.Strings.Fixed;
with Ada.Containers.Indefinite_Vectors;
procedure Changeable is
use Ada.Text_Io, Ada.Strings.Fixed;
package String_Vectors is
new Ada.Containers.Indefinite_Vectors (Index_Type => Positive,
Element_Type => String);
Filename : constant String := "unixdict.txt";
File : File_Type;
Words : String_Vectors.Vector;
begin
Open (File, In_File, Filename);
while not End_Of_File (File) loop
declare
Word : constant String := Get_Line (File);
begin
if Word'Length > 11 then
Words.Append (Word);
end if;
end;
end loop;
Close (File);
for Word_Index_1 in Words.First_Index .. Words.Last_Index loop
for Word_Index_2 in Word_Index_1 + 1 .. Words.Last_Index loop
declare
Image : String (1 .. 14);
Word_1 : String renames Words (Word_Index_1);
Word_2 : String renames Words (Word_Index_2);
Match : Natural := 0;
begin
if Word_1'Length = Word_2'Length then
for Index in Word_1'Range loop
if Word_1 (Index) = Word_2 (Index) then
Match := Match + 1;
end if;
end loop;
if Match = Word_1'Length - 1 then
Move (Word_1, Image);
Put (Image); Put (" <-> ");
Move (Word_2, Image);
Put_Line (Image);
end if;
end if;
end;
end loop;
end loop;
end Changeable;
- Output:
aristotelean <-> aristotelian claustrophobia <-> claustrophobic committeeman <-> committeemen committeewoman <-> committeewomen complementary <-> complimentary confirmation <-> conformation congresswoman <-> congresswomen councilwoman <-> councilwomen craftsperson <-> draftsperson eavesdropped <-> eavesdropper frontiersman <-> frontiersmen handicraftsman <-> handicraftsmen incommutable <-> incomputable installation <-> instillation kaleidescope <-> kaleidoscope neuroanatomy <-> neuroanotomy newspaperman <-> newspapermen nonagenarian <-> nonogenarian onomatopoeia <-> onomatopoeic philanthrope <-> philanthropy prescription <-> proscription schizophrenia <-> schizophrenic shakespearean <-> shakespearian spectroscope <-> spectroscopy underclassman <-> underclassmen upperclassman <-> upperclassmen
ALGOL 68
Brute force - tries each possible changed word.
# find words where changing one letter results in another word #
# only words of 12 or more characters are to be considered #
IF FILE input file;
STRING file name = "unixdict.txt";
open( input file, file name, stand in channel ) /= 0
THEN
# failed to open the file #
print( ( "Unable to open """ + file name + """", newline ) )
ELSE
# file opened OK #
BOOL at eof := FALSE;
# set the EOF handler for the file - notes eof has been reached and #
# returns TRUE so processing can continue #
on logical file end( input file, ( REF FILE f )BOOL: at eof := TRUE );
# table of possible words - there are around 1000 12+ character words #
[ 1 : 2 000 ]STRING words; # in unixdict.txt #
# in-place quick sort an array of strings #
PROC s quicksort = ( REF[]STRING a, INT lb, ub )VOID:
IF ub > lb
THEN
# more than one element, so must sort #
INT left := lb;
INT right := ub;
# choosing the middle element of the array as the pivot #
STRING pivot := a[ left + ( ( right + 1 ) - left ) OVER 2 ];
WHILE
WHILE IF left <= ub THEN a[ left ] < pivot ELSE FALSE FI
DO
left +:= 1
OD;
WHILE IF right >= lb THEN a[ right ] > pivot ELSE FALSE FI
DO
right -:= 1
OD;
left <= right
DO
STRING t := a[ left ];
a[ left ] := a[ right ];
a[ right ] := t;
left +:= 1;
right -:= 1
OD;
s quicksort( a, lb, right );
s quicksort( a, left, ub )
FI # s quicksort # ;
# returns the length of s #
OP LENGTH = ( STRING s )INT: 1 + ( UPB s - LWB s );
# returns TRUE if words[ low : high ] contains s, FALSE otherwise #
PROC is word = ( STRING s, INT low, high )BOOL:
IF high < low THEN FALSE
ELSE INT mid = ( low + high ) OVER 2;
IF words[ mid ] > s THEN is word( s, low, mid - 1 )
ELIF words[ mid ] = s THEN TRUE
ELSE is word( s, mid + 1, high )
FI
FI # is word # ;
INT w count := 0; # store the 12 character words #
WHILE
STRING word;
get( input file, ( word, newline ) );
NOT at eof
DO
IF LENGTH word > 11 THEN
words[ w count +:= 1 ] := word
FI
OD;
close( input file );
s quicksort( words, 1, w count ); # sort the words #
FOR i TO w count DO # find the changeable words #
STRING word = words[ i ];
STRING c word := word;
FOR i FROM LWB word TO UPB word DO
FOR c FROM ABS word[ i ] + 1 TO ABS "z" DO
c word[ i ] := REPR c;
IF is word( c word, 1, w count ) THEN
FOR p FROM LENGTH word TO 15 DO print( ( " " ) ) OD;
print( ( word, " <-> ", c word, newline ) )
FI
OD;
c word[ i ] := word[ i ]
OD
OD
FI
- Output:
aristotelean <-> aristotelian claustrophobia <-> claustrophobic committeeman <-> committeemen committeewoman <-> committeewomen complementary <-> complimentary confirmation <-> conformation congresswoman <-> congresswomen councilwoman <-> councilwomen craftsperson <-> draftsperson eavesdropped <-> eavesdropper frontiersman <-> frontiersmen handicraftsman <-> handicraftsmen incommutable <-> incomputable installation <-> instillation kaleidescope <-> kaleidoscope neuroanatomy <-> neuroanotomy newspaperman <-> newspapermen nonagenarian <-> nonogenarian onomatopoeia <-> onomatopoeic philanthrope <-> philanthropy prescription <-> proscription schizophrenia <-> schizophrenic shakespearean <-> shakespearian spectroscope <-> spectroscopy underclassman <-> underclassmen upperclassman <-> upperclassmen
Arturo
wordset: map read.lines relative "unixdict.txt" => strip
wordset: select wordset 'word -> 12 =< size word
results: new []
loop wordset 'a [
loop select wordset 'word [equal? size a size word] 'b [
if a <> b [
if 1 = levenshtein a b [
'results ++ @[sort @[a b]]
]
]
]
]
loop unique results 'result ->
print join.with:" - " result
- Output:
aristotelean - aristotelian claustrophobia - claustrophobic committeeman - committeemen committeewoman - committeewomen complementary - complimentary confirmation - conformation congresswoman - congresswomen councilwoman - councilwomen craftsperson - draftsperson eavesdropped - eavesdropper frontiersman - frontiersmen handicraftsman - handicraftsmen incommutable - incomputable installation - instillation kaleidescope - kaleidoscope neuroanatomy - neuroanotomy newspaperman - newspapermen nonagenarian - nonogenarian onomatopoeia - onomatopoeic philanthrope - philanthropy prescription - proscription schizophrenia - schizophrenic shakespearean - shakespearian spectroscope - spectroscopy underclassman - underclassmen upperclassman - upperclassmen
AutoHotkey
FileRead, db, % A_Desktop "\unixdict.txt"
oWord := [], Found := []
for i, word in StrSplit(db, "`n", "`r")
if (StrLen(word) > 11)
oWord[word] := true
for word1 in oWord
for word2 in oWord
if Changeable(word1, word2) && !Found[word2]
found[word1] := true, result .= word1 . "`t<-> " word2 "`n"
MsgBox, 262144, , % result
return
Changeable(s1, s2) {
if (StrLen(s1) <> StrLen(s2))
return 0
for i, v in StrSplit(s1)
if (v = SubStr(s2, i, 1))
num++
return (StrLen(s1) - num = 1)
}
- Output:
aristotelean <-> aristotelian claustrophobia <-> claustrophobic committeeman <-> committeemen committeewoman <-> committeewomen complementary <-> complimentary confirmation <-> conformation congresswoman <-> congresswomen councilwoman <-> councilwomen craftsperson <-> draftsperson eavesdropped <-> eavesdropper frontiersman <-> frontiersmen handicraftsman <-> handicraftsmen incommutable <-> incomputable installation <-> instillation kaleidescope <-> kaleidoscope neuroanatomy <-> neuroanotomy newspaperman <-> newspapermen nonagenarian <-> nonogenarian onomatopoeia <-> onomatopoeic philanthrope <-> philanthropy prescription <-> proscription schizophrenia <-> schizophrenic shakespearean <-> shakespearian spectroscope <-> spectroscopy underclassman <-> underclassmen upperclassman <-> upperclassmen
AWK
# syntax: GAWK -f CHANGEABLE_WORDS.AWK unixdict.txt
#
# sorting:
# PROCINFO["sorted_in"] is used by GAWK
# SORTTYPE is used by Thompson Automation's TAWK
#
{ arr[$0]++ }
END {
a2z = "abcdefghijklmnopqrstuvwxyz"
a2z_leng = length(a2z)
PROCINFO["sorted_in"] = "@ind_str_asc" ; SORTTYPE = 1
for (word in arr) {
leng = length(word)
if (leng < 12) {
continue
}
printed = 0
for (i=1; i<=leng; i++) {
if (printed == 1) {
break
}
if (i == 1) {
L = ""
R = substr(word,2)
}
else if (i == leng) {
L = substr(word,1,leng-1)
R = ""
}
else {
L = substr(word,1,i)
R = substr(word,i+2)
}
for (j=1; j<a2z_leng; j++) {
new_word = L substr(a2z,j,1) R
if (new_word in arr && word != new_word) {
printf("%-15s %s\n",word,new_word)
printed = 1
count++
}
}
}
}
printf("%d words\n",count)
exit(0)
}
- Output:
aristotelean aristotelian aristotelian aristotelean claustrophobia claustrophobic claustrophobic claustrophobia committeeman committeemen committeemen committeeman committeewoman committeewomen committeewomen committeewoman complementary complimentary complimentary complementary confirmation conformation conformation confirmation congresswoman congresswomen congresswomen congresswoman councilwoman councilwomen councilwomen councilwoman craftsperson draftsperson draftsperson craftsperson eavesdropped eavesdropper eavesdropper eavesdropped frontiersman frontiersmen frontiersmen frontiersman handicraftsman handicraftsmen handicraftsmen handicraftsman incommutable incomputable incomputable incommutable installation instillation instillation installation kaleidescope kaleidoscope kaleidoscope kaleidescope neuroanatomy neuroanotomy neuroanotomy neuroanatomy newspaperman newspapermen newspapermen newspaperman nonagenarian nonogenarian nonogenarian nonagenarian onomatopoeia onomatopoeic onomatopoeic onomatopoeia philanthrope philanthropy philanthropy philanthrope prescription proscription proscription prescription schizophrenia schizophrenic schizophrenic schizophrenia shakespearean shakespearian shakespearian shakespearean spectroscope spectroscopy spectroscopy spectroscope underclassman underclassmen underclassmen underclassman upperclassman upperclassmen upperclassmen upperclassman
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORD_SIZE 32
typedef struct string_tag {
size_t length;
char str[MAX_WORD_SIZE];
} string_t;
void fatal(const char* message) {
fprintf(stderr, "%s\n", message);
exit(1);
}
void* xmalloc(size_t n) {
void* ptr = malloc(n);
if (ptr == NULL)
fatal("Out of memory");
return ptr;
}
void* xrealloc(void* p, size_t n) {
void* ptr = realloc(p, n);
if (ptr == NULL)
fatal("Out of memory");
return ptr;
}
int hamming_distance(const string_t* str1, const string_t* str2) {
size_t len1 = str1->length;
size_t len2 = str2->length;
if (len1 != len2)
return 0;
int count = 0;
const char* s1 = str1->str;
const char* s2 = str2->str;
for (size_t i = 0; i < len1; ++i) {
if (s1[i] != s2[i])
++count;
// don't care about counts > 2 in this case
if (count == 2)
break;
}
return count;
}
int main(int argc, char** argv) {
const char* filename = argc < 2 ? "unixdict.txt" : argv[1];
FILE* in = fopen(filename, "r");
if (!in) {
perror(filename);
return EXIT_FAILURE;
}
char line[MAX_WORD_SIZE];
size_t size = 0, capacity = 1024;
string_t* dictionary = xmalloc(sizeof(string_t) * capacity);
while (fgets(line, sizeof(line), in)) {
if (size == capacity) {
capacity *= 2;
dictionary = xrealloc(dictionary, sizeof(string_t) * capacity);
}
size_t len = strlen(line) - 1;
if (len > 11) {
string_t* str = &dictionary[size];
str->length = len;
memcpy(str->str, line, len);
str->str[len] = '\0';
++size;
}
}
fclose(in);
printf("Changeable words in %s:\n", filename);
int n = 1;
for (size_t i = 0; i < size; ++i) {
const string_t* str1 = &dictionary[i];
for (size_t j = 0; j < size; ++j) {
const string_t* str2 = &dictionary[j];
if (i != j && hamming_distance(str1, str2) == 1)
printf("%2d: %-14s -> %s\n", n++, str1->str, str2->str);
}
}
free(dictionary);
return EXIT_SUCCESS;
}
- Output:
Changeable words in unixdict.txt: 1: aristotelean -> aristotelian 2: aristotelian -> aristotelean 3: claustrophobia -> claustrophobic 4: claustrophobic -> claustrophobia 5: committeeman -> committeemen 6: committeemen -> committeeman 7: committeewoman -> committeewomen 8: committeewomen -> committeewoman 9: complementary -> complimentary 10: complimentary -> complementary 11: confirmation -> conformation 12: conformation -> confirmation 13: congresswoman -> congresswomen 14: congresswomen -> congresswoman 15: councilwoman -> councilwomen 16: councilwomen -> councilwoman 17: craftsperson -> draftsperson 18: draftsperson -> craftsperson 19: eavesdropped -> eavesdropper 20: eavesdropper -> eavesdropped 21: frontiersman -> frontiersmen 22: frontiersmen -> frontiersman 23: handicraftsman -> handicraftsmen 24: handicraftsmen -> handicraftsman 25: incommutable -> incomputable 26: incomputable -> incommutable 27: installation -> instillation 28: instillation -> installation 29: kaleidescope -> kaleidoscope 30: kaleidoscope -> kaleidescope 31: neuroanatomy -> neuroanotomy 32: neuroanotomy -> neuroanatomy 33: newspaperman -> newspapermen 34: newspapermen -> newspaperman 35: nonagenarian -> nonogenarian 36: nonogenarian -> nonagenarian 37: onomatopoeia -> onomatopoeic 38: onomatopoeic -> onomatopoeia 39: philanthrope -> philanthropy 40: philanthropy -> philanthrope 41: prescription -> proscription 42: proscription -> prescription 43: schizophrenia -> schizophrenic 44: schizophrenic -> schizophrenia 45: shakespearean -> shakespearian 46: shakespearian -> shakespearean 47: spectroscope -> spectroscopy 48: spectroscopy -> spectroscope 49: underclassman -> underclassmen 50: underclassmen -> underclassman 51: upperclassman -> upperclassmen 52: upperclassmen -> upperclassman
C++
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
int hamming_distance(const std::string& str1, const std::string& str2) {
size_t len1 = str1.size();
size_t len2 = str2.size();
if (len1 != len2)
return 0;
int count = 0;
for (size_t i = 0; i < len1; ++i) {
if (str1[i] != str2[i])
++count;
// don't care about counts > 2 in this case
if (count == 2)
break;
}
return count;
}
int main(int argc, char** argv) {
const char* filename(argc < 2 ? "unixdict.txt" : argv[1]);
std::ifstream in(filename);
if (!in) {
std::cerr << "Cannot open file '" << filename << "'.\n";
return EXIT_FAILURE;
}
std::string line;
std::vector<std::string> dictionary;
while (getline(in, line)) {
if (line.size() > 11)
dictionary.push_back(line);
}
std::cout << "Changeable words in " << filename << ":\n";
int n = 1;
for (const std::string& word1 : dictionary) {
for (const std::string& word2 : dictionary) {
if (hamming_distance(word1, word2) == 1)
std::cout << std::setw(2) << std::right << n++
<< ": " << std::setw(14) << std::left << word1
<< " -> " << word2 << '\n';
}
}
return EXIT_SUCCESS;
}
- Output:
Changeable words in unixdict.txt: 1: aristotelean -> aristotelian 2: aristotelian -> aristotelean 3: claustrophobia -> claustrophobic 4: claustrophobic -> claustrophobia 5: committeeman -> committeemen 6: committeemen -> committeeman 7: committeewoman -> committeewomen 8: committeewomen -> committeewoman 9: complementary -> complimentary 10: complimentary -> complementary 11: confirmation -> conformation 12: conformation -> confirmation 13: congresswoman -> congresswomen 14: congresswomen -> congresswoman 15: councilwoman -> councilwomen 16: councilwomen -> councilwoman 17: craftsperson -> draftsperson 18: draftsperson -> craftsperson 19: eavesdropped -> eavesdropper 20: eavesdropper -> eavesdropped 21: frontiersman -> frontiersmen 22: frontiersmen -> frontiersman 23: handicraftsman -> handicraftsmen 24: handicraftsmen -> handicraftsman 25: incommutable -> incomputable 26: incomputable -> incommutable 27: installation -> instillation 28: instillation -> installation 29: kaleidescope -> kaleidoscope 30: kaleidoscope -> kaleidescope 31: neuroanatomy -> neuroanotomy 32: neuroanotomy -> neuroanatomy 33: newspaperman -> newspapermen 34: newspapermen -> newspaperman 35: nonagenarian -> nonogenarian 36: nonogenarian -> nonagenarian 37: onomatopoeia -> onomatopoeic 38: onomatopoeic -> onomatopoeia 39: philanthrope -> philanthropy 40: philanthropy -> philanthrope 41: prescription -> proscription 42: proscription -> prescription 43: schizophrenia -> schizophrenic 44: schizophrenic -> schizophrenia 45: shakespearean -> shakespearian 46: shakespearian -> shakespearean 47: spectroscope -> spectroscopy 48: spectroscopy -> spectroscope 49: underclassman -> underclassmen 50: underclassmen -> underclassman 51: upperclassman -> upperclassmen 52: upperclassmen -> upperclassman
Delphi
var Dict: TStringList; {List holds dictionary}
procedure DoChangeWords(Memo: TMemo);
{Do change word problem}
var I,J,K,Inx,Cnt: integer;
var S: string;
procedure Display(OldStr,NewStr: string);
{Display both the original word and the modified word}
begin
Inc(Cnt);
Memo.Lines.Add(IntToStr(Cnt)+': '+OldStr+' '+NewStr);
end;
begin
Cnt:=0;
{Check every word in the dictionary}
for I:=0 to Dict.Count-1 do
begin
{Only check words at least 12 chars long}
if Length(Dict[I])>=12 then
begin
{Test a specific position in the word}
for J:=1 to Length(Dict[I]) do
begin
{try all combinations of alpha chars in the position}
for K:=byte('a') to byte('z') do
begin
{skip if the char is already in the position}
if Dict[I][J]=char(K) then continue;
{Get a new copy of the word to modify}
S:=Dict[I];
{Modify the position}
S[J]:=char(K);
{Is it in the dictionary? }
Inx:=Dict.IndexOf(S);
{Display it if it is}
if Inx>=0 then Display(Dict[I],S);
end;
end;
end;
end;
end;
initialization
{Create/load dictionary}
Dict:=TStringList.Create;
Dict.LoadFromFile('unixdict.txt');
Dict.Sorted:=True;
finalization
Dict.Free;
end.
- Output:
1: aristotelean aristotelian 2: aristotelian aristotelean 3: claustrophobia claustrophobic 4: claustrophobic claustrophobia 5: committeeman committeemen 6: committeemen committeeman 7: committeewoman committeewomen 8: committeewomen committeewoman 9: complementary complimentary 10: complimentary complementary 11: confirmation conformation 12: conformation confirmation 13: congresswoman congresswomen 14: congresswomen congresswoman 15: councilwoman councilwomen 16: councilwomen councilwoman 17: craftsperson draftsperson 18: draftsperson craftsperson 19: eavesdropped eavesdropper 20: eavesdropper eavesdropped 21: frontiersman frontiersmen 22: frontiersmen frontiersman 23: handicraftsman handicraftsmen 24: handicraftsmen handicraftsman 25: incommutable incomputable 26: incomputable incommutable 27: installation instillation 28: instillation installation 29: kaleidescope kaleidoscope 30: kaleidoscope kaleidescope 31: neuroanatomy neuroanotomy 32: neuroanotomy neuroanatomy 33: newspaperman newspapermen 34: newspapermen newspaperman 35: nonagenarian nonogenarian 36: nonogenarian nonagenarian 37: onomatopoeia onomatopoeic 38: onomatopoeic onomatopoeia 39: philanthrope philanthropy 40: philanthropy philanthrope 41: prescription proscription 42: proscription prescription 43: schizophrenia schizophrenic 44: schizophrenic schizophrenia 45: shakespearean shakespearian 46: shakespearian shakespearean 47: spectroscope spectroscopy 48: spectroscopy spectroscope 49: underclassman underclassmen 50: underclassmen underclassman 51: upperclassman upperclassmen 52: upperclassmen upperclassman
F#
// Changeable words: Nigel Galloway. June 14th., 2021
let fN g=Seq.fold2(fun z n g->z+if n=g then 0 else 1) 0 g
let rec fG n g=match g with h::t->fG(n@(t|>List.choose(fun g->match fN g h with 1->Some(h,g)|_->None))) t|_->n
seq{use n=System.IO.File.OpenText("unixdict.txt") in while not n.EndOfStream do yield n.ReadLine()}|>Seq.filter(fun n->n.Length>11)
|>List.ofSeq|>List.groupBy(fun n->n.Length)|>Seq.collect(fun(_,n)->fG [] n)|>Seq.iter(fun(n,g)->printfn "%s <=> %s" n g)
- Output:
claustrophobia <=> claustrophobic committeewoman <=> committeewomen handicraftsman <=> handicraftsmen aristotelean <=> aristotelian committeeman <=> committeemen confirmation <=> conformation councilwoman <=> councilwomen craftsperson <=> draftsperson eavesdropped <=> eavesdropper frontiersman <=> frontiersmen incommutable <=> incomputable installation <=> instillation kaleidescope <=> kaleidoscope neuroanatomy <=> neuroanotomy newspaperman <=> newspapermen nonagenarian <=> nonogenarian onomatopoeia <=> onomatopoeic philanthrope <=> philanthropy prescription <=> proscription spectroscope <=> spectroscopy complementary <=> complimentary congresswoman <=> congresswomen schizophrenia <=> schizophrenic shakespearean <=> shakespearian underclassman <=> underclassmen upperclassman <=> upperclassmen
Factor
USING: assocs combinators.short-circuit formatting
io.encodings.ascii io.files kernel math math.combinatorics
math.distances sequences ;
: changeable? ( str str -- ? )
{ [ [ length ] bi@ = ] [ hamming-distance 1 = ] } 2&& ;
"unixdict.txt" ascii file-lines
[ length 11 > ] filter
2 [ first2 changeable? ] filter-combinations
[ "%s <-> %s\n" printf ] assoc-each
- Output:
aristotelean <-> aristotelian claustrophobia <-> claustrophobic committeeman <-> committeemen committeewoman <-> committeewomen complementary <-> complimentary confirmation <-> conformation congresswoman <-> congresswomen councilwoman <-> councilwomen craftsperson <-> draftsperson eavesdropped <-> eavesdropper frontiersman <-> frontiersmen handicraftsman <-> handicraftsmen incommutable <-> incomputable installation <-> instillation kaleidescope <-> kaleidoscope neuroanatomy <-> neuroanotomy newspaperman <-> newspapermen nonagenarian <-> nonogenarian onomatopoeia <-> onomatopoeic philanthrope <-> philanthropy prescription <-> proscription schizophrenia <-> schizophrenic shakespearean <-> shakespearian spectroscope <-> spectroscopy underclassman <-> underclassmen upperclassman <-> upperclassmen
FreeBASIC
Brute force method, reuses some code from Odd_words#FreeBASIC.
#define NULL 0
type node
word as string*32 'enough space to store any word in the dictionary
nxt as node ptr
end type
function addword( tail as node ptr, word as string ) as node ptr
'allocates memory for a new node, links the previous tail to it,
'and returns the address of the new node
dim as node ptr newnode = allocate(sizeof(node))
tail->nxt = newnode
newnode->nxt = NULL
newnode->word = word
return newnode
end function
function length( word as string ) as uinteger
'necessary replacement for the built-in len function, which in this
'case would always return 32
for i as uinteger = 1 to 32
if asc(mid(word,i,1)) = 0 then return i-1
next i
return 999
end function
dim as string word
dim as node ptr tail = allocate( sizeof(node) )
dim as node ptr head = tail, curr = head, currj
tail->nxt = NULL
tail->word = "XXXXHEADER"
open "unixdict.txt" for input as #1
while true
line input #1, word
if word = "" then exit while
if length(word)>11 then tail = addword( tail, word )
wend
close #1
dim as string tempword
while curr->nxt <> NULL
for i as uinteger = 1 to length(curr->word)
for j as uinteger = 97 to 122
if j = asc(mid(curr->word,i,1)) then continue for
tempword = left(curr->word,i-1)+ chr(j) + mid(curr->word, i+1, length(curr->word)-i)
currj = head
while currj->nxt <> NULL
if tempword = currj->word then print left(curr->word,length(curr->word));" ---> ";tempword
currj = currj->nxt
wend
next j
next i
curr = curr->nxt
wend
- Output:
aristotelean ---> aristotelian aristotelian ---> aristotelean claustrophobia ---> claustrophobic claustrophobic ---> claustrophobia committeeman ---> committeemen committeemen ---> committeeman committeewoman ---> committeewomen committeewomen ---> committeewoman complementary ---> complimentary complimentary ---> complementary confirmation ---> conformation conformation ---> confirmation congresswoman ---> congresswomen congresswomen ---> congresswoman councilwoman ---> councilwomen councilwomen ---> councilwoman craftsperson ---> draftsperson draftsperson ---> craftsperson eavesdropped ---> eavesdropper eavesdropper ---> eavesdropped frontiersman ---> frontiersmen frontiersmen ---> frontiersman handicraftsman ---> handicraftsmen handicraftsmen ---> handicraftsman incommutable ---> incomputable incomputable ---> incommutable installation ---> instillation instillation ---> installation kaleidescope ---> kaleidoscope kaleidoscope ---> kaleidescope neuroanatomy ---> neuroanotomy neuroanotomy ---> neuroanatomy newspaperman ---> newspapermen newspapermen ---> newspaperman nonagenarian ---> nonogenarian nonogenarian ---> nonagenarian onomatopoeia ---> onomatopoeic onomatopoeic ---> onomatopoeia philanthrope ---> philanthropy philanthropy ---> philanthrope prescription ---> proscription proscription ---> prescription schizophrenia ---> schizophrenic schizophrenic ---> schizophrenia shakespearean ---> shakespearian shakespearian ---> shakespearean spectroscope ---> spectroscopy spectroscopy ---> spectroscope underclassman ---> underclassmen underclassmen ---> underclassman upperclassman ---> upperclassmen upperclassmen ---> upperclassman
FutureBasic
#plist NSAppTransportSecurity @{NSAllowsArbitraryLoads:YES}
include "NSLog.incl"
local fn Words as CFArrayRef
CFURLRef url = fn URLWithString( @"http://wiki.puzzlers.org/pub/wordlists/unixdict.txt" )
CFStringRef string = fn StringWithContentsOfURL( url, NSUTF8StringEncoding, NULL )
CFArrayRef array = fn StringComponentsSeparatedByCharactersInSet( string, fn CharacterSetNewlineSet )
CFMutableArrayRef words = fn MutableArrayWithCapacity(0)
for string in array
if ( len(string) > 11 )
MutableArrayAddObject( words, string )
end if
next
end fn = words
void local fn DoIt
dispatchglobal
CFArrayRef words = fn Words
CFStringRef wd1, wd2
long length, i, j
unichar chr
for wd1 in words
length = len(wd1)
for i = 0 to length - 1
chr = fn StringCharacterAtIndex( wd1, i )
for j = 97 to 122
if ( j == chr ) then continue
wd2 = fn StringWithFormat( @"%@%c%@", left(wd1,i), j, right(wd1,length-i-1) )
if ( fn ArrayContainsObject( words, wd2 ) )
NSLog(@"%@\t%@",wd1,wd2)
end if
next
next
next
dispatchend
end fn
fn DoIt
HandleEvents
- Output:
aristotelean aristotelian aristotelian aristotelean claustrophobia claustrophobic claustrophobic claustrophobia committeeman committeemen committeemen committeeman committeewoman committeewomen committeewomen committeewoman complementary complimentary complimentary complementary confirmation conformation conformation confirmation congresswoman congresswomen congresswomen congresswoman councilwoman councilwomen councilwomen councilwoman craftsperson draftsperson draftsperson craftsperson eavesdropped eavesdropper eavesdropper eavesdropped frontiersman frontiersmen frontiersmen frontiersman handicraftsman handicraftsmen handicraftsmen handicraftsman incommutable incomputable incomputable incommutable installation instillation instillation installation kaleidescope kaleidoscope kaleidoscope kaleidescope neuroanatomy neuroanotomy neuroanotomy neuroanatomy newspaperman newspapermen newspapermen newspaperman nonagenarian nonogenarian nonogenarian nonagenarian onomatopoeia onomatopoeic onomatopoeic onomatopoeia philanthrope philanthropy philanthropy philanthrope prescription proscription proscription prescription schizophrenia schizophrenic schizophrenic schizophrenia shakespearean shakespearian shakespearian shakespearean spectroscope spectroscopy spectroscopy spectroscope underclassman underclassmen underclassmen underclassman upperclassman upperclassmen upperclassmen upperclassman
Go
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"unicode/utf8"
)
func hammingDist(s1, s2 string) int {
r1 := []rune(s1) // in case there are non-ASCII characters
r2 := []rune(s2) // ditto
if len(r1) != len(r2) {
return 0
}
count := 0
for i := 0; i < len(r1); i++ {
if r1[i] != r2[i] {
count++
if count == 2 {
break // don't care about counts > 2
}
}
}
return count
}
func main() {
wordList := "unixdict.txt"
b, err := ioutil.ReadFile(wordList)
if err != nil {
log.Fatal("Error reading file")
}
bwords := bytes.Fields(b)
var words []string
for _, bword := range bwords {
s := string(bword)
if utf8.RuneCountInString(s) > 11 {
words = append(words, s)
}
}
count := 0
fmt.Println("Changeable words in", wordList, "\b:")
for _, word1 := range words {
for _, word2 := range words {
if word1 != word2 && hammingDist(word1, word2) == 1 {
count++
fmt.Printf("%2d: %-14s -> %s\n", count, word1, word2)
}
}
}
}
- Output:
Changeable words in unixdict.txt: 1: aristotelean -> aristotelian 2: aristotelian -> aristotelean 3: claustrophobia -> claustrophobic 4: claustrophobic -> claustrophobia 5: committeeman -> committeemen 6: committeemen -> committeeman 7: committeewoman -> committeewomen 8: committeewomen -> committeewoman 9: complementary -> complimentary 10: complimentary -> complementary 11: confirmation -> conformation 12: conformation -> confirmation 13: congresswoman -> congresswomen 14: congresswomen -> congresswoman 15: councilwoman -> councilwomen 16: councilwomen -> councilwoman 17: craftsperson -> draftsperson 18: draftsperson -> craftsperson 19: eavesdropped -> eavesdropper 20: eavesdropper -> eavesdropped 21: frontiersman -> frontiersmen 22: frontiersmen -> frontiersman 23: handicraftsman -> handicraftsmen 24: handicraftsmen -> handicraftsman 25: incommutable -> incomputable 26: incomputable -> incommutable 27: installation -> instillation 28: instillation -> installation 29: kaleidescope -> kaleidoscope 30: kaleidoscope -> kaleidescope 31: neuroanatomy -> neuroanotomy 32: neuroanotomy -> neuroanatomy 33: newspaperman -> newspapermen 34: newspapermen -> newspaperman 35: nonagenarian -> nonogenarian 36: nonogenarian -> nonagenarian 37: onomatopoeia -> onomatopoeic 38: onomatopoeic -> onomatopoeia 39: philanthrope -> philanthropy 40: philanthropy -> philanthrope 41: prescription -> proscription 42: proscription -> prescription 43: schizophrenia -> schizophrenic 44: schizophrenic -> schizophrenia 45: shakespearean -> shakespearian 46: shakespearian -> shakespearean 47: spectroscope -> spectroscopy 48: spectroscopy -> spectroscope 49: underclassman -> underclassmen 50: underclassmen -> underclassman 51: upperclassman -> upperclassmen 52: upperclassmen -> upperclassman
J
;:inv ({~ ~.@($ /:~"1@#: I.@,)@(1=+/ .~: ::0:&>/~))(#~ 11<#@>) cutLF fread'unixdict.txt'
aristotelean aristotelian
claustrophobia claustrophobic
committeeman committeemen
committeewoman committeewomen
complementary complimentary
confirmation conformation
congresswoman congresswomen
councilwoman councilwomen
craftsperson draftsperson
eavesdropped eavesdropper
frontiersman frontiersmen
handicraftsman handicraftsmen
incommutable incomputable
installation instillation
kaleidescope kaleidoscope
neuroanatomy neuroanotomy
newspaperman newspapermen
nonagenarian nonogenarian
onomatopoeia onomatopoeic
philanthrope philanthropy
prescription proscription
schizophrenia schizophrenic
shakespearean shakespearian
spectroscope spectroscopy
underclassman underclassmen
upperclassman upperclassmen
Java
import java.io.*;
import java.util.*;
public class ChangeableWords {
public static void main(String[] args) {
try {
final String fileName = "unixdict.txt";
List<String> dictionary = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.length() > 11)
dictionary.add(line);
}
}
System.out.printf("Changeable words in %s:\n", fileName);
int n = 1;
for (String word1 : dictionary) {
for (String word2 : dictionary) {
if (word1 != word2 && hammingDistance(word1, word2) == 1)
System.out.printf("%2d: %-14s -> %s\n", n++, word1, word2);
}
}
} catch (Exception e) {
e.printStackTtexture();
}
}
private static int hammingDistance(String str1, String str2) {
int len1 = str1.length();
int len2 = str2.length();
if (len1 != len2)
return 0;
int count = 0;
for (int i = 0; i < len1; ++i) {
if (str1.charAt(i) != str2.charAt(i))
++count;
// don't care about counts > 2 in this case
if (count == 2)
break;
}
return count;
}
}
- Output:
Changeable words in unixdict.txt: 1: aristotelean -> aristotelian 2: aristotelian -> aristotelean 3: claustrophobia -> claustrophobic 4: claustrophobic -> claustrophobia 5: committeeman -> committeemen 6: committeemen -> committeeman 7: committeewoman -> committeewomen 8: committeewomen -> committeewoman 9: complementary -> complimentary 10: complimentary -> complementary 11: confirmation -> conformation 12: conformation -> confirmation 13: congresswoman -> congresswomen 14: congresswomen -> congresswoman 15: councilwoman -> councilwomen 16: councilwomen -> councilwoman 17: craftsperson -> draftsperson 18: draftsperson -> craftsperson 19: eavesdropped -> eavesdropper 20: eavesdropper -> eavesdropped 21: frontiersman -> frontiersmen 22: frontiersmen -> frontiersman 23: handicraftsman -> handicraftsmen 24: handicraftsmen -> handicraftsman 25: incommutable -> incomputable 26: incomputable -> incommutable 27: installation -> instillation 28: instillation -> installation 29: kaleidescope -> kaleidoscope 30: kaleidoscope -> kaleidescope 31: neuroanatomy -> neuroanotomy 32: neuroanotomy -> neuroanatomy 33: newspaperman -> newspapermen 34: newspapermen -> newspaperman 35: nonagenarian -> nonogenarian 36: nonogenarian -> nonagenarian 37: onomatopoeia -> onomatopoeic 38: onomatopoeic -> onomatopoeia 39: philanthrope -> philanthropy 40: philanthropy -> philanthrope 41: prescription -> proscription 42: proscription -> prescription 43: schizophrenia -> schizophrenic 44: schizophrenic -> schizophrenia 45: shakespearean -> shakespearian 46: shakespearian -> shakespearean 47: spectroscope -> spectroscopy 48: spectroscopy -> spectroscope 49: underclassman -> underclassmen 50: underclassmen -> underclassman 51: upperclassman -> upperclassmen 52: upperclassmen -> upperclassman
jq
Works with gojq, the Go implementation of jq
# Emit a stream of words "greater than" the input word that differ by just one character.
def changeable_to($dict):
. as $w
| range(0;length) as $i
| (.[$i:$i+1]|explode[]) as $j
| [range($j+1;123) | [.] | implode] as $alphas # 122 is "z"
| .[:$i] + $alphas[] + .[$i+1:]
| select($dict[.]);
INDEX( inputs; . )
| . as $dict
| keys_unsorted[] # or keys[] for gojq
| select(length>11)
| . as $w
| [changeable_to($dict)] | unique[]
| "\($w) <=> \(.)"
Invocation: jq -n -rR -f changeable-words.jq unixdict.txt
- Output:
aristotelean <=> aristotelian claustrophobia <=> claustrophobic committeeman <=> committeemen committeewoman <=> committeewomen complementary <=> complimentary confirmation <=> conformation congresswoman <=> congresswomen councilwoman <=> councilwomen craftsperson <=> draftsperson eavesdropped <=> eavesdropper frontiersman <=> frontiersmen handicraftsman <=> handicraftsmen incommutable <=> incomputable installation <=> instillation kaleidescope <=> kaleidoscope neuroanatomy <=> neuroanotomy newspaperman <=> newspapermen nonagenarian <=> nonogenarian onomatopoeia <=> onomatopoeic philanthrope <=> philanthropy prescription <=> proscription schizophrenia <=> schizophrenic shakespearean <=> shakespearian spectroscope <=> spectroscopy underclassman <=> underclassmen upperclassman <=> upperclassmen
Julia
See Alternade_words#Julia for the foreachword function.
const alts = Set{String}()
function ischangeable(w, d)
alternatives = [w[1:p[1]-1] * p[2] * w[p[1]+1:end] for p in Iterators.product(1:length(w), 'a':'z')]
for a in alternatives
if a != w && haskey(d, a)
result = join(sort([w, a]), " <=> ")
if !(result in alts)
push!(alts, result)
return result
end
end
end
return ""
end
foreachword("unixdict.txt", ischangeable, minlen = 12, colwidth=40, numcols=2)
- Output:
Word source: unixdict.txt aristotelean <=> aristotelian claustrophobia <=> claustrophobic committeeman <=> committeemen committeewoman <=> committeewomen complementary <=> complimentary confirmation <=> conformation congresswoman <=> congresswomen councilwoman <=> councilwomen craftsperson <=> draftsperson eavesdropped <=> eavesdropper frontiersman <=> frontiersmen handicraftsman <=> handicraftsmen incommutable <=> incomputable installation <=> instillation kaleidescope <=> kaleidoscope neuroanatomy <=> neuroanotomy newspaperman <=> newspapermen nonagenarian <=> nonogenarian onomatopoeia <=> onomatopoeic philanthrope <=> philanthropy prescription <=> proscription schizophrenia <=> schizophrenic shakespearean <=> shakespearian spectroscope <=> spectroscopy underclassman <=> underclassmen upperclassman <=> upperclassmen
Nim
Using the standard module std/editdistance
to get the distance between two words.
import std/editdistance, sugar
# Build list of words with length >= 12.
let words = collect(newSeq):
for word in "unixdict.txt".lines:
if word.len >= 12:
word
echo "List of changeable words:\n"
var count = 0
for i in 0..<words.high:
let word1 = words[i]
for j in i+1..words.high:
let word2 = words[j]
if word1.len == word2.len and editDistance(word1, word2) == 1:
echo word1, " <-> ", word2
inc count, 2
echo "\nFound ", count, " changeable words."
- Output:
List of changeable words: aristotelean <-> aristotelian claustrophobia <-> claustrophobic committeeman <-> committeemen committeewoman <-> committeewomen complementary <-> complimentary confirmation <-> conformation congresswoman <-> congresswomen councilwoman <-> councilwomen craftsperson <-> draftsperson eavesdropped <-> eavesdropper frontiersman <-> frontiersmen handicraftsman <-> handicraftsmen incommutable <-> incomputable installation <-> instillation kaleidescope <-> kaleidoscope neuroanatomy <-> neuroanotomy newspaperman <-> newspapermen nonagenarian <-> nonogenarian onomatopoeia <-> onomatopoeic philanthrope <-> philanthropy prescription <-> proscription schizophrenia <-> schizophrenic shakespearean <-> shakespearian spectroscope <-> spectroscopy underclassman <-> underclassmen upperclassman <-> upperclassmen Found 52 changeable words.
Pascal
Free Pascal
{$mode ObjFPC}{$H+}
uses
Classes, SysUtils;
const
FNAME = 'unixdict.txt';
function OneCharDifference(s1, s2: string): boolean;
var
i, diffCount: integer;
begin
diffCount := 0;
if Length(s1) <> Length(s2) then
Exit(false);
for i := 1 to Length(s1) do
begin
if s1[i] <> s2[i] then
Inc(diffCount);
if diffCount > 1 then
Exit(false);
end;
Result := diffCount = 1;
end;
procedure PurgeList(var list: TStringList);
{ Remove every word that doesn't have at least 12 characters }
var
i: Integer;
begin
for i := Pred(list.Count) downto 0 do
if Length(list[i]) < 12 then
list.Delete(i);
end;
var
list: TStringList;
i, j: Integer;
begin
list := TStringList.Create;
try
list.LoadFromFile(FNAME);
PurgeList(list);
for i := 0 to list.Count - 2 do
for j := i + 1 to list.Count - 1 do
if OneCharDifference(list[i], list[j]) then
writeln(list[i]:15, ' <-> ', list[j]);
finally
list.Free;
end;
end.
- Output:
aristotelean <-> aristotelian claustrophobia <-> claustrophobic committeeman <-> committeemen committeewoman <-> committeewomen complementary <-> complimentary confirmation <-> conformation congresswoman <-> congresswomen councilwoman <-> councilwomen craftsperson <-> draftsperson eavesdropped <-> eavesdropper frontiersman <-> frontiersmen handicraftsman <-> handicraftsmen incommutable <-> incomputable installation <-> instillation kaleidescope <-> kaleidoscope neuroanatomy <-> neuroanotomy newspaperman <-> newspapermen nonagenarian <-> nonogenarian onomatopoeia <-> onomatopoeic philanthrope <-> philanthropy prescription <-> proscription schizophrenia <-> schizophrenic shakespearean <-> shakespearian spectroscope <-> spectroscopy underclassman <-> underclassmen upperclassman <-> upperclassmen
Perl
#!/usr/bin/perl
use strict;
use warnings;
my @words;
@ARGV = 'unixdict.txt';
while( <> )
{
chomp;
length > 11 or next;
for my $prev ( @{ $words[length] } )
{
($prev ^ $_) =~ tr/\0//c == 1 and printf "%30s <-> %s\n", $prev, $_;
}
push @{ $words[length] }, $_;
}
- Output:
aristotelean <-> aristotelian claustrophobia <-> claustrophobic committeeman <-> committeemen committeewoman <-> committeewomen complementary <-> complimentary confirmation <-> conformation congresswoman <-> congresswomen councilwoman <-> councilwomen craftsperson <-> draftsperson eavesdropped <-> eavesdropper frontiersman <-> frontiersmen handicraftsman <-> handicraftsmen incommutable <-> incomputable installation <-> instillation kaleidescope <-> kaleidoscope neuroanatomy <-> neuroanotomy newspaperman <-> newspapermen nonagenarian <-> nonogenarian onomatopoeia <-> onomatopoeic philanthrope <-> philanthropy prescription <-> proscription schizophrenia <-> schizophrenic shakespearean <-> shakespearian spectroscope <-> spectroscopy underclassman <-> underclassmen upperclassman <-> upperclassmen
Alternatively:
#!/usr/bin/perl
use strict; # https://rosettacode.org/wiki/Changeable_words
use warnings;
local $_ = do {local(@ARGV, $/) = 'unixdict.txt'; <> =~ s/^.{0,11}\n//gmr };
my $count = 0;
printf "%3d: %15s <-> %s\n", ++$count, $1, $4
while /^ ((\N*)\N(\N*)) \n(?=.*^ (\2\N\3) \n)/gmsx;
- Output:
1: aristotelean <-> aristotelian 2: claustrophobia <-> claustrophobic 3: committeeman <-> committeemen 4: committeewoman <-> committeewomen 5: complementary <-> complimentary 6: confirmation <-> conformation 7: congresswoman <-> congresswomen 8: councilwoman <-> councilwomen 9: craftsperson <-> draftsperson 10: eavesdropped <-> eavesdropper 11: frontiersman <-> frontiersmen 12: handicraftsman <-> handicraftsmen 13: incommutable <-> incomputable 14: installation <-> instillation 15: kaleidescope <-> kaleidoscope 16: neuroanatomy <-> neuroanotomy 17: newspaperman <-> newspapermen 18: nonagenarian <-> nonogenarian 19: onomatopoeia <-> onomatopoeic 20: philanthrope <-> philanthropy 21: prescription <-> proscription 22: schizophrenia <-> schizophrenic 23: shakespearean <-> shakespearian 24: spectroscope <-> spectroscopy 25: underclassman <-> underclassmen 26: upperclassman <-> upperclassmen
Phix
with javascript_semantics function changeable(string a, b) return length(a)=length(b) and sum(sq_ne(a,b))=1 end function function over11(string word) return length(word)>11 end function sequence words = filter(unix_dict(),over11), res = {} for i=1 to length(words) do for j=i+1 to length(words) do if changeable(words[i],words[j]) then res = append(res,words[i]&" <=> "&words[j]) end if end for end for printf(1,"%d changeable words found:\n%s\n",{length(res),join(shorten(res,"",3),"\n")})
- Output:
26 changeable words found: aristotelean <=> aristotelian claustrophobia <=> claustrophobic committeeman <=> committeemen ... spectroscope <=> spectroscopy underclassman <=> underclassmen upperclassman <=> upperclassmen
Prolog
:- dynamic dictionary_word/1.
main:-
File_name = 'unixdict.txt',
load_dictionary_from_file(File_name, 12),
print_changeable_words(File_name).
load_dictionary_from_file(File, Min_length):-
open(File, read, Stream),
retractall(dictionary_word(_)),
load_dictionary_from_stream(Stream, Min_length),
close(Stream).
load_dictionary_from_stream(Stream, Min_length):-
read_line_to_string(Stream, String),
String \= end_of_file,
!,
string_length(String, Length),
(Length >= Min_length ->
assertz(dictionary_word(String))
;
true),
load_dictionary_from_stream(Stream, Min_length).
load_dictionary_from_stream(_, _).
print_changeable_words(File_name):-
writef('Changeable words in %w:\n', [File_name]),
findall([Word1, Word2],
(dictionary_word(Word1),
dictionary_word(Word2),
Word1 \= Word2,
hamming_distance(Word1, Word2, 1)),
Words),
nth1(N, Words, [Word1, Word2]),
writef('%3r: %15l-> %w\n', [N, Word1, Word2]),
fail.
print_changeable_words(_).
hamming_distance(String1, String2, Dist):-
string_chars(String1, Chars1),
string_chars(String2, Chars2),
hamming_distance(Chars1, Chars2, Dist, 0).
hamming_distance([], [], Dist, Dist):-!.
hamming_distance([Ch|Chars1], [Ch|Chars2], Dist, Count):-
!,
hamming_distance(Chars1, Chars2, Dist, Count).
hamming_distance([_|Chars1], [_|Chars2], Dist, Count):-
Count1 is Count + 1,
Count1 < 2,
hamming_distance(Chars1, Chars2, Dist, Count1).
- Output:
Changeable words in unixdict.txt: 1: aristotelean -> aristotelian 2: aristotelian -> aristotelean 3: claustrophobia -> claustrophobic 4: claustrophobic -> claustrophobia 5: committeeman -> committeemen 6: committeemen -> committeeman 7: committeewoman -> committeewomen 8: committeewomen -> committeewoman 9: complementary -> complimentary 10: complimentary -> complementary 11: confirmation -> conformation 12: conformation -> confirmation 13: congresswoman -> congresswomen 14: congresswomen -> congresswoman 15: councilwoman -> councilwomen 16: councilwomen -> councilwoman 17: craftsperson -> draftsperson 18: draftsperson -> craftsperson 19: eavesdropped -> eavesdropper 20: eavesdropper -> eavesdropped 21: frontiersman -> frontiersmen 22: frontiersmen -> frontiersman 23: handicraftsman -> handicraftsmen 24: handicraftsmen -> handicraftsman 25: incommutable -> incomputable 26: incomputable -> incommutable 27: installation -> instillation 28: instillation -> installation 29: kaleidescope -> kaleidoscope 30: kaleidoscope -> kaleidescope 31: neuroanatomy -> neuroanotomy 32: neuroanotomy -> neuroanatomy 33: newspaperman -> newspapermen 34: newspapermen -> newspaperman 35: nonagenarian -> nonogenarian 36: nonogenarian -> nonagenarian 37: onomatopoeia -> onomatopoeic 38: onomatopoeic -> onomatopoeia 39: philanthrope -> philanthropy 40: philanthropy -> philanthrope 41: prescription -> proscription 42: proscription -> prescription 43: schizophrenia -> schizophrenic 44: schizophrenic -> schizophrenia 45: shakespearean -> shakespearian 46: shakespearian -> shakespearean 47: spectroscope -> spectroscopy 48: spectroscopy -> spectroscope 49: underclassman -> underclassmen 50: underclassmen -> underclassman 51: upperclassman -> upperclassmen 52: upperclassmen -> upperclassman
Python
from collections import defaultdict, Counter
def getwords(minlength=11, fname='unixdict.txt'):
"Return set of lowercased words of > given number of characters"
with open(fname) as f:
words = f.read().strip().lower().split()
return {w for w in words if len(w) > minlength}
words11 = getwords()
word_minus_1 = defaultdict(list) # map word minus char to (word, index) pairs
minus_1_to_word = defaultdict(list) # map word minus char to word
for w in words11:
for i in range(len(w)):
minus_1 = w[:i] + w[i+1:]
word_minus_1[minus_1].append((w, i)) # minus one char
if minus_1 in words11:
minus_1_to_word[minus_1].append(w)
cwords = set() # Changed char words
for _, v in word_minus_1.items():
if len(v) >1:
change_indices = Counter(i for wrd, i in v)
change_words = set(wrd for wrd, i in v)
words_changed = None
if len(change_words) > 1 and change_indices.most_common(1)[0][1] > 1:
words_changed = [wrd for wrd, i in v
if change_indices[i] > 1]
if words_changed:
cwords.add(tuple(sorted(words_changed)))
print(f"{len(minus_1_to_word)} words that are from deleting a char from other words:")
for k, v in sorted(minus_1_to_word.items()):
print(f" {k:12} From {', '.join(v)}")
print(f"\n{len(cwords)} words that are from changing a char from other words:")
for v in sorted(cwords):
print(f" {v[0]:12} From {', '.join(v[1:])}")
- Output:
6 words that are from deleting a char from other words: chromatograph From chromatography electroencephalograph From electroencephalography evolutionary From revolutionary michelangelo From michaelangelo spectrograph From spectrography tetrafluoride From tetrafluouride 26 words that are from changing a char from other words: aristotelean From aristotelian claustrophobia From claustrophobic committeeman From committeemen committeewoman From committeewomen complementary From complimentary confirmation From conformation congresswoman From congresswomen councilwoman From councilwomen craftsperson From draftsperson eavesdropped From eavesdropper frontiersman From frontiersmen handicraftsman From handicraftsmen incommutable From incomputable installation From instillation kaleidescope From kaleidoscope neuroanatomy From neuroanotomy newspaperman From newspapermen nonagenarian From nonogenarian onomatopoeia From onomatopoeic philanthrope From philanthropy prescription From proscription schizophrenia From schizophrenic shakespearean From shakespearian spectroscope From spectroscopy underclassman From underclassmen upperclassman From upperclassmen
Quackery
[ over size
over size != iff
[ 2drop false ]
done
0 unrot
witheach
[ over i^ peek
!= rot + swap
over 2 = if
conclude ]
drop 1 = ] is 1diff ( $ $ --> b )
$ "rosetta/unixdict.txt"
sharefile drop nest$
[] swap witheach
[ dup size 11 > iff
[ nested join ]
else drop ]
[ behead over witheach
[ 2dup
1diff iff
[ over echo$
sp echo$ cr ]
else drop ]
drop
dup size 1 = until ]
drop
- Output:
aristotelean aristotelian claustrophobia claustrophobic committeeman committeemen committeewoman committeewomen complementary complimentary confirmation conformation congresswoman congresswomen councilwoman councilwomen craftsperson draftsperson eavesdropped eavesdropper frontiersman frontiersmen handicraftsman handicraftsmen incommutable incomputable installation instillation kaleidescope kaleidoscope neuroanatomy neuroanotomy newspaperman newspapermen nonagenarian nonogenarian onomatopoeia onomatopoeic philanthrope philanthropy prescription proscription schizophrenia schizophrenic shakespearean shakespearian spectroscope spectroscopy underclassman underclassmen upperclassman upperclassmen
Raku
Sorensen-Dice is very fast to calculate similarities but isn't great for detecting small changes. Levenshtein is great for detecting small changes but isn't very fast.
Get the best of both worlds by doing an initial filter with Sorensen, then get exact results with Levenshtein.
use Text::Levenshtein;
use Text::Sorensen :sorensen;
my @words = grep {.chars > 11}, 'unixdict.txt'.IO.words;
my %bi-grams = @words.map: { $_ => .&bi-gram };
my %skip = @words.map: { $_ => 0 };
say (++$).fmt('%2d'), |$_ for @words.hyper.map: -> $this {
next if %skip{$this};
my ($word, @sorensens) = sorensen($this, %bi-grams);
next unless @sorensens.=grep: { 1 > .[0] > .8 };
@sorensens = @sorensens»[1].grep: {$this.chars == .chars};
my @levenshtein = distance($this, @sorensens).grep: * == 1, :k;
next unless +@levenshtein;
%skip{$_}++ for @sorensens[@levenshtein];
": {$this.fmt('%14s')} <-> ", @sorensens[@levenshtein].join: ', ';
}
- Output:
1: aristotelean <-> aristotelian 2: claustrophobia <-> claustrophobic 3: committeeman <-> committeemen 4: committeewoman <-> committeewomen 5: complimentary <-> complementary 6: confirmation <-> conformation 7: congresswoman <-> congresswomen 8: councilwoman <-> councilwomen 9: draftsperson <-> craftsperson 10: eavesdropped <-> eavesdropper 11: frontiersman <-> frontiersmen 12: handicraftsman <-> handicraftsmen 13: incommutable <-> incomputable 14: installation <-> instillation 15: kaleidescope <-> kaleidoscope 16: neuroanatomy <-> neuroanotomy 17: newspaperman <-> newspapermen 18: nonagenarian <-> nonogenarian 19: onomatopoeia <-> onomatopoeic 20: philanthrope <-> philanthropy 21: proscription <-> prescription 22: schizophrenia <-> schizophrenic 23: shakespearean <-> shakespearian 24: spectroscope <-> spectroscopy 25: underclassman <-> underclassmen 26: upperclassman <-> upperclassmen
REXX
This REXX version doesn't care what order the words in the dictionary are in, nor does it care what
case (lower/upper/mixed) the words are in, the search for alternades is caseless.
It also allows the minimum length to be specified on the command line (CL) as well as the dictionary file identifier.
/*REXX program finds changeable words (within an identified dict.), changing any letter.*/
parse arg minL iFID . /*obtain optional arguments from the CL*/
if minL=='' | minL=="," then minL= 12 /*Not specified? Then use the default.*/
if iFID=='' | iFID=="," then iFID='unixdict.txt' /* " " " " " " */
call readDict /*read & process/filter the dictionary.*/
abc= 'abcdefghijklmnopqrstuvwxyz'; upper abc /*alphabet ordered by frequency of use.*/
Labc= length(abc) /*the length of the alphabet to be used*/
finds= 0 /*count of the changeable words found.*/
do j=1 for n; L= length($.j) /*process all the words that were found*/
x= $.j; upper x /*get an uppercased version of the word*/
do k=1 for L; y= substr(x, k, 1) /*Y: the current letter being changed.*/
do c=1 for Labc /* [↓] change the Y letter to another.*/
?= substr(abc, c, 1) /*get a new char to replace one in word*/
if ?==y then iterate /*Is this the same char? Then use next*/
new= overlay(?, x, k); upper new /*create a spanking new (changed) word.*/
if @.new=='' then iterate /*New word not in dictionary? Skip it.*/
finds= finds + 1 /*bump count of changeable words found.*/
say right(left($.j, 30), 40) @.new /*indent original word for readability.*/
end /*c*/
end /*k*/
end /*j*/
say copies('─', 30) finds ' changeable words found with a minimum length of ' minL
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
readDict: n=0; @.= /*N: the word count of usable words. */
do #=1 while lines(iFID)\==0 /*read each word in the file (word=X).*/
x= strip( linein( iFID) ) /*pick off a word from the input line. */
if length(x)<minL then iterate /*Is the word too short? Then skip it.*/
if \datatype(x, 'M') then iterate /* " " " not alphabetic? Skip it.*/
n= n + 1; $.n= x; /*bump the word counter; assign to $. */
upper x; @.x= $.n /*assign uppercased word ───► array. */
end /*#*/ /* [↑] semaphore name is uppercased. */
#= # - 1 /*adjust word count because of DO loop.*/
say copies('─', 30) # "words ("n 'usable words) in the dictionary file: ' iFID
return
- output when using the default inputs:
────────────────────────────── 25104 words (1064 usable words) in the dictionary file: unixdict.txt aristotelean aristotelian aristotelian aristotelean claustrophobia claustrophobic claustrophobic claustrophobia committeeman committeemen committeemen committeeman committeewoman committeewomen committeewomen committeewoman complementary complimentary complimentary complementary confirmation conformation conformation confirmation congresswoman congresswomen congresswomen congresswoman councilwoman councilwomen councilwomen councilwoman craftsperson draftsperson draftsperson craftsperson eavesdropped eavesdropper eavesdropper eavesdropped frontiersman frontiersmen frontiersmen frontiersman handicraftsman handicraftsmen handicraftsmen handicraftsman incommutable incomputable incomputable incommutable installation instillation instillation installation kaleidescope kaleidoscope kaleidoscope kaleidescope neuroanatomy neuroanotomy neuroanotomy neuroanatomy newspaperman newspapermen newspapermen newspaperman nonagenarian nonogenarian nonogenarian nonagenarian onomatopoeia onomatopoeic onomatopoeic onomatopoeia philanthrope philanthropy philanthropy philanthrope prescription proscription proscription prescription schizophrenia schizophrenic schizophrenic schizophrenia shakespearean shakespearian shakespearian shakespearean spectroscope spectroscopy spectroscopy spectroscope underclassman underclassmen underclassmen underclassman upperclassman upperclassmen upperclassmen upperclassman ────────────────────────────── 52 changeable words found with a minimum length of 12
Ring
cStr = read("unixdict.txt")
wordList = str2list(cStr)
num = 0
see "working..." + nl
ln = len(wordList)
for n = ln to 1 step -1
if len(wordList[n]) < 12
del(wordList,n)
ok
next
see "Changable words are:" + nl
for n = 1 to len(wordList)
len = len(wordList[n])
for m = 1 to len
abcList = "abcdefghijklmnopqrstuvwxyz"
for abc in abcList
str1 = left(wordList[n],m-1)
str2 = abc
str3 = right(wordList[n],len-m)
tempWord = str1 + str2 + str3
ind = find(wordList,tempWord)
bool = (ind > 0) and (wordList[n][m] != abc)
if bool = 1
num = num + 1
see "" + num + ". " + wordList[n] + " >> " + tempWord + nl
ok
next
next
next
see "done..." + nl
Output:
working... Changable words are: 1. aristotelean >> aristotelian 2. aristotelian >> aristotelean 3. claustrophobia >> claustrophobic 4. claustrophobic >> claustrophobia 5. committeeman >> committeemen 6. committeemen >> committeeman 7. committeewoman >> committeewomen 8. committeewomen >> committeewoman 9. complementary >> complimentary 10. complimentary >> complementary 11. confirmation >> conformation 12. conformation >> confirmation 13. congresswoman >> congresswomen 14. congresswomen >> congresswoman 15. councilwoman >> councilwomen 16. councilwomen >> councilwoman 17. craftsperson >> draftsperson 18. draftsperson >> craftsperson 19. eavesdropped >> eavesdropper 20. eavesdropper >> eavesdropped 21. frontiersman >> frontiersmen 22. frontiersmen >> frontiersman 23. handicraftsman >> handicraftsmen 24. handicraftsmen >> handicraftsman 25. incommutable >> incomputable 26. incomputable >> incommutable 27. installation >> instillation 28. instillation >> installation 29. kaleidescope >> kaleidoscope 30. kaleidoscope >> kaleidescope 31. neuroanatomy >> neuroanotomy 32. neuroanotomy >> neuroanatomy 33. newspaperman >> newspapermen 34. newspapermen >> newspaperman 35. nonagenarian >> nonogenarian 36. nonogenarian >> nonagenarian 37. onomatopoeia >> onomatopoeic 38. onomatopoeic >> onomatopoeia 39. philanthrope >> philanthropy 40. philanthropy >> philanthrope 41. prescription >> proscription 42. proscription >> prescription 43. schizophrenia >> schizophrenic 44. schizophrenic >> schizophrenia 45. shakespearean >> shakespearian 46. shakespearian >> shakespearean 47. spectroscope >> spectroscopy 48. spectroscopy >> spectroscope 49. underclassman >> underclassmen 50. underclassmen >> underclassman 51. upperclassman >> upperclassmen 52. upperclassmen >> upperclassman done...
Ruby
words = File.open("unixdict.txt").readlines.map(&:chomp).select{|w| w.size > 11 }
size_groups = words.group_by(&:size).sort.map(&:last)
res = size_groups.flat_map do |group|
group.combination(2).select{|word1, word2| word1.chars.zip(word2.chars).one?{|c1, c2| c1 != c2} }
end
puts "Found #{res.size} changeable word pairs:"
res.each{|w1, w2|puts "#{w1} - #{w2}" }
- Output:
Found 26 changeable word pairs: aristotelean - aristotelian committeeman - committeemen confirmation - conformation councilwoman - councilwomen craftsperson - draftsperson eavesdropped - eavesdropper frontiersman - frontiersmen incommutable - incomputable installation - instillation kaleidescope - kaleidoscope neuroanatomy - neuroanotomy newspaperman - newspapermen nonagenarian - nonogenarian onomatopoeia - onomatopoeic philanthrope - philanthropy prescription - proscription spectroscope - spectroscopy complementary - complimentary congresswoman - congresswomen schizophrenia - schizophrenic shakespearean - shakespearian underclassman - underclassmen upperclassman - upperclassmen claustrophobia - claustrophobic committeewoman - committeewomen handicraftsman - handicraftsmen
Sidef
var file = File("unixdict.txt")
if (!file.exists) {
require('LWP::Simple')
say ":: Retrieving #{file} from internet..."
%S<LWP::Simple>.mirror(
'https://web.archive.org/web/20180611003215if_/' +
'http://www.puzzlers.org:80/pub/wordlists/unixdict.txt',
'unixdict.txt')
}
var words = file.read.words
var bucket = Hash()
var count = 0
words.each {|word|
var len = word.len
len > 11 || next
bucket{len} := []
bucket{len}.each{|prev|
if (prev ^ word -> count("\0") == len-1) {
printf("%2d: %20s <-> %s\n", ++count, prev, word)
}
}
bucket{len} << word
}
- Output:
1: aristotelean <-> aristotelian 2: claustrophobia <-> claustrophobic 3: committeeman <-> committeemen 4: committeewoman <-> committeewomen 5: complementary <-> complimentary 6: confirmation <-> conformation 7: congresswoman <-> congresswomen 8: councilwoman <-> councilwomen 9: craftsperson <-> draftsperson 10: eavesdropped <-> eavesdropper 11: frontiersman <-> frontiersmen 12: handicraftsman <-> handicraftsmen 13: incommutable <-> incomputable 14: installation <-> instillation 15: kaleidescope <-> kaleidoscope 16: neuroanatomy <-> neuroanotomy 17: newspaperman <-> newspapermen 18: nonagenarian <-> nonogenarian 19: onomatopoeia <-> onomatopoeic 20: philanthrope <-> philanthropy 21: prescription <-> proscription 22: schizophrenia <-> schizophrenic 23: shakespearean <-> shakespearian 24: spectroscope <-> spectroscopy 25: underclassman <-> underclassmen 26: upperclassman <-> upperclassmen
Wren
Using the Hamming Distance between two equal length strings which needs to be 1 here:
import "io" for File
import "./fmt" for Fmt
var hammingDist = Fn.new { |s1, s2|
s1 = s1.toList // in case there are non-ASCII characters
s2 = s2.toList // ditto
var count = 0
var i = 0
while (i < s1.count) {
if (s1[i] != s2[i]) {
count = count + 1
if (count == 2) break // don't care about counts > 2
}
i = i + 1
}
return count
}
var wordList = "unixdict.txt" // local copy
var words = File.read(wordList).trimEnd().split("\n").where { |w| w.count > 11 }.toList
var count = 0
System.print("Changeable words in %(wordList):")
for (word1 in words) {
for (word2 in words) {
if (word1 != word2 && word1.count == word2.count) {
if (hammingDist.call(word1, word2) == 1) {
count = count + 1
Fmt.print("$2d: $-14s -> $s", count, word1, word2)
}
}
}
}
- Output:
Changeable words in unixdict.txt: 1: aristotelean -> aristotelian 2: aristotelian -> aristotelean 3: claustrophobia -> claustrophobic 4: claustrophobic -> claustrophobia 5: committeeman -> committeemen 6: committeemen -> committeeman 7: committeewoman -> committeewomen 8: committeewomen -> committeewoman 9: complementary -> complimentary 10: complimentary -> complementary 11: confirmation -> conformation 12: conformation -> confirmation 13: congresswoman -> congresswomen 14: congresswomen -> congresswoman 15: councilwoman -> councilwomen 16: councilwomen -> councilwoman 17: craftsperson -> draftsperson 18: draftsperson -> craftsperson 19: eavesdropped -> eavesdropper 20: eavesdropper -> eavesdropped 21: frontiersman -> frontiersmen 22: frontiersmen -> frontiersman 23: handicraftsman -> handicraftsmen 24: handicraftsmen -> handicraftsman 25: incommutable -> incomputable 26: incomputable -> incommutable 27: installation -> instillation 28: instillation -> installation 29: kaleidescope -> kaleidoscope 30: kaleidoscope -> kaleidescope 31: neuroanatomy -> neuroanotomy 32: neuroanotomy -> neuroanatomy 33: newspaperman -> newspapermen 34: newspapermen -> newspaperman 35: nonagenarian -> nonogenarian 36: nonogenarian -> nonagenarian 37: onomatopoeia -> onomatopoeic 38: onomatopoeic -> onomatopoeia 39: philanthrope -> philanthropy 40: philanthropy -> philanthrope 41: prescription -> proscription 42: proscription -> prescription 43: schizophrenia -> schizophrenic 44: schizophrenic -> schizophrenia 45: shakespearean -> shakespearian 46: shakespearian -> shakespearean 47: spectroscope -> spectroscopy 48: spectroscopy -> spectroscope 49: underclassman -> underclassmen 50: underclassmen -> underclassman 51: upperclassman -> upperclassmen 52: upperclassmen -> upperclassman
XPL0
string 0; \use zero-terminated strings
int Dict(26000); \pointers to words (enough for unixdict.txt)
int DictSize; \actual number of pointers in Dict
func StrCmp(A, B); \Compare string A to B
char A, B; \Returns: >0 if A>B, =0 if A=B, and <0 if A<B
int I;
[for I:= 0 to -1>>1 do
[if A(I) # B(I) then return A(I) - B(I);
if A(I) = 0 then return 0;
];
]; \StrCmp
func LookUp(Word); \Return 'true' if Word is in Dict
char Word;
int Lo, Hi, I, Cmp;
[Lo:= 0; Hi:= DictSize-1;
loop [I:= (Lo+Hi) / 2; \binary search
Cmp:= StrCmp(Word, Dict(I));
if Cmp < 0 then Hi:= I-1 else Lo:= I+1;
if Cmp = 0 then return true;
if Lo > Hi then return false;
];
]; \LookUp
int I, J, L, DI, Ch, Count;
char Word, ChgWord(25); \longest word in unixdict.txt is 22 chars
def Tab=$09, LF=$0A, CR=$0D, EOF=$1A;
[FSet(FOpen("unixdict.txt", 0), ^I); \load dictionary
OpenI(3); \assume alphabetical order and all lowercase
DI:= 0; \ignore non-alpha characters: 0..9, ' and &
repeat Dict(DI):= Reserve(0); \get pointer to memory used to store Word
Word:= Dict(DI);
I:= 0;
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;
];
Word(I):= 0; \terminate Word string
I:= Reserve(I+1); \reserve memory used for Word
DI:= DI+1; \next dictionary entry
until Ch = EOF;
DictSize:= DI;
DI:= 0; Count:= 0; \print out all changeable words
repeat Word:= Dict(DI); \assume all lowercase letters
I:= 0; J:= 0;
loop [Ch:= Word(I);
if Ch = 0 then quit;
ChgWord(I):= Ch;
I:= I+1;
];
ChgWord(I):= 0;
if I >= 12 then \Word must have at least 12 chars
[for J:= 0 to I-1 do \for all letter positions in Word
[for L:= ^a to ^z do \for all letters
if L # Word(J) then
[ChgWord(J):= L;
if LookUp(ChgWord) then
[Count:= Count+1;
IntOut(0, Count); ChOut(0, Tab);
Text(0, Word); ChOut(0, Tab);
Text(0, ChgWord);
CrLf(0);
];
ChgWord(J):= Word(J); \undo letter change
];
];
];
DI:= DI+1;
until DI >= DictSize;
]
- Output:
1 aristotelean aristotelian 2 aristotelian aristotelean 3 claustrophobia claustrophobic 4 claustrophobic claustrophobia 5 committeeman committeemen 6 committeemen committeeman 7 committeewoman committeewomen 8 committeewomen committeewoman 9 complementary complimentary 10 complimentary complementary 11 confirmation conformation 12 conformation confirmation 13 congresswoman congresswomen 14 congresswomen congresswoman 15 councilwoman councilwomen 16 councilwomen councilwoman 17 craftsperson draftsperson 18 draftsperson craftsperson 19 eavesdropped eavesdropper 20 eavesdropper eavesdropped 21 frontiersman frontiersmen 22 frontiersmen frontiersman 23 handicraftsman handicraftsmen 24 handicraftsmen handicraftsman 25 incommutable incomputable 26 incomputable incommutable 27 installation instillation 28 instillation installation 29 kaleidescope kaleidoscope 30 kaleidoscope kaleidescope 31 neuroanatomy neuroanotomy 32 neuroanotomy neuroanatomy 33 newspaperman newspapermen 34 newspapermen newspaperman 35 nonagenarian nonogenarian 36 nonogenarian nonagenarian 37 onomatopoeia onomatopoeic 38 onomatopoeic onomatopoeia 39 philanthrope philanthropy 40 philanthropy philanthrope 41 prescription proscription 42 proscription prescription 43 schizophrenia schizophrenic 44 schizophrenic schizophrenia 45 shakespearean shakespearian 46 shakespearian shakespearean 47 spectroscope spectroscopy 48 spectroscopy spectroscope 49 underclassman underclassmen 50 underclassmen underclassman 51 upperclassman upperclassmen 52 upperclassmen upperclassman