/* Textonyms (Rosetta code) Picat. http://rosettacode.org/wiki/Textonyms """ When entering text on a phone's digital pad it is possible that a particular combination of digits corresponds to more than one word. Such are called textonyms. Assuming the digit keys are mapped to letters as follows: 2 -> ABC 3 -> DEF 4 -> GHI 5 -> JKL 6 -> MNO 7 -> PQRS 8 -> TUV 9 -> WXYZ Task Write a program that finds textonyms in a list of words such as Textonyms/wordlist or unixdict.txt. The task should produce a report: There are #{0} words in #{1} which can be represented by the digit key mapping. They require #{2} digit combinations to represent them. #{3} digit combinations represent Textonyms. Where: #{0} is the number of words in the list which can be represented by the digit key mapping. #{1} is the URL of the wordlist being used. #{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 Textonyms. E.G.: 2748424767 -> "Briticisms", "criticisms" Extra credit Use a word list and keypad mapping other than English. """ Cf phone_code2.pi This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp,util. main => go. go => Dict = "unixdict.txt", Words = read_file_lines(Dict), Map = new_map(), Counts = 0, foreach(Word in Words, Code=encode(Word), Word.len == Code.len) Map.put(Code,Map.get(Code,[]) ++ [Word]), Counts := Counts + 1 end, Lens = [[V.len,K,V] : K=V in Map].sort_down, NumNonUnique = [1 : L in Lens, L[1] > 1].len, printf("There are %d words in '%w' which can be represented by the Textonyms mapping.\n",Counts,Dict), printf("They require %d digit combinations to represent them.\n", Map.keys.len), printf("%d digit combinations represent Textonyms.\n",NumNonUnique), nl, MaxNumWords = Lens[1,1], println(maxNumWords=MaxNumWords), println([L : L in Lens, L[1] == MaxNumWords]), MaxLen = max([Word[2].len=Word : Word in Lens]), println(maxLen=MaxLen), println(lens6=Lens.take(6)), nl. phone_map(a,'2'). phone_map(b,'2'). phone_map(c,'2'). phone_map(d,'3'). phone_map(e,'3'). phone_map(f,'3'). phone_map(g,'4'). phone_map(h,'4'). phone_map(i,'4'). phone_map(j,'5'). phone_map(k,'5'). phone_map(l,'5'). phone_map(m,'6'). phone_map(n,'6'). phone_map(o,'6'). phone_map(p,'7'). phone_map(q,'7'). phone_map(r,'7'). phone_map(s,'7'). phone_map(t,'8'). phone_map(u,'8'). phone_map(v,'8'). phone_map(w,'9'). phone_map(x,'9'). phone_map(y,'9'). phone_map(z,'9'). phone_map(_,''). encode(Word) = [P : C in Word, phone_map(C,P), P != '']. go2 => Dict = "unixdict.txt", Words = new_map([Word=1 : Word in read_file_lines(Dict)]), member(Num,330_000..340_000), PhoneWords = findall(Word, (decode(Num,Word), Words.has_key(Word))), PhoneWords.len > 1, println(Num=PhoneWords), fail, nl. % Decode a number to a word decode(Num,Word) :- decode(Num.to_string,"",Word). decode([],Word,Word). decode([P|T],Word0,[C|Word]) :- phone_map(C,P), decode(T,Word0,Word). rand_cp(N,Min,Max) = X => _ = random2(), X = new_list(N), X :: Min..Max, solve($[rand_var,rand_val],X).