; your code goes here
(in-package #:cl-user)
(defpackage #:phrase
(:use #:cl)
(:export #:word-count))
(in-package #:phrase)
(defun word-count (phrase)
(let (words word-start word-end)
(labels ((update-word ()
(let* ((word (string-downcase (subseq phrase word-start word-end)))
(count (assoc word words :test #'string-equal)))
(if (null count)
(push (cons word 1) words)
(incf (cdr count))))
(reset-word))
(reset-word ()
(setf word-start nil
word-end nil))
(has-word ()
(not (equal word-end word-start))))
(loop for c across phrase
for i = 0 then (1+ i)
if (alphanumericp c) do
(if (null word-start)
(setf word-start i
word-end (1+ i))
(incf word-end))
else if (has-word) do
(update-word)
finally
(when (has-word)
(update-word))
(return words)))))
(print (word-count "Fuck this stupid shit. Fuck!"))
OyB5b3VyIGNvZGUgZ29lcyBoZXJlCihpbi1wYWNrYWdlICM6Y2wtdXNlcikKKGRlZnBhY2thZ2UgIzpwaHJhc2UKICAoOnVzZSAjOmNsKQogICg6ZXhwb3J0ICM6d29yZC1jb3VudCkpCihpbi1wYWNrYWdlICM6cGhyYXNlKQoKKGRlZnVuIHdvcmQtY291bnQgKHBocmFzZSkKICAobGV0ICh3b3JkcyB3b3JkLXN0YXJ0IHdvcmQtZW5kKQogICAgKGxhYmVscyAoKHVwZGF0ZS13b3JkICgpCiAgICAgICAgICAgICAgIChsZXQqICgod29yZCAoc3RyaW5nLWRvd25jYXNlIChzdWJzZXEgcGhyYXNlIHdvcmQtc3RhcnQgd29yZC1lbmQpKSkKICAgICAgICAgICAgICAgICAgICAgIChjb3VudCAoYXNzb2Mgd29yZCB3b3JkcyA6dGVzdCAjJ3N0cmluZy1lcXVhbCkpKQogICAgICAgICAgICAgICAgIChpZiAobnVsbCBjb3VudCkKICAgICAgICAgICAgICAgICAgICAgKHB1c2ggKGNvbnMgd29yZCAxKSB3b3JkcykKICAgICAgICAgICAgICAgICAgICAgKGluY2YgKGNkciBjb3VudCkpKSkKICAgICAgICAgICAgICAgKHJlc2V0LXdvcmQpKQogICAgICAgICAgICAgKHJlc2V0LXdvcmQgKCkKICAgICAgICAgICAgICAgKHNldGYgd29yZC1zdGFydCBuaWwKICAgICAgICAgICAgICAgICAgICAgd29yZC1lbmQgbmlsKSkKICAgICAgICAgICAgIChoYXMtd29yZCAoKQogICAgICAgICAgICAgICAobm90IChlcXVhbCB3b3JkLWVuZCB3b3JkLXN0YXJ0KSkpKQogICAgICAobG9vcCBmb3IgYyBhY3Jvc3MgcGhyYXNlCiAgICAgICAgIGZvciBpID0gMCB0aGVuICgxKyBpKQogICAgICAgICBpZiAoYWxwaGFudW1lcmljcCBjKSBkbwogICAgICAgICAgIChpZiAobnVsbCB3b3JkLXN0YXJ0KQogICAgICAgICAgICAgICAoc2V0ZiB3b3JkLXN0YXJ0IGkKICAgICAgICAgICAgICAgICAgICAgd29yZC1lbmQgKDErIGkpKQogICAgICAgICAgICAgICAoaW5jZiB3b3JkLWVuZCkpCiAgICAgICAgIGVsc2UgaWYgKGhhcy13b3JkKSBkbwogICAgICAgICAgICh1cGRhdGUtd29yZCkKICAgICAgICAgZmluYWxseQogICAgICAgICAgICh3aGVuIChoYXMtd29yZCkKICAgICAgICAgICAgICh1cGRhdGUtd29yZCkpCiAgICAgICAgICAgKHJldHVybiB3b3JkcykpKSkpCiAgICAgICAgICAgCihwcmludCAod29yZC1jb3VudCAiRnVjayB0aGlzIHN0dXBpZCBzaGl0LiBGdWNrISIpKQ==