/* Cryptogram (a.k.a. Isomorphic Words) in Picat. Given a word, check if any other word(s) in a word list have the same "structure". Example (from http://www.wolframalpha.com/input/?i=cryptograms+krkrpl&lk=3) krkrpl -> cacaos cocoas icicle jojoba jujube lilies mimics papacy papaws piping pipits reread tatami titian vivify Also, compare with my Isomorphic Words program: http://hakank.org/isomorphic_words/isomorphic_words.cgi Example: The word "krkrpl" has the tructure [1,2,1,2,3,4] and so does these 93 words: [acacin,alaloi,alalus,ananke,anansi,ananym,azazel,babasu,beberg,bibiru, cacaos,cicily,cocoas,cocona,cucule,cuculi,cucurb,cucuta,cucuyo,didier, didies,didine,dodoes,dodoma,dodona,egegik,fifine,fifing,fifish,gagaku, gagate,icicle,jijiga,jojoba,jujube,kakapo,kokoda,kokopu,kukupa,lalage, lalang,lilian,lilias,lilied,lilies,lilith,lilium,lilius,luluai,mimics, mimine,miming,mimish,nanako,nonoic,ononis,papacy,papago,papain,papaio, papane,papaws,pipier,pipile,pipilo,piping,pipits,popode,pupulo,reread, rerent,sasabe,sasani,seseli,sisile,sisith,tatami,tatamy,tatars,tatary, teteak,titian,titien,tities,totora,totowa,wewela,vivian,vivica,vivien, vivify,vyvyan,zizith] For the structure abcdeabcd ([1,2,3,4,5,1,2,3,4]) there are 7 words: muckamuck okeydokey outshouts overcover overhover overlover pungapung This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ % import util. % import cp. main => go. go => Word1 = "krkrpl", % Word1 = "anna", % Word1 = "hakank", % Word1 = "kjellerstrand", % Word1 = "mississippi", % Word1 = "abcdeabcd", % Word1 = "abcde", % [1,2,3,4,5] % Len = Word1.length, println(word=Word1), Structure1 = structure(Word1), println(structure=Structure1), Wordlist = "words_lower.txt", % Wordlist = "sv_spelling_org_utf8.txt", Words = check_wordlist(Wordlist, Structure1), foreach(W in Words) println(W) end, println(len=Words.length), nl. % random length and random structure go2 => Len = 3 + random2() mod 10, Structure = structure([1+random2() mod Len : _ in 1..Len]), println(structure=Structure), Wordlist = "words_lower.txt", Words = check_wordlist2(Wordlist, Structure), foreach(Word in Words) println(Word) end, nl. % % Match the structure of each words in a wordlist. % check_wordlist(Wordlist, Structure) = Words => Len = Structure.length, FD = open(Wordlist), Words = [], while (not at_end_of_stream(FD)) Word2 := read_line(FD), if Word2.length == Len, structure(Word2) = Structure then Words := Words ++ [Word2] end end, close(FD). check_wordlist2(Wordlist, Structure) = Words => Len = Structure.length, Words = [Word : Word in read_file_lines(Wordlist), Word.length=Len, structure(Word) = Structure]. % % Convert a word to a word structure, i.e. where % each character gets the index of its first occurrence. % % E.g. % % krkrpl has the structure [1,2,1,2,3,4] % % 121234 % krkrpl % % hakank has the structure [1,2,3,2,4,3] % abcde has the structure [1,2,3,4,5] % structure(Word) = S => M = new_map(), S1 = [], Ix = 1, foreach(W in Word) if not(M.has_key(W)) then M.put(W,Ix), Ix := Ix + 1 end, S1 := S1 ++ [M.get(W)] end, S = S1. % % Another approach. % % Though not as nice as in K (0-based): % ,/&:'(?a)=/:a:"hakank" % 0 1 2 1 3 2 % Or in J (also 0-based): % (i.~~.)~'hakank' % 0 1 2 1 3 2 % structure2(Word) = S => U = Word.remove_dups(), M = new_map([C=I : {C,I} in zip(U, 1..U.length)]), S = [M.get(C) : C in Word].