2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -10,7 +10,11 @@ Assuming the digit keys are mapped to letters as follows:
8 -> TUV
9 -> WXYZ
The task is to write a program that finds textonyms in a list of words such as [[Textonyms/wordlist]] or [http://www.puzzlers.org/pub/wordlists/unixdict.txt].
;Task:
Write a program that finds textonyms in a list of words such as  
[[Textonyms/wordlist]]   or  
[http://www.puzzlers.org/pub/wordlists/unixdict.txt unixdict.txt].
The task should produce a report:
@ -24,10 +28,13 @@ Where:
#{2} is the number of digit combinations required to represent the words in #{0}.
#{3} is the number of #{2} which represent more than one word.
At your discretion show a couple of examples of your solution displaying Textonys. e.g.
At your discretion show a couple of examples of your solution displaying Textonys.
E.G.:
2748424767 -> "Briticisms", "criticisms"
Extra credit:
;Extra credit:
Use a word list and keypad mapping other than English.
<br><br>

View file

@ -0,0 +1,136 @@
# find textonyms in a list of words #
# use the associative array in the Associate array/iteration task #
PR read "aArray.a68" PR
# returns the number of occurances of ch in text #
PROC count = ( STRING text, CHAR ch )INT:
BEGIN
INT result := 0;
FOR c FROM LWB text TO UPB text DO IF text[ c ] = ch THEN result +:= 1 FI OD;
result
END # count # ;
CHAR invalid char = "*";
# returns text with the characters replaced by their text digits #
PROC to text = ( STRING text )STRING:
BEGIN
STRING result := text;
FOR pos FROM LWB result TO UPB result DO
CHAR c = to upper( result[ pos ] );
IF c = "A" OR c = "B" OR c = "C" THEN result[ pos ] := "2"
ELIF c = "D" OR c = "E" OR c = "F" THEN result[ pos ] := "3"
ELIF c = "G" OR c = "H" OR c = "I" THEN result[ pos ] := "4"
ELIF c = "J" OR c = "K" OR c = "L" THEN result[ pos ] := "5"
ELIF c = "M" OR c = "N" OR c = "O" THEN result[ pos ] := "6"
ELIF c = "P" OR c = "Q" OR c = "R" OR c = "S" THEN result[ pos ] := "7"
ELIF c = "T" OR c = "U" OR c = "V" THEN result[ pos ] := "8"
ELIF c = "W" OR c = "X" OR c = "Y" OR c = "Z" THEN result[ pos ] := "9"
ELSE # not a character that can be encoded # result[ pos ] := invalid char
FI
OD;
result
END # to text # ;
# read the list of words and store in an associative array #
CHAR separator = "/"; # character that will separate the textonyms #
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 #
on logical file end( input file, ( REF FILE f )BOOL:
BEGIN
# note that we reached EOF on the #
# latest read #
at eof := TRUE;
# return TRUE so processing can continue #
TRUE
END
);
REF AARRAY words := INIT LOC AARRAY;
INT word count := 0;
INT combinations := 0;
INT multiple count := 0;
INT max length := 0;
WHILE STRING word;
get( input file, ( word, newline ) );
NOT at eof
DO
STRING text word = to text( word );
IF count( text word, invalid char ) = 0 THEN
# the word can be fully encoded #
word count +:= 1;
INT length := ( UPB word - LWB word ) + 1;
IF length > max length THEN
# this word is longer than the maximum length found so far #
max length := length
FI;
IF ( words // text word ) = "" THEN
# first occurance of this encoding #
combinations +:= 1;
words // text word := word
ELSE
# this encoding has already been used #
IF count( words // text word, separator ) = 0
THEN
# this is the second time this encoding is used #
multiple count +:= 1
FI;
words // text word +:= separator + word
FI
FI
OD;
# close the file #
close( input file );
# find the maximum number of textonyms #
INT max textonyms := 0;
REF AAELEMENT e := FIRST words;
WHILE e ISNT nil element DO
INT textonyms := count( value OF e, separator );
IF textonyms > max textonyms
THEN
max textonyms := textonyms
FI;
e := NEXT words
OD;
print( ( "There are ", whole( word count, 0 ), " words in ", file name, " which can be represented by the digit key mapping.", newline ) );
print( ( "They require ", whole( combinations, 0 ), " digit combinations to represent them.", newline ) );
print( ( whole( multiple count, 0 ), " combinations represent Textonyms.", newline ) );
# show the textonyms with the maximum number #
print( ( "The maximum number of textonyms for a particular digit key mapping is ", whole( max textonyms + 1, 0 ), " as follows:", newline ) );
e := FIRST words;
WHILE e ISNT nil element DO
IF INT textonyms := count( value OF e, separator );
textonyms = max textonyms
THEN
print( ( " ", key OF e, " encodes ", value OF e, newline ) )
FI;
e := NEXT words
OD;
# show the textonyms with the maximum length #
print( ( "The longest words are ", whole( max length, 0 ), " chracters long", newline ) );
print( ( "Encodings with this length are:", newline ) );
e := FIRST words;
WHILE e ISNT nil element DO
IF max length = ( UPB key OF e - LWB key OF e ) + 1
THEN
print( ( " ", key OF e, " encodes ", value OF e, newline ) )
FI;
e := NEXT words
OD;
FI

View file

@ -0,0 +1,104 @@
main := method(
setupLetterToDigitMapping
file := File clone openForReading("./unixdict.txt")
words := file readLines
file close
wordCount := 0
textonymCount := 0
dict := Map clone
words foreach(word,
(key := word asPhoneDigits) ifNonNil(
wordCount = wordCount+1
value := dict atIfAbsentPut(key,list())
value append(word)
if(value size == 2,textonymCount = textonymCount+1)
)
)
write("There are ",wordCount," words in ",file name)
writeln(" which can be represented by the digit key mapping.")
writeln("They require ",dict size," digit combinations to represent them.")
writeln(textonymCount," digit combinations represent Textonyms.")
samplers := list(maxAmbiquitySampler, noMatchingCharsSampler)
dict foreach(key,value,
if(value size == 1, continue)
samplers foreach(sampler,sampler examine(key,value))
)
samplers foreach(sampler,sampler report)
)
setupLetterToDigitMapping := method(
fromChars := Sequence clone
toChars := Sequence clone
list(
list("ABC", "2"), list("DEF", "3"), list("GHI", "4"),
list("JKL", "5"), list("MNO", "6"), list("PQRS","7"),
list("TUV", "8"), list("WXYZ","9")
) foreach( map,
fromChars appendSeq(map at(0), map at(0) asLowercase)
toChars alignLeftInPlace(fromChars size, map at(1))
)
Sequence asPhoneDigits := block(
str := call target asMutable translate(fromChars,toChars)
if( str contains(0), nil, str )
) setIsActivatable(true)
)
maxAmbiquitySampler := Object clone do(
max := list()
samples := list()
examine := method(key,textonyms,
i := key size - 1
if(i > max size - 1,
max setSize(i+1)
samples setSize(i+1)
)
nw := textonyms size
nwmax := max at(i)
if( nwmax isNil or nw > nwmax,
max atPut(i,nw)
samples atPut(i,list(key,textonyms))
)
)
report := method(
writeln("\nExamples of maximum ambiquity for each word length:")
samples foreach(sample,
sample ifNonNil(
writeln(" ",sample at(0)," -> ",sample at(1) join(" "))
)
)
)
)
noMatchingCharsSampler := Object clone do(
samples := list()
examine := method(key,textonyms,
for(i,0,textonyms size - 2 ,
for(j,i+1,textonyms size - 1,
if( _noMatchingChars(textonyms at(i), textonyms at(j)),
samples append(list(textonyms at(i),textonyms at(j)))
)
)
)
)
_noMatchingChars := method(t1,t2,
t1 foreach(i,ich,
if(ich == t2 at(i), return false)
)
true
)
report := method(
write("\nThere are ",samples size," textonym pairs which ")
writeln("differ at each character position.")
if(samples size > 10, writeln("The ten largest are:"))
samples sortInPlace(at(0) size negate)
if(samples size > 10,samples slice(0,10),samples) foreach(sample,
writeln(" ",sample join(" ")," -> ",sample at(0) asPhoneDigits)
)
)
)
main

View file

@ -0,0 +1,55 @@
-- Global variables
http = require("socket.http")
keys = {"VOICEMAIL", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}
dictFile = "http://www.puzzlers.org/pub/wordlists/unixdict.txt"
-- Return the sequence of keys required to type a given word
function keySequence (str)
local sequence, noMatch, letter = ""
for pos = 1, #str do
letter = str:sub(pos, pos)
for i, chars in pairs(keys) do
noMatch = true
if chars:match(letter) then
sequence = sequence .. tostring(i)
noMatch = false
break
end
end
if noMatch then return nil end
end
return tonumber(sequence)
end
-- Generate table of words grouped by key sequence
function textonyms (dict)
local combTable, keySeq = {}
for word in dict:gmatch("%S+") do
keySeq = keySequence(word)
if keySeq then
if combTable[keySeq] then
table.insert(combTable[keySeq], word)
else
combTable[keySeq] = {word}
end
end
end
return combTable
end
-- Analyse sequence table and print details
function showReport (keySeqs)
local wordCount, seqCount, tCount = 0, 0, 0
for seq, wordList in pairs(keySeqs) do
wordCount = wordCount + #wordList
seqCount = seqCount + 1
if #wordList > 1 then tCount = tCount + 1 end
end
print("There are " .. wordCount .. " words in " .. dictFile)
print("which can be represented by the digit key mapping.")
print("They require " .. seqCount .. " digit combinations to represent them.")
print(tCount .. " digit combinations represent Textonyms.")
end
-- Main procedure
showReport(textonyms(http.request(dictFile)))

View file

@ -0,0 +1,45 @@
$url = "http://www.puzzlers.org/pub/wordlists/unixdict.txt"
$file = "$env:TEMP\unixdict.txt"
(New-Object System.Net.WebClient).DownloadFile($url, $file)
$unixdict = Get-Content -Path $file
[string]$alpha = "abcdefghijklmnopqrstuvwxyz"
[string]$digit = "22233344455566677778889999"
$table = [ordered]@{}
for ($i = 0; $i -lt $alpha.Length; $i++)
{
$table.Add($alpha[$i], $digit[$i])
}
$words = foreach ($word in $unixdict)
{
if ($word -match "^[a-z]*$")
{
[PSCustomObject]@{
Word = $word
Number = ($word.ToCharArray() | ForEach-Object {$table.$_}) -join ""
}
}
}
$digitCombinations = $words | Group-Object -Property Number
$textonyms = $digitCombinations | Where-Object -Property Count -GT 1 | Sort-Object -Property Count -Descending
Write-Host ("There are {0} words in {1} which can be represented by the digit key mapping." -f $words.Count, $url)
Write-Host ("They require {0} digit combinations to represent them." -f $digitCombinations.Count)
Write-Host ("{0} digit combinations represent Textonyms.`n" -f $textonyms.Count)
Write-Host "Top 5 in ambiguity:"
$textonyms | Select-Object -First 5 -Property Count,
@{Name="Textonym"; Expression={$_.Name}},
@{Name="Words" ; Expression={$_.Group.Word -join ", "}} | Format-Table -AutoSize
Write-Host "Top 5 in length:"
$textonyms | Sort-Object {$_.Name.Length} -Descending |
Select-Object -First 5 -Property @{Name="Length" ; Expression={$_.Name.Length}},
@{Name="Textonym"; Expression={$_.Name}},
@{Name="Words" ; Expression={$_.Group.Word -join ", "}} | Format-Table -AutoSize
Remove-Item -Path $file -Force -ErrorAction SilentlyContinue

View file

@ -1,47 +1,49 @@
/*REXX program counts the number of textonyms are in a file (dictionary)*/
parse arg iFID . /*get optional fileID of the file*/
if iFID=='' then iFID='UNIXDICT.TXT' /*filename of the word dictionary*/
@.=0 /*digit combinations placeholder.*/
!.=; $.= /*sparse array of textonyms;words*/
alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZ' /*supported alphabet to be used. */
digitKey= 22233344455566677778889999 /*translated alphabet to dig key.*/
digKey=0; wordCount=0 /*# digit combinations; wordCount*/
ills=0; dups=0; longest=0; mostus=0 /*illegals; duplicate words; lit.*/
first=0; last=0; long=0; most=0 /*for: first, last, longest, ··· */
call linein iFID, 1, 0 /*point to the first char in dict*/
#=0 /*number of textonyms in the file*/
/* [↑] ───in case file is open.*/
do j=1 while lines(iFID)\==0 /*keep reading until exhausted. */
x=linein(iFID); y=x; upper x /*get a word and uppercase it. */
if \datatype(x,'U') then do; ills=ills+1; iterate; end /*illegal? */
if $.x\=='' then do; dups=dups+1; iterate; end /*duplicate?*/
else $.x=. /*indicate it's a righteous word.*/
wordCount=wordCount+1 /*bump the word count (for file).*/
z=translate(x, digitKey, alphabet) /*build translated digit key word*/
@.z=@.z+1 /*flag the digit key word exists.*/
!.z=!.z y; _=words(!.z) /*build a list of same digit key.*/
if _>most then do; mostus=z; most=_; end /*remember mostus digKeys.*/
if @.z==2 then do; #=#+1 /*bump the count of the textonyms*/
if first==0 then first=z /*the first textonym found*/
last=z /* " last " " */
_=length(!.z) /*length of the digit key.*/
if _>longest then long=z /*is this the longest ? */
longest=max(_, longest) /*now, shoot for this len.*/
end /* [↑] discretionary stuff*/
if @.z\==1 then iterate /*Does it already exist? Skip it*/
digKey=digKey+1 /*bump count of digit key words. */
/*REXX program counts and displays the number of textonyms that are in a dictionary file*/
parse arg iFID . /*obtain optional fileID from the C.L. */
if iFID=='' then iFID='UNIXDICT.TXT' /*Not specified? Then use the default.*/
@.=0 /*the placeholder of digit combinations*/
!.=; $.= /*sparse array of textonyms; words. */
alphabet= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' /*the supported alphabet to be used. */
digitKey= 22233344455566677778889999 /*translated alphabet to digit keys. */
digKey=0; wordCount=0 /*number digit combinations; wordCount.*/
ills=0; dups=0; longest=0; mostus=0 /*illegals; duplicated words; longest..*/
first=0; last=0; long=0; most=0 /*first, last, longest, most counts. */
call linein iFID, 1, 0 /*point to the first char in dictionary*/
#=0 /*number of textonyms in file (so far).*/
do j=1 while lines(iFID)\==0 /*keep reading the file until exhausted*/
x=linein(iFID); y=x; upper x /*get a word; save a copy; uppercase it*/
if \datatype(x,'U') then do; ills=ills+1; iterate; end /*is it illegal? */
if $.x\=='' then do; dups=dups+1; iterate; end /*is it duplicate?*/
else $.x=. /*indicate that it's a righteous word. */
wordCount=wordCount+1 /*bump the word count (for the file). */
z=translate(x, digitKey, alphabet) /*build a translated digit key word. */
@.z=@.z+1 /*flag that the digit key word exists. */
!.z=!.z y; _=words(!.z) /*build list of equivalent digit key(s)*/
if _>most then do; mostus=z; most=_; end /*remember the "mostus" digit keys. */
if @.z==2 then do; #=#+1 /*bump the count of the textonyms. */
if first==0 then first=z /*the first textonym found. */
last=z /* " last " " */
_=length(!.z) /*the length (# chars) of the digit key*/
if _>longest then long=z /*is this the longest textonym ? */
longest=max(_, longest) /*now, use this length as a target/goal*/
end /* [↑] discretionary (extra credit). */
if @.z\==1 then iterate /*Does it already exist? Then Skip it.*/
digKey=digKey+1 /*bump the count of digit key words. */
end /*j*/
@@=' which can be represented by the digit key mapping.'
say wordCount 'is the number of words in file "'iFID'"' @@
if ills\==0 then say ills 'word's(ills) "contained illegal characters."
if dups\==0 then say dups "duplicate word"s(dups) 'detected.'
say 'They require' digKey "combination"s(digKey) 'to represent them.'
say # 'digit combination's(#) "represent Textonyms."
@whichCan...= 'which can be represented by digit key mapping.'
@Ta = 'There are '
say 'The dictionary file being used is: ' iFID
say @Ta wordCount ' words in the file' @whichCan...
if ills\==0 then say @Ta ills ' word's(ills) "contained illegal characters."
if dups\==0 then say @Ta dups " duplicate word"s(dups) 'in the dictionary detected.'
say 'The textonyms require ' digKey " combination"s(digKey) 'to represent them.'
say @Ta # ' digit combination's(#) " that can represent Textonyms."
say
if first\==0 then say ' first digit key=' !.first
if last\==0 then say ' last digit key=' !.last
if long\==0 then say ' longest digit key=' !.long
if most\==0 then say ' numerous digit key=' !.mostus ' ('most "words)"
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────S subroutine────────────────────────*/
s: if arg(1)==1 then return ''; return 's' /*a simple pluralizer.*/
if first\==0 then say ' first digit key=' !.first
if last\==0 then say ' last digit key=' !.last
if long\==0 then say ' longest digit key=' !.long
if most\==0 then say ' numerous digit key=' !.mostus ' ('most "words)"
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
s: if arg(1)==1 then return ''; return "s" /*a simple pluralizer.*/