(defun splitStr (str)
"Appends characters from str to my-string unless the character is a space. When a space is encountered, add the current my-string to a new list."
(setq my-string "") ;; Initialize my-string as an empty global string
(setq result-list '()) ;; Initialize an empty list to store parts of the string
(setq len (length str)) ;; Get the length of the input string
(dotimes (i len)
(setq curr-char (char str i)) ;; Get the character at index `i`
(if (char/= #\Space curr-char) ;; If the character is not a space
(setq my-string (concatenate 'string my-string (string curr-char))) ;; Append character to my-string
(when (> (length my-string) 0) ;; If my-string is not empty
(push my-string result-list) ;; Add my-string to result-list
(setq my-string "")))) ;; Reset my-string to empty string
;; After the loop, add the final my-string if it's not empty
(when (> (length my-string) 0)
(push my-string result-list))
(nreverse result-list)) ;; Return the reversed list to maintain original order
;;==========================================================================
;;
;; STARTER FILE FOR CSC 4240/5240 PROGRAM #1: Eliza
;;==========================================================================
;;----------------------------------------------------------------------------
;; eliza: top-level function which, when given a sentence (no
;; punctuation, please!), comes back with a response like you would.
( defun eliza ( sentence )
;(format t "Input type: ~a, value: ~a~%" (type-of sentence) sentence)
( respond ( change-pros sentence ) database ) )
;;----------------------------------------------------------------------------
;; change-pros: changes the pronouns of the sentence so that Eliza can
;; come back with the appropriately switched first and second person
;; references.
( defun change-pros ( sentence )
( cond
( ( null sentence ) nil )
( ( equal ( car sentence ) 'you )
( cons 'I ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'I )
( cons 'you ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'my )
( cons 'your ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'your )
( cons 'my ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'mine )
( cons 'yours ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'yours )
( cons 'mine ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'he )
( cons 'him ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'him )
( cons 'he ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'she )
( cons 'she ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'her )
( cons 'hers ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'hers )
( cons 'her ( change-pros ( cdr sentence ) ) ) )
( ( equal ( car sentence ) 'it )
( cons 'it ( change-pros ( cdr sentence ) ) ) )
;; CHANGE THIS: add more cases here of pronouns or other words
;; that should flip in order for this to work well
( t ( cons ( car sentence ) ( change-pros ( cdr sentence ) ) ) ) ) )
;;----------------------------------------------------------------------------
;; respond: given a sentence, looks through the database in search of
;; a matching pattern and the response; given the database response,
;; uses 'instantiate' to fill in the blanks, and returns the completed
;; response
( defun respond ( sentence db )
( cond
;; end of DB, return nil - should never really happen
( ( null db ) nil )
;; if the result of matching the sentence against the current
;; pattern is a success, produce this response
(
( success ( setq result ( match sentence ( first ( car db ) ) ) ) )
(setf *random-state* (make-random-state t))
(setq idx ( length (car db) ))
(setq rndm ( random idx ))
(if (= rndm 0)
(setq rndm 1)
(princ ""))
; (princ rndm)
; (princ #\Newline)
( instantiate result ( nth rndm ( car db ) ) )
)
;; otherwise, keep looking through the DB
( t ( respond sentence ( cdr db ) ) ) ) )
;;----------------------------------------------------------------------------
;; match: if there is not a match between this pattern and this data,
;; returns 'fail;' otherwise, returns the sentence in partitioned
;; format
( defun match ( data pattern )
( cond
;; end of both data and pattern; a match
( ( and ( null data ) ( null pattern ) ) nil )
;; end of pattern, but not end of data; no match
( ( null pattern ) fail )
;; end of data, but not end of pattern; if the pattern starts with
;; a variable, eat it and try and match the rest of the pattern to
;; the null sentence (will only work if all variables); otherwise,
;; fail
( ( null data )
( cond
( ( variablep ( car pattern ) )
( if ( success ( setq result ( match data ( cdr pattern ) ) ) )
result
fail ) )
( t fail ) ) )
;; first item of data and pattern are identical; if the rest of it
;; matched, return the first item cons'ed with the rest of the
;; partitioned sentence; otherwise, fail
( ( equal ( car data ) ( car pattern ) )
( if ( success ( setq result ( match ( cdr data ) ( cdr pattern ) ) ) )
( cons ( list ( car data ) ) result )
fail ) )
;; first item of pattern is a variable; if the rest of the data
;; (minus the first word, matched to the variable) is a match with
;; all of the pattern, return the appropriate stuff; if all of the
;; data (variable eats nothing) matches the rest of the pattern,
;; return appropriate stuff; else, fail.
( ( variablep ( car pattern ) )
( cond
;; variable eats nothing; () is put in partitioned sentence
( ( success ( setq result ( match data ( cdr pattern ) ) ) )
( cons () result ) )
;; variable eats one word; word is cons'ed into the first
;; element of the partitioned sentence, assuming that the step
;; before an actual match word would be a ()
( ( success ( setq result ( match ( cdr data ) pattern ) ) )
( cons ( cons ( car data ) ( car result ) ) ( cdr result ) ) )
;; otherwise, fail
( t fail ) ) )
( t fail ) ) )
;;----------------------------------------------------------------------------
;; instantiate: takes a partitioned sentence and the response it has
;; been matched to and generates the appropriated completed response
( defun instantiate ( partitioned response )
( cond
( ( null response ) nil )
;; numbers indicate what part of the partitioned sentence to
;; insert into the response
( ( numberp ( car response ) )
( setq index ( - ( car response ) 1 ) )
( append ( nth index partitioned )
( instantiate partitioned ( cdr response ) ) ) )
( t ( cons ( car response )
( instantiate partitioned ( cdr response ) ) ) ) ) )
;;---------------------------------------------------------------------------
;;
;; helping functions
;;
;;---------------------------------------------------------------------------
( setq fail '-1 )
( defun success ( result )
( not ( equal result fail ) ) )
( defun variablep ( word )
( equal word '0 ) )
;;---------------------------------------------------------------------------
;;
;; database
;;
;;---------------------------------------------------------------------------
;; CHANGE THIS: add more to this database so that the interaction is
;; more interesting and communicative and so that Eliza sounds like you
;; would sound in the same conversation!
;;---------------------------------------------------------------------------
( setq database
'(
;; example greetings/farewells -- change them to sound like you
(
(Hello 0)
(Hello - have a seat and tell me how you feel today.)
)
( (0 You came here because 0)
(A lot of people come here for that reason so you are not alone.) )
((0 your day 0)
("Great! I would love to hear that, tell me how was your day?")
)
( (0 Goodbye 0)
(Goodbye - I hope you enjoyed this session.) )
;; feelings
( (0 you think 0)
(And just why do you think 4 ? ) )
( (0 you are happy 0)
(That's wonderful! What’s making you happy today? ) )
(
(0 you feel joyful 0)
("I'm glad to hear that! Tell me more what makes you feel joyful?" )
)
((0 you are excited 0)
(
"I'm glad to hear that! Tell me more what makes you feel excited?"
))
((0 password 0)
"You can reset your password if you forgot it"
)
((0 got lost 0)
"Try calling 911 or go to nearest police station! Take care!"
)
((0 missed your appointment 0)
"I know how it feels, but can you try rescheduling it?"
)
((0 laptop not working 0)
"It is frustrating to hear that.. do you have a backup of your data?"
)
((0 too much work 0)
"Try getting some rest please"
)
((0 feel tired 0)
"Why do you feel tired?"
)
((0 you feel sad 0)
("I'm sorry to hear that. Why do you think you are sad?"
"What’s making you feel sad?"
"Tell me more about what’s troubling you."))
((0 you are angry 0)
("I see. What made you feel this way?"
"Why do you think you’re feeling so angry?"
"Can you tell me more about what’s making you angry?"))
;; the catch-alls
(
(0)
(Could you expand on that?)
("Hmmm.. Is it possible to elaborate more on that please?")
("Hmmm.. I feel I didn't get what you mean. Can you explain again in other terms?")
("Uhh.. I fear I don't understand what are you talking about..")
("Ops, didn't get it, please expand on that.")
)
)
)
; (princ (eliza '(I feel joyful)))
; (princ #\Newline)
; (princ "#############")
; ; (princ inn)
; ; (princ (splitStr "I feel joy"))
; (princ res)
; (princ #\Newline)
; (princ (eliza res))
; (princ res)
;; Convert the splitStr result from strings to symbols
;; Call eliza with the list of symbols and print the result
; (princ (eliza res)
(dotimes (i 4) ; Loop 10 times with `i` from 0 to 9
(setq inn (read-line))
(setq inn-uppercase (string-upcase inn))
(print inn-uppercase)
(setq res (mapcar #'intern (splitStr inn-uppercase)))
(print (eliza res))
)