{"id":201,"date":"2004-06-10T19:42:22","date_gmt":"2004-06-10T17:42:22","guid":{"rendered":"http:\/\/blogs.bl0rg.net\/neingeist-neu\/2004\/06\/10\/add-a-gram\/"},"modified":"2006-10-10T03:43:11","modified_gmt":"2006-10-10T01:43:11","slug":"add-a-gram","status":"publish","type":"post","link":"https:\/\/blogs.bl0rg.net\/neingeist\/2004\/06\/10\/add-a-gram\/","title":{"rendered":"Add-A-Gram"},"content":{"rendered":"<p>Another toy problem from the <a href=\"http:\/\/www.itasoftware.com\/careers\/programmers-archive.php\">ITA software page<\/a> is the Add-A-Gram:<\/p>\n<p><em><br \/>\nAn &#8220;add-a-gram&#8221;<br \/>\nis a sequence of words formed by starting with a 3-letter word, adding<br \/>\na letter and rearranging to form a 4-letter word, and so on. For example,<br \/>\nhere are add-a-grams of the words &#8220;CREDENTIALS&#8221; and &#8220;ANACHRONISM&#8221;:<\/em><\/p>\n<p><em>      ail + s =<br \/>\nsail + n =<br \/>\nnails + e = <\/em><\/p>\n<p><em>      aliens + t =<br \/>\nsalient + r =<br \/>\nentrails + c =<br \/>\nclarinets + e =<br \/>\ninterlaces + d =<br \/>\nCREDENTIALS (length 11)<\/em><\/p>\n<p><em>(&#8230;) given the dictionary found<br \/>\n<a href=\"http:\/\/www.itasoftware.com\/careers\/WORD.LST\">here (1.66MB)<\/a>, what is the longest add-a-gram?<br \/>\n<\/em><\/p>\n<p>Running my code to get the longst add-a-gram is left as an exercise to the reader \ud83d\ude09 I also did some basic performance testing and compared the results<br \/>\nof my Lisp version to those of the versions on the site in<br \/>\n<a href=\"http:\/\/www.itasoftware.com\/careers\/solutions\/addagram\/addagram.pl\">Perl<\/a><br \/>\nand <a href=\"http:\/\/www.itasoftware.com\/careers\/solutions\/addagram\/addagram.py\">Python<\/a>.  Looks like Lisp isn&#8217;t so slow after all. Timings and Lisp code follow:<br \/>\n<!--more--><\/p>\n<pre>;; CMUCL:       $ time lisp -eval '(compile-file \"add-a-gram.lisp\")' -eval '(load \"add-a-gram.x86f\")' -eval '(run)' -eval '(quit)'\r\n;;              real    0m11.834s\r\n;; Python:      $ time .\/addagram.py WORD.LST\r\n;;              real    0m43.589s\r\n;; Perl:        $ time perl addagram.pl WORD.LST\r\n\r\n;;              real    0m17.541s\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defparametercm_defvar.html\">defvar<\/a> *wordlist* nil)\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> run ()\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/speope_letcm_letst.html\">let<\/a> ((best-word \"\"))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/spefor_setq.html\">setq<\/a> *wordlist* (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_make-hash-table.html\">make-hash-table<\/a> :test 'equal))\r\n(read-file \"WORD.LST\")\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_maphash.html\">maphash<\/a> #'(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/sym_lambda.html\">lambda<\/a> (sorted-word word)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/speope_if.html\">if<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">&gt;<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_length.html\">length<\/a> word) (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_length.html\">length<\/a> best-word))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/speope_if.html\">if<\/a> (add-a-gram-p sorted-word)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/stagenfun_doc_umentationcp.html\">setf<\/a> best-word sorted-word)))) *wordlist*)\r\n(show-result best-word)))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> read-file (arg-file-name)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/speope_letcm_letst.html\">let<\/a> ((line nil))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_with-open-file.html\">with-open-file<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/syscla_stream.html\">stream<\/a> arg-file-name :direction :input)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_loop.html\">loop<\/a> while (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/spefor_setq.html\">setq<\/a> line (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_read-line.html\">read-line<\/a> stream nil)) do\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_whencm_unless.html\">unless<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\"> (<\/a><a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_length.html\">length<\/a> line) 3)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/stagenfun_doc_umentationcp.html\">setf<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_gethash.html\">gethash<\/a> (sort-word line) *wordlist*) line))))))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> add-a-gram-p (sorted-word)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/speope_letcm_letst.html\">let<\/a> ((foo nil))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_cond.html\">cond<\/a> ((<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">=<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_length.html\">length<\/a> sorted-word) 3) (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_gethash.html\">gethash<\/a> sorted-word *wordlist*))\r\n((<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/syscla_null.html\">null<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_gethash.html\">gethash<\/a> sorted-word *wordlist*)) nil)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/stagenfun_doc_umentationcp.html\">t<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/stagenfun_doc_umentationcp.html\">setf<\/a> foo (remove-one-char sorted-word))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_loop.html\">loop<\/a> until (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/typspe_or.html\">or<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/syscla_null.html\">null<\/a> foo) (add-a-gram-p (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">car<\/a> foo)))\r\ndo (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/stagenfun_doc_umentationcp.html\">setf<\/a> foo (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">cdr<\/a> foo)))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_carcm_cdr_darcm_cddddr.html\">car<\/a> foo)))))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> remove-one-char (word)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/speope_letcm_letst.html\">let<\/a> ((foo nil))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_loop.html\">loop<\/a> for k from 1 to (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_length.html\">length<\/a> word) do\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_push.html\">push<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_concatenate.html\">concatenate<\/a> 'string\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_subseq.html\">subseq<\/a> word 0 (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_1plcm_1-.html\">1-<\/a> k))\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_subseq.html\">subseq<\/a> word k (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_length.html\">length<\/a> word))) foo))\r\nfoo))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> sort-word (word)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_concatenate.html\">concatenate<\/a> 'string (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_sortcm_stable-sort.html\">sort<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_coerce.html\">coerce<\/a> word 'list) #'char&lt;)))\r\n\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_defun.html\">defun<\/a> show-result (sorted-word)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/mac_cond.html\">cond<\/a> ((<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_eqcm_sleq__lteqcm_gteq.html\">=<\/a> (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_length.html\">length<\/a> sorted-word) 3)\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_format.html\">format<\/a> t \"~A~%\" (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_gethash.html\">gethash<\/a> sorted-word *wordlist*)) )\r\n(<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/stagenfun_doc_umentationcp.html\">t<\/a>             (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/fun_format.html\">format<\/a> t \"~A~%\" (<a href=\"http:\/\/www.lisp.org\/HyperSpec\/Body\/acc_gethash.html\">gethash<\/a> sorted-word *wordlist*))\r\n(show-result (add-a-gram-p sorted-word)))))<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Another toy problem from the ITA software page is the Add-A-Gram: An &#8220;add-a-gram&#8221; is a sequence of words formed by starting with a 3-letter word, adding a letter and rearranging to form a 4-letter word, and so on. For example, here are add-a-grams of the words &#8220;CREDENTIALS&#8221; and &#8220;ANACHRONISM&#8221;: ail + s = sail + [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[14],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/posts\/201"}],"collection":[{"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/comments?post=201"}],"version-history":[{"count":0,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/posts\/201\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/media?parent=201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/categories?post=201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.bl0rg.net\/neingeist\/wp-json\/wp\/v2\/tags?post=201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}