|
(ns functional-tv-puzzles.-2020.ayoda-371 |
|
(:require [clojure.string :as s] |
|
[clojure.test :as t])) |
|
|
|
(defn ayoda [txt] |
|
(let [transform (fn [[beg end :as contents]] |
|
(if end |
|
[(s/capitalize end), (s/lower-case beg)] |
|
contents)) |
|
build-sentence (fn [halves] |
|
(->> halves |
|
(interpose " ") |
|
flatten |
|
(apply str))) |
|
link-sentences (fn [sentences] |
|
(->> sentences |
|
(map #(str % ".")) |
|
(interpose " ") |
|
(apply str)))] |
|
(->> (s/split txt #"\.\s*" ) |
|
(map |
|
#(->> (s/split % #",\s*") |
|
transform |
|
build-sentence)) |
|
link-sentences))) |
|
|
|
;; Single pass-through |
|
(defn ayoda-2 [txt] |
|
(let [txt (str txt " . ") ;; end-marker |
|
dot? #(re-matches #"\.\s*" %) |
|
comma? #(re-matches #",\s*" %) |
|
|
|
;; Raw text -> seq of tokens: words and separators |
|
tokenizing (comp (partition-by #(#{\space \. \,} %)) |
|
(map #(apply str %)) |
|
(map s/trim) |
|
(filter seq)) |
|
|
|
;; Tokens -> [<sentence first half str>, <second half str>], or [<single>] |
|
;; One tuple per sentence. |
|
structuring (fn [rf] |
|
(let [init-val [""] |
|
halves (atom init-val) |
|
add-word #(do (swap! halves |
|
(fn [[beg end]] |
|
(if end |
|
[beg (str end % " ")] |
|
[(str beg % " ")]))) |
|
(rf %2)) |
|
add-half #(do (swap! halves |
|
(fn [[beg]] |
|
[beg ""])) |
|
(rf %)) |
|
done #(let [v @halves] |
|
(reset! halves init-val) |
|
(rf % v))] |
|
(completing (fn [acc token] |
|
(cond (dot? token) |
|
(done acc) |
|
(comma? token) |
|
(add-half acc) |
|
:else |
|
(add-word token acc)))))) |
|
|
|
;; Core task of switching halves and capitalization |
|
transforming (fn [rf] |
|
(completing (fn [acc [beg end :as content]] |
|
(rf acc |
|
(if end |
|
[(s/capitalize end), (s/lower-case beg)] |
|
content))))) |
|
|
|
;; Tuples -> sentences |
|
formatting (fn [rf] |
|
(completing (fn [acc [beg end]] |
|
(rf acc |
|
(if end |
|
(str beg (s/trim end) ". ") |
|
(str (s/trim beg) ". ")))))) |
|
|
|
;; Detect last space using end-narker and remove. |
|
trimming (fn [rf] |
|
(completing (fn [acc txt] |
|
(if (dot? txt) |
|
(rf (s/trim acc)) |
|
(rf acc txt)))))] |
|
|
|
(transduce (comp tokenizing |
|
structuring |
|
transforming |
|
formatting |
|
trimming) str txt))) |
|
|
|
|
|
(t/deftest ayoda_test |
|
(t/are [input exp] (= exp (ayoda input) (ayoda-2 input)) |
|
"Talk like this, Yoda does." |
|
"Yoda does talk like this." |
|
|
|
"Translate back to normal, you must." |
|
"You must translate back to normal." |
|
|
|
"Fun, Clojure is. Learn it, I will." |
|
"Clojure is fun. I will learn it." |
|
|
|
"Do or do not. There is no try." |
|
"Do or do not. There is no try." |
|
|
|
"To be or not to be, what to make of. Nothing or something. So, that is." |
|
"What to make of to be or not to be. Nothing or something. That is so." |
|
)) |
Hi @ericnormand,
Couldn't find the one I sent to you by mail, so posting it here: