1 / 44

Solving Jumble ® Puzzles Dictionaries, Hashes and Permutations

Solving Jumble ® Puzzles Dictionaries, Hashes and Permutations. Richard A. DeVenezia. Jumble ® Puzzles. Four scrambled words Two five letter words Two six letter words Marked letters of unscrambled words Scramble of an answer to a cartoon hint. Sample Puzzle. LASRN O O O SHACE O O O

nelson
Download Presentation

Solving Jumble ® Puzzles Dictionaries, Hashes and Permutations

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Solving Jumble®PuzzlesDictionaries, Hashes and Permutations Richard A. DeVenezia

  2. Jumble® Puzzles • Four scrambled words • Two five letter words • Two six letter words • Marked letters of unscrambled words • Scramble of an answer to a cartoon hint

  3. Sample Puzzle LASRN OOO SHACE OOO HOTGUF OOO CLATHE OOO Hint: You are here. A:

  4. Puzzle Representation • Scrambled words • letter pool • Unscrambled key • Circled positions to answer pool • Answer key • Dashes

  5. Problem Solving • Input • Unjumble • Permutation, Lookup • Letter Pool • Find Answer • Permutation, Lookup • Output Results

  6. Puzzle Data • One puzzle per date datalines; 2006-10-09 ----- ------- fasrn OOO-- shace O--OO hotguf --OO-O clathe --OO-O run;

  7. Input data jumbles (keep=date jumble circle) answers (keep=date answer) ; input date yymmdd10. answer $char50.; output answers; do i = 1 to 4; input jumble:$6. circle:$6. ; output jumbles; end;

  8. ALLPERM • Permutations • interchange • “Because each permutation is generated from the previous permutation by a single interchange, the algorithm is very efficient.” SAS Help

  9. ALLPERM data allperms; array p[5] (1:5); do i = 1 to FACT(5); call ALLPERM(i, of p[*]); output; end; run;

  10. Lookup • DATA Step • SET KEY=index • Custom format • Hash object • Hash • Key • Data

  11. Hash object declare HASH dict (); dict.defineKey('word'); dict.defineDone(); word='SESUG'; dict.add(); word='SUGI'; found = (dict.check()=0); put found=; --- found=0

  12. Dictionary Data • http://wordlist.sourceforge.net/ • Word lists • http://prdownloads.sourceforge.net/wordlist/agid-4.zip • infl.txt (inflected) Part of Speech conferee N: conferees conference N: conferences conference V: conferenced | conferencing | conferences conferencing N?: conferencings

  13. Dictionary Input infile INFL dlm=' ,|' missover end=end; input word pos @; do until (word=''); word = compress (word,'~<!?'); if not indexc (word,'123456790.{}') then words.replace(); input word@; end; input;

  14. Dictionary Output • Hash method OUTPUT(dataset:dataset) rc = words.output (dataset:’sasuser.agid_dictionary’);

  15. Unjumble • Data • Four jumbled words • Permutations • of letter array • 5! + 5! + 6! + 6! • 1,680 lookups by word • ALLPERM • N = n1 n2 n3 n4 combinations

  16. Load Dictionary declare hash dict (); dict.defineKey ('word'); dict.defineDone (); length word $6; do until (end_dict); set &dictionary (where=(length(word) in (5,6))) end=end_dict ; word = lowcase(word); dict.replace(); end;

  17. Data do until (end_jumble); set jumbles end=end_jumble; where date = “09OCT2006”D; _i + 1; jumble = lowcase(jumble); link allperm; end;

  18. ALLPERM section • Jumbled Word to Letter Array • For each permutation of Array • Array to Word • If Word in Dictionary • Determine circled letters • OUTPUT

  19. Word to Letter Array • length jumble $6 • array letters $1 letter1-letter6 • call pokelong (jumble, addrlong (letters[1]))

  20. Letter Array to Word • length jumble $6 • array letters $1 letter1-letter6 • jumble = peekclong (addrlong (letters[1])), 6)

  21. Check Each Permutation L = length (jumble); call pokelong(jumble,addrlong(letters[1])); do i = 1 to fact (L); if L = 5 then call allperm (i, of letters1-letters5); else call allperm (i, of letters1-letters6); word = peekclong (addrlong (letters(1)), L); if (word ne jumble) and dict.check () = 0 then ... end;

  22. Circled Letters k = 1; circled = ' '; do j = 1 to length (circle); if substr(circle,j,1) = 'O' then do; substr(circled,k,1) = substr(word,j,1); substr(wurd,j,1) = upcase(substr(wurd,j,1)); k + 1; end; end; OUTPUT; c l a t h e * * O O * O c h a l e t circled=alt wurd=chALeT

  23. WORK.UNJUMBLE 1211 = 2 combinations

  24. WORK.POOL create table pool as select a.circled as A, b.circled as B , c.circled as C, d.circled as D , a.wurd as _A, b.wurd as _B , c.wurd as _C, d.wurd as _D from unjumble as a, unjumble as b , unjumble as c, unjumble as d where a._i = 1 and b._i = 2 and c._i = 3 and d._i = 4 ;

  25. Finding the Answer • Permute pool • ALLPERM ? • 12 letter pool = 479,001,600 perms • Lexicographic ordering • Permutation f precedes a permutation g in the lexicographic (alphabetic) order iff for the minimum value of k such that f(k) g(k), we have f(k) < g(k).

  26. Lexico-what? • Ordered progression • Avoid unnecessary checks • Example • iterator arrives at 1-3-2-4-5 • dictionary says no 1-3’s • advance to nextperm 1-4-x-x-x

  27. Next Perm i j • From right • find i where f ( i-1 ) < f ( i ) • From i+1 • find j where f ( j ) < f ( i-1 ) • Swap • f ( i-1 ) and f ( j - 1 ) • Reverse • from i to end 1 - 5 - 4 - 3 - 2 swap 2 - 5 - 4 - 3 - 1 reverse 2 - 1 - 4 - 3 - 5 2 - 1 - 3 - 4 - 5

  28. NEXTPERM next_perm: i = 12; do while (i > 1); if (indx[i-1] <= indx[i]) then leave; i + (-1); end; if i = 1 then return; j = i + 1; do while (j <= 12); if (indx[i-1] >= indx[j]) then leave; j + 1; end;

  29. NEXTPERM * swap ; ix1 = i-1; ix2 = j-1; h = indx[ix1]; indx[ix1] = indx[ix2]; indx[ix2] = h; * reverse v[i..n] by swapping; ix1 = i; ix2 = 12; do while (ix1 < ix2); h = indx[ix1]; indx[ix1] = indx[ix2]; indx[ix2] = h; ix1 + 1; ix2 + (-1); end;

  30. Letter Pool • POOL_0 • Original letters • POOL • Letters ordered according to current permutation • Mapping • Pool_0 to Pool

  31. Filling the Pool array circles [4] $6 a b c d; ix = 1; do i = 1 to dim(circles); do j = 1 to length (circles[i]); pool0[ix] = substr (circles[i],j,1); pool [ix] = pool0[ix]; indx [ix] = ix; ix + 1; end; end;

  32. Mapping * map items that were permuted; if i > 1 then do ix = i-1 to dim(pool); pool [ ix ] = pool0 [ indx [ ix ] ] ; end; return;

  33. Dead Ends • 12 letters • s n a a e s u g t a l t • No words start with “snaa” • Can skip remaining sequence of 8! permutations that start with “snaa”

  34. Short Cut • Word not in dictionary • Find shortest prefix that also isn’t • Sort after prefix • Compute next permutation

  35. Prefix Dictionary * hash for dictionary of word prefixes; declare hash part (); part.defineKey ("length", "count", "prefix"); part.defineDone (); * ... For each word added to dictionary ...; * add word prefixes to word prefix dictionary; length = length(word); do count = 2 to length-1; prefix = substr(word,1,count); if part.check() eq 0 then continue; part.add(); end;

  36. Word Tests word=peekclong(addrlong(pool(p)),length); if (dict.check() ne 0) then do; * word not found, find smallest prefix * not in prefix dictionary; do count = 2 to length-1; prefix = substr(word,1,count); if part.check() ne 0 then leave; end;

  37. Last Perm of Tail • Sort the mapping indices • Descending order • Method • Index Testing • Not Quicksort

  38. Tail Sort array map[12]; call missing (of map[*]); LEFT = p + count; RIGHT = 12; do ix = LEFT to RIGHT; map [ indx [ ix ] ] = 1; end; j = 12; do ix = 1 to 12 while (j >= LEFT); if not map[ ix ] > 0 then continue; indx [ j ] = ix; j = j - 1; end;

  39. Word Found • Two cases • Last word of answer • Output • Proceed using next perm • Not last word • Continue using same perm

  40. Successes if (q = 2) then do; if (soln.check() ne 0) then do; soln.add(); put 'NOTE: ' words[*]; end; words[q] = ' '; end; else do; * advance p to next word place; q + 1; p + length; length = wordlens[q]; CONTINUE; * return to top of loop; end;

  41. Fallback • Word construction • starts at position p • Permutation • altered indices prior to p • search space exhausted • Response • reduce p to prior start points

  42. Backing Up do while ((i <= p) and (i > 1)) ; q = q - 1; words[q]=''; length = wordlens[q]; p = p - length; end;

  43. Answer is: SESUG ATLANTA Paper, Slides, and Code available at http://www.devenezia.com/papers

  44. About the Author Richard A. DeVenezia Independent Consultant 9949 East Steuben Road Remsen, NY 13438 (315) 831-8802 http://www.devenezia.com/contact.php

More Related