Re: a golden oldie challenge: Eliza
  Home FAQ Contact Sign in
comp.lang.functional only
 
Advanced search
POPULAR GROUPS

more...

 Up
Re: a golden oldie challenge: Eliza         

Group: comp.lang.functional · Group Profile
Author: Stevan Apter
Date: Feb 23, 2008 10:21

in q:

D:(("1 father|mother|brother|sister 2";"tell me about your 0.");
("1 am|i'm 2";"why are you 2|have you always been 2?");
("1 i 2";"why do you 2?");
("1 you 2";"we're talking about you, not me.|please don't be so personal"))

E:"|"vs"that's very interesting. do go on.|
tell me more|
i'm not sure i understand you fully|
can you elaborate on that?"

S:{(`$"|"vs first w where not b;raze w where b:(first each w:" "vs x)in"0123456789")}each D[;0]
R:"|"vs'D[;1]
P:{(y,x,z)(x,y)?z}[`$("you";"your";"yourself";"i'm";"i am");`$("i";"my";"myself";"you are";"you're")]

e:{w:(`$" "vs x except".?")except`; / words except punctuation, blanks
b:w in\:/:S[;0]; / boolean mask: words X rules
if[count[b]=i:(any each b)?1b;:E first 1?count E]; / if no key match on a rule, early exit
p:1_'(0,1+k:b[i]?1b)_`,w; / split input on key
r:{x first 1?count x}R i; / pick a rule
n:r first raze r ss/:"0123456789"; / which part of input to replace
ssr[r;n;" "sv string(),P each(w[k],p)"I"$n]} / construct reply

in k it's about half the size, but i'll spare you.

"William James" yahoo.com> wrote in message news:c4d42479-42ea-4238-afaa-72517bf00d3b@k2g2000hse.googlegroups.com...
> On Feb 22, 5:59 am, Mark Tarver ukonline.co.uk> wrote:
>> On 22 Feb, 11:49, Mark Tarver 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
no comments
diggit! del.icio.us! reddit!