From: Frank Buss
Subject: word puzzle
Date: 
Message-ID: <147wcu7o75vk1.1vw4itgkbl3ex$.dlg@40tude.net>
A challenge for recreation: Write a program, which creates a useful
sentence with all 26 characters, e.g.:

"the quick brown fox jumps over the lazy dog"

"Ein jedes Zebra will viel Pfirsichyoghurt mit extra Quark"

You can test it with this function:

(defun missing (string)
  (coerce
   (loop with lower = (string-downcase string)
         for c from (char-code #\a) to (char-code #\z)
         unless (find (code-char c) lower) collect (code-char c))
   'string))

This function returns the missing characters for a valid sentence.

Is it possible to construct such a sentence, where each character is used
only once (not counting spaces)?

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de

From: Wade Humeniuk
Subject: Re: word puzzle
Date: 
Message-ID: <qsPCf.140924$6K2.27603@edtnps90>
Frank Buss wrote:
> A challenge for recreation: Write a program, which creates a useful
> sentence with all 26 characters, e.g.:
> 
> "the quick brown fox jumps over the lazy dog"
> 
> "Ein jedes Zebra will viel Pfirsichyoghurt mit extra Quark"
> 
> You can test it with this function:
> 
> (defun missing (string)
>   (coerce
>    (loop with lower = (string-downcase string)
>          for c from (char-code #\a) to (char-code #\z)
>          unless (find (code-char c) lower) collect (code-char c))
>    'string))
> 
> This function returns the missing characters for a valid sentence.
> 
> Is it possible to construct such a sentence, where each character is used
> only once (not counting spaces)?
> 

Where is the dictionary and does the sentence have to be grammatically
correct (but still can contain nonsense)?

Wade
From: Frank Buss
Subject: Re: word puzzle
Date: 
Message-ID: <1x4ephuga0li7.2lgk0w0zbzw0.dlg@40tude.net>
Wade Humeniuk wrote:

> Where is the dictionary and does the sentence have to be grammatically
> correct (but still can contain nonsense)?

I don't have a dictionary. We need a dictionary where each word has
attributes like that it is an adjective, noun etc. With "useful" I meant
grammtically and spelled correctly. But creating a Lisp program, which can
create non-nonsense sentences from a dictionary, like in the link from
Jens, is impossible, isn't it? Even for a human like me it was difficult to
create at least a nonsense sentence in German. But perhaps an interactive
solution, where the computer helps finding the next best word of a given
sentence, could help.

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Alexander Schmolck
Subject: Re: word puzzle
Date: 
Message-ID: <yfsmzhgav9x.fsf@oc.ex.ac.uk>
Frank Buss <··@frank-buss.de> writes:

> I don't have a dictionary. We need a dictionary where each word has
> attributes like that it is an adjective, noun etc. 

You might want to consider wordnet.

'as
From: Frank Buss
Subject: Re: word puzzle
Date: 
Message-ID: <1ij1aotbmseaa.1ri3g51mnyeni$.dlg@40tude.net>
Alexander Schmolck wrote:

> You might want to consider wordnet.

Do you mean http://wordnet.princeton.edu/ ? Nice, but not many words.
Perhaps a program which prints all possible combinations for perfect
pangrams from the ispell dictionary at
http://prdownloads.sourceforge.net/wordlist/ispell-enwl-3.1.20.zip would be
a good start.

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Alexander Schmolck
Subject: Re: word puzzle
Date: 
Message-ID: <yfshd7mbvlm.fsf@oc.ex.ac.uk>
Frank Buss <··@frank-buss.de> writes:

> Alexander Schmolck wrote:
> 
> > You might want to consider wordnet.
> 
> Do you mean http://wordnet.princeton.edu/ ? Nice, but not many words.

10^5 (or so) are not enough? (you might want to get a list of pronouns from
somewhere, though). BTW, there also used to be a lisp binding somewhere.

> Perhaps a program which prints all possible combinations for perfect
> pangrams from the ispell dictionary at
> http://prdownloads.sourceforge.net/wordlist/ispell-enwl-3.1.20.zip would be
> a good start.

Hmm, didn't you want to generate grammatical sentences?

'as
From: Frank Buss
Subject: Re: word puzzle
Date: 
Message-ID: <1tklkpi1e2ivn$.12pyskj8gib69.dlg@40tude.net>
Alexander Schmolck wrote:

> Hmm, didn't you want to generate grammatical sentences?

yes, but my idea was that there are not many possible combinations and that
I can sort out the right ones. I've written a simple search program, but it
is too slow, no result after some hours calculating.

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Andrew Philpot
Subject: Re: word puzzle
Date: 
Message-ID: <slrndtsq9a.1pf.philpot@blombos.isi.edu>
In article <···············@oc.ex.ac.uk>, Alexander Schmolck wrote:
> Frank Buss <··@frank-buss.de> writes:
> 
>> Alexander Schmolck wrote:
>> 
>> > You might want to consider wordnet.
>> 
>> Do you mean http://wordnet.princeton.edu/ ? Nice, but not many words.
> 
> 10^5 (or so) are not enough? (you might want to get a list of pronouns from
> somewhere, though). BTW, there also used to be a lisp binding somewhere.

WordNet has only open-class words (noun, verb, adjective, adverb).
It's not hard to find lists of closed class words elsewhere on the
web.

I use Mark Nahabedian's binding to WordNet and have updated it to
handle significant changes to WN since the package was originally
developed.  There is another binding by Wheeler Ruml, which I think I
found to be less complete.

http://www.isi.edu/philpot/wordnet/WORDNET-NAHA.tar.gz

Also I added my utilities for WordNet in that directory

http://www.isi.edu/philpot/wordnet/WORDNET-NAHA.tar.gz

Andrew
From: Jens Axel Søgaard
Subject: Re: word puzzle
Date: 
Message-ID: <43dbc375$0$38720$edfadb0f@dread12.news.tele.dk>
Frank Buss wrote:
> A challenge for recreation: Write a program, which creates a useful
> sentence with all 26 characters, e.g.:
...
> Is it possible to construct such a sentence, where each character is used
> only once (not counting spaces)?

It is quite a challenge to make a "useful" sentence.

Birger Nielsen has some nice ones for danish, swedish, german and
french.

     <http://www.246.dk/ordliste.html>

-- 
Jens Axel S�gaard
From: Jens Axel Søgaard
Subject: Re: word puzzle
Date: 
Message-ID: <43dbc5e7$0$38703$edfadb0f@dread12.news.tele.dk>
Jens Axel S�gaard wrote:

Brw - the danish solution

   "H�j bly gom vandt fr�k sexquiz p� wc"

has no extra characters. It means

   "Tall, shy bridegroom won bold sex quiz on wc"

-- 
Jens Axel S�gaard
From: Coby Beck
Subject: Re: word puzzle
Date: 
Message-ID: <NLQCf.154254$km.29836@edtnps89>
"Jens Axel S�gaard" <······@soegaard.net> wrote in message 
······························@dread12.news.tele.dk...
> Frank Buss wrote:
>> A challenge for recreation: Write a program, which creates a useful
>> sentence with all 26 characters, e.g.:
> ...
>> Is it possible to construct such a sentence, where each character is used
>> only once (not counting spaces)?
>
> It is quite a challenge to make a "useful" sentence.
>
> Birger Nielsen has some nice ones for danish, swedish, german and
> french.

Too many E's ... oh never mind...

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: word puzzle
Date: 
Message-ID: <87d5ibc3t0.fsf@qrnik.zagroda>
Jens Axel S�gaard <······@soegaard.net> writes:

>> Is it possible to construct such a sentence, where each character is used
>> only once (not counting spaces)?
>
> It is quite a challenge to make a "useful" sentence.
>
> Birger Nielsen has some nice ones for danish, swedish, german and
> french.
>
>      <http://www.246.dk/ordliste.html>

Here are pangrams in various languages:
http://en.wikipedia.org/wiki/Pangram

It's hard to construct a sensible perfect pangram in English,
compared to some other languages.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: Frank Buss
Subject: Re: word puzzle
Date: 
Message-ID: <1gbk5dtstlahb$.1a7i449ncfoky.dlg@40tude.net>
Frank Buss wrote:

> A challenge for recreation: Write a program, which creates a useful
> sentence with all 26 characters

BTW: this is called a pangram: http://en.wikipedia.org/wiki/Pangram

For German there is no perfect pangram known (each character occurs exactly
once) and the English ones are using obscure words, so you can become
famous when finding one :-)

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: ······@corporate-world.lisp.de
Subject: Re: word puzzle
Date: 
Message-ID: <1138551503.917705.11130@g44g2000cwa.googlegroups.com>
Stefan Ram wrote:
> ( defun generate ()
>   ( apply #'noun-plus-fverb
>     ( list
>       ( generate0 )
>       ( generate-a-verb ))))

...

>   The next step should be cleaning up the code.

First: How about formatting the code in the usual style without the
extra spaces?

Instead of:

( defun generate ()
  ( apply #'noun-plus-fverb
    ( list
      ( generate0 )
      ( generate-a-verb ))))

See this:

(defun generate ()
  (apply #'noun-plus-fverb
         (list (generate0)
               (generate-a-verb))))

Second: how about adding some documentation?

(defun generate ()
 "The function GENERATE does FOO, expects BAR and returns BAZ."
  (apply #'noun-plus-fverb
         (list (generate0)
               (generate-a-verb))))

Third:

Instead:

(defun generate ()
  (apply #'noun-plus-fverb
         (list (generate0)
               (generate-a-verb))))


Why not:

(defun generate ()
  (noun-plus-fverb (generate0) (generate-a-verb)))
From: André Thieme
Subject: Re: word puzzle
Date: 
Message-ID: <1138579960.220989.96880@g44g2000cwa.googlegroups.com>
Stefan Ram schrieb:

> ( defun generate0 ()
>   ( apply #'det-plus-noun
>     ( list
>       ( generate-a-sentence-start )
>       ( generate-a-sentence-continuation ))))
>
> ( defun generate ()
>   ( apply #'noun-plus-fverb
>     ( list
>       ( generate0 )
>       ( generate-a-verb ))))
>
> ( defun generate-case ()
>   ( let (( sentence ( first( generate ))))
>     ( if sentence( string-capitalize sentence :END 1 ))))

>   The next step should be cleaning up the code.

To come a bit closer to how Lisp code should look like copy a function
and type at the repl:
(pprint '
This won't always yield to a perfect look but it would make your code
much more readable.
Anthoer thing: if your IF has an empty else-clause you can use WHEN:
(if sentence
    (string-capitalize sentence :END 1))

becomes

(when sentence
  (string-capitalize sentence :END 1))


André
--
From: Pascal Bourguignon
Subject: Re: word puzzle
Date: 
Message-ID: <8764o3rqrw.fsf@thalassa.informatimago.com>
···@zedat.fu-berlin.de (Stefan Ram) writes:
> ( defun generate-a-sentence-continuation ()
>   ( nth( random 8 )
>     ( list
>       ( list "man"     ( list "ch" ))
>       ( list "aunt"    ( list "Ch" ))
>       ( list "car"     ( list "cH" ))
>       ( list "auto"    ( list "CH" ))
>       ( list "men"     ( list "ph" ))
>       ( list "aunts"   ( list "ph" ))
>       ( list "cars"    ( list "pH" ))
>       ( list "autos"   ( list "pH" )))))
       
 
Instead of strings you can use symbols here.  all, you're writing a
program in Lisp & Intelligent SYMBOLIC Processing language.

Also, since this is literal data, that you don't plan to modify, you
can use quote:

(defun generate-a-sentence-continuation ()
  (choose-one-of
     '(("man"    (ch))
       ("aunt"   (cch))  ; assuming case is significant, since you used string=
       ("car"    (chh))  ; not that I understand your coding.
       ("auto"   (cchh)) ; also since it seems you're encoding several
       ("men"    (ph))   ; orthogonal properties, you could put them
       ("aunts"  (ph))   ; separately in the list.
       ("cars"   (phh)) 
       ("autos"  (phh)))))

I would use for example: singular, plural, animed, inanimed, etc and write:

  ("man"    (singular animed))
  ("aunt"   (singular animed))
  ("car"    (singular inanimed))
  ("auto"   (singular inanimed))
  ("men"    (plural   animed))
  ("aunts"  (plural   animed))
  ("cars"   (plural   inanimed))
  ("autos"  (plural   inanimed))

etc.

Then the tests are greatly simplified: (member 'plural attributes)
instead of (or (string= "pH" attributes) (string== "ph" attributes)) etc...


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

CAUTION: The mass of this product contains the energy equivalent of
85 million tons of TNT per net ounce of weight.
From: Pascal Bourguignon
Subject: Re: word puzzle
Date: 
Message-ID: <87bqxrsxj8.fsf@thalassa.informatimago.com>
···@zedat.fu-berlin.de (Stefan Ram) writes:

> ···@zedat.fu-berlin.de (Stefan Ram) writes:
>>>("car" (chh))  ; not that I understand your coding.
>>Thank you! My plan for the next step is a code cleanup anyway,
>>and so I will take your suggestions into consideration.
>
>   OK. The previous notation was not very readable. This was
>   related to me not fully understanding what I read in the book.
>   Now, I have tried to write the lexicon using notions which I
>   understand:
>
> ( setf lexicon 
>   ( vector 
>     ( list 
>       :text "the"
>       :description 
>       ( list 
>         :isa 'determiner 
>         :number 'singular ))
>     ( list 
>       :text "man"
>       :description 
>       ( list 
>         :isa 'noun 
>         :number 'singular 
>         :firstsound 'consonant 
>         :meaning 'human  ))
>     ( list 
>       :text "walks"
>       :description 
>       ( list 
>         :isa 'verb
>         :needs ( list :isa 'noun-phrase :number 'singular :person '3 )))))


Sine all the data is literal, you don't need to build new lists and
vector at run-time: you can let the reader do it for you.  If you plan
to modify these lists or vector, you can always copy-tree them...

(setf lexicon 
   #((:text "the" :description (:isa determiner :number singular))
     (:text "man" 
      :description (:isa noun :number singular 
                    :firstsound consonant :meaning human))
     (:text "walks" 
      :description (:isa verb 
                    :needs (:isa noun-phrase :number singular 
                    :person 3)))))

A nice property of this form is that you can put it in a data file and
read it as is:

--------------------(words.data)-------------------------------------
(:text "the" :description (:isa determiner :number singular))

(:text "man" 
 :description (:isa noun :number singular 
                    :firstsound consonant :meaning human))
(:text "walks" 
 :description (:isa verb 
               :needs (:isa noun-phrase :number singular :person 3))))
---------------------------------------------------------------------

(setf lexicon
  (with-open-file (file "word.data")
    (let ((*read-eval* nil))
      (loop with lex = (make-array 0 :adjustable t)
            for word = (read file nil nil)
            while word
            do (vector-push-extend word lex)
            finally (return lex)))))


>   To select one determiner at random from the above lexicon, I
>   append their index to a list called "buffer" and then I choose
>   one of the elements from this buffer. However, I remember
>   having read that "progn" is no good style. So comments are
>   welcome.

It's not that it's no good style, it's that it's useless.  
Read clhs defun


> ( defun choose-one-of( list )
>   ( nth( random( length list )) list ))
>
> ( defun select( type )
>   "select a word from the lexicon matching the given type"
>   ( progn
>     ( setf buffer '() )

You haven't declared the global variable buffer.
Or is it a local variable?  Then use LET:

   (let ((buffer '())) 
      ...)

>     ( dotimes( i( array-dimension lexicon 0 )) 

You really need to see a parentheses doctor!
Warning, this is probably the last answer you'll get from this
newsgroup if you continue with this parenthesis spacing...


>       ( setq entry ( aref lexicon i ))


(loop for entry across lexicon
      do ...

>       ( setq text ( getf entry :text ))
>       ( setq description ( getf entry :description ))
>       ( setq entrytype ( getf description :isa ))

You'd need to introduce some abstraction here.  GETF is low level.
You might want to change the representation and use structures or CLOS
objects.  So instead of these GETF, use accessor functions:

(defmacro define-getf-accessor (name &optional (keyword name))
   `(progn
        (defun ,name (object) 
            (getf object ,keyword))
        (defun (setf ,name) (value object) 
            (setf (getf object  ,keyword) value))))
(define-getf-accessor lexeme-text            :text)
(define-getf-accessor lexeme-description     :description)
(define-getf-accessor description-type :isa)

Then:

    (let* ((text (lexeme-text entry))
           (desc (lexeme-description entry))
           (type (description-type desc)))
        ...)

>       ( if ( equal type entrytype )
>         ( setf buffer ( append buffer ( list i )))))
                          ^^^^^^
                          O(n�)

Use PUSH and if you mind the order, lateru NREVERSE.

Inside LOOP, you can merely use COLLECT.

>     ( aref lexicon ( choose-one-of buffer ))))

>   I have tested this using a loop:
>
> ( loop repeat 7 do ( print ( getf ( sentence-start ) :text )))
>
>   And it finds determiners, indeed, from a lexicon slightly
>   larger that the one above:
>
> "some"
> "some"
> "all"
> "a"
> "a"
> "the"
> "several"
>

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

WARNING: This product attracts every other piece of matter in the
universe, including the products of other manufacturers, with a
force proportional to the product of the masses and inversely
proportional to the distance between them.