Google Mail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Message from discussion a golden oldie challenge: Eliza
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Follow-up To:
Add Cc | Add Follow-up to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers that you hear
 
William James  
View profile   Translate to Translated (View Original)
 More options 22 Feb 2008, 22:09
Newsgroups: comp.lang.lisp, comp.lang.functional
From: William James <w_a_x_...@yahoo.com>
Date: Fri, 22 Feb 2008 14:09:58 -0800 (PST)
Local: Fri 22 Feb 2008 22:09
Subject: Re: a golden oldie challenge: Eliza
On Feb 22, 5:59 am, Mark Tarver <dr.mtar...@ukonline.co.uk> wrote:

> On 22 Feb, 11:49, Mark Tarver <dr.mtar...@ukonline.co.uk> wrote:

> > Having got 3936 LOC through a 4000 LOC implementation, I thought I'd
> > do some recreational
> > hacking and do an old old program I've not looked at for some time -
> > Eliza.   You all know Eliza well enough for me not to have to spell it
> > out.  The challenge is to implement or dig up an Eliza program (you
> > don't have to write it yourself) in your favourite FPL.  Note that the
> > script that drives Eliza's responses should not be counted towards the
> > LOC count.  Some constraints.

> > 1.  The script itself should be changeable by any novice.  That is to
> > say that it should not
> >      be a pile of hard-wired code written in the native language of
> > the program or require
> >      deep programming skills.

> > 2.  The program should receive keyboard input from the user -
> > including the usual punctuation
> >      and any characters he wants to enter without crashing.

> > During the Harrop Wars on comp.lang.lisp a lot of stuff was thrown
> > around about the desirability of pattern matching.  The challenge is
> > interesting because it involves a style of pattern-matching called
> > 'segment pattern matching' that is not hard-wired into most FPLs and
> > I'd like to see how well different FPLs cope with something outside
> > the standard.

> > Oh last thing; don't get too uptight about this.  It's only a bit of
> > fun.

> > Mark

> Well here is my shot at it in Qi.  Total LOC excluding script is 70
> LOC.

I added some features and wrote it in Ruby.

Sample session:

? Hi. I'm going to be your worst nightmare.
Why are you going to be my worst nightmare?
? I think you're full of it.
Why do you think I am full of it?
? My mother told me so.
Tell me about your mother.
? No. You tell me about yours.
We're talking about you, not me.
? You're obviously retarded.
Please don't be so personal.
? Damn your eyes!
I'm not sure that I understand you fully.
? Understand a kick in the pants?
Can you elaborate on that?
? I always ignore idiots.
Why do you always ignore idiots?
? I am afraid of dinosaurs.
Have you always been afraid of dinosaurs?
? quit

Script =
  [[:x, ["father",'mother','brother','sister'], :y],
    ["Tell me about your ", :_, "."]],
  [[:x, ["am", "i'm"], :y], [["Why are you", :y, "?"],
                             ["Have you always been", :y, "?"]]],
  [[:x, "I", :y], ["Why do you", :y, "?"]],
  [[:x, 'you', :y], [["We're talking about you, not me."],
             ["Please don't be so personal."]]],
  [[:x], [["That's very interesting. Do go on."],
        ["Tell me more."],
        ["I'm not sure that I understand you fully."],
        ["Can you elaborate on that?"] ]]

def change_person s
  h = { 'I','you',  'my','your', 'myself','yourself',
    'you are','I am', "you're", 'I am' }
  tmp = s.scan(/you are|you're|\w+|\W+/).map{|s|
    h[s] or h.invert[s] or s }
  tmp[-1] = "me"  if "I" == tmp[-1]
  tmp.join
end

patterns, symbols, replies = [], [], []

Script.each{|ary|
  syms = []
  patterns <<  Regexp.new( "^" +
    ary[0].map{|x|
      case x
        when Symbol
          syms << x
          "(.*?)"
        when String
          "\\b#{ x }\\b"
        when Array
          syms << :_
          "\\b(#{ x.join('|') })\\b"
        else
          ".*?"
      end
    }.join + "$", true ) # Case-insensitive.
  symbols << syms
  ary[1] = ary[1].sort_by{ rand }  if ary[1][0].is_a? Array
  replies << ary[1]

}

while true
  print "? "
  resp = gets.strip.sub(/[.!?,;]+$/, "")
  break if 'quit' == resp
  patterns.each_with_index{|pat,i|
    if match_data = resp.match( pat )
      reply = replies[i]
      if reply[0].is_a? Array
        # Rotate replies for variety.
        reply.push( reply.shift )
        reply = reply[0]
      end
      captures = match_data.captures.map{|s| change_person s}
      # Create associative array mapping symbols to values.
      t = Hash[ *symbols[i].zip( captures ).flatten ]
      puts reply.map{|x| x.is_a?(Symbol) ? t[x] : x }.join
      break
    end
  }
end

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message, you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google