doctor() =>    '  '
	where write('tty', '     hi! use lowercase and no punctuation and end session with carriage return' , '\n');
		x = talkg(script()).
 
talkg(scr) => if null(x) then write(TTY, 'your bill is in the mail!', '\n')
	   else talk2g(x, scr) 
		where x = read(line, TTY).

talk2g(x, scr) => talkg(scr) where y = doc(x, scr);
			   write(TTY, '    ');
			   writelist(y) = true.

doc(stmt,scr) => parse(scan(stmt, scr), edit(stmt, changes())).

/***************** Editing phase *********************/

edit([], chlist) => [].
edit([h|t], chlist) => if eq(ass, NOTFOUND) then cons(h, edit(t, chlist))
			   else cons(ass, edit(t, chlist))
				where ass = assoc2(chlist, h).
assoc2([], x) 	      => NOTFOUND.
assoc2([[a|b]|t], x)  => if eq(a,x) then b else assoc2(t, x). 

scan(stmt, script) => scan2(stmt, [0], script).

scan2([], [a|b], scr) => if eq(a,0) then 
				(t where [h|t] = searchkey(scr, 'NONE')) 
			 else b. 

scan2([h|t], answer, scr) => scan3([h|t], answer, searchkey(scr, h), scr).

scan3(stmt, answer, next, scr) => 
		if greaterp(nxt,ans) then scan2(t1, next, scr)
		else scan2(t1, answer, scr)
		where stmt = [st | t1]; answer = [ans | t2]; next = [nxt | t3].

searchkey([], word) => [0].
searchkey([[word2|weightandrules] | restscr], word) =>
		if eq(word, word2) then weightandrules 
		else searchkey(restscr, word).
		
writelist([])    => true 	 where write(TTY, '\n').
writelist([h|t]) => writelist(t) where write(TTY, h).


/****************   Parsing phase ******************/

parse(pat, stmt) => parse2(pat, stmt, dec)
				where pat = [[a|b]|t];
				      dec <- decompose(a, stmt, []).
	/* Here, `where' is better than a pattern on the argument */

parse2([h1|t1], st, [h2|t2]) => if null(t2) then parse(t1, st)
			        else reassemble(h2, cdrh1)
					where h1 = [carh1 | cdrh1].
	/* Here, `cdr' is useful */

		/**** Decomposition ****/
decompose([], stmt, result) => [true | result].
decompose([0|x], stmt, result) => 
	if null(x) then [app(result, [stmt]) | true]
	else (decomp2(find(stmt, h, []), [0|x], result)
			where x = [h|t]).

decompose([w1|p1], [w2|s1], result) =>
	if eq(w1, w2) then decompose(p1, s1, app(result, [[w1]]))
	else [[] | []].

decomp2([[]|t], pat, result) => [[] | []].
decomp2([h|[j|[k|f1]]], [a|[b|p1]], result) =>
	decompose(p1, k, app(result, [[j], [b]])).

find([], word, result) => [[]].
find([word1|s1], word, result) => 
	if eq(word1,word) then [true, result, s1] 
	else find(s1, word, app(result, [word1])).

app([], x) => x.
app([h|t], y) => cons(h, app(t, y)).

		/**** Reassembly ****/

reassemble(phrases, rules) => 
	substitute(choose(rand(length(rules)), rules), phrases, []).

substitute([], phrases, result) => result.
substitute([h|r1], phrases, result) => 
	if numberp(h) 
	then substitute(r1, phrases, app(result, choose(h,phrases)))
	else substitute(r1, phrases, app(result, [h])).

choose(n, [h|rest]) => if eq(n,1) then h else choose(n-1,rest).

length([]) => 0.
length([h|t]) => 1+length(t).

rand(n) => 1 + (cputime mod n).

/*************************** Change list *************************/

changes() =>
  [ [ 'am' | 'are' ],
    [ 'i' | 'you' ],
    [ 'im' | 'youre' ],
    [ 'me' | 'you' ],
    [ 'mine' | 'yours' ],
    [ 'my' | 'your' ],
    [ 'myself' | 'yourself' ],
    [ 'you' | 'i' ],
    [ 'your' | 'my' ],
    [ 'yours' | 'mine' ],
    [ 'youre' | 'im' ],
    [ 'yourself' | 'myself' ],
    [ 'were' | 'was' ]
  ].

