|
(ns functional-tv-puzzles.2020.remove-last-vowels-367) |
|
|
|
(def vowels (set "aeiouAEIOU")) |
|
|
|
;; NOTE that when a single letter (vowel) word is removed, one of the surrounding |
|
;; spaces is removed as well, e.g. |
|
;; "This is a test" => "Ths s tst" rather than |
|
;; => "Ths s tst" |
|
|
|
;; Plugin impl that splits the word at last vowel and joins surroundings |
|
(defn no-last-vowel-1 [word] |
|
(let [split-pos (->> word |
|
(map-indexed (fn [i x] |
|
(if (vowels x) i -1))) |
|
(filter (complement neg?)) |
|
last) |
|
[pfx sfx] (split-at split-pos word)] |
|
(->> [pfx (rest sfx)] |
|
flatten |
|
(apply str)))) |
|
|
|
;; Plugin impl whih uses partitioning, prunes last vowel |
|
;; of applicable partition and rebuilds. |
|
(defn no-last-vowel-2 [word] |
|
(let [[last, before-last & begin] (reverse |
|
(partition-by vowels word)) |
|
[last', before-last'] (if (some vowels last) |
|
[(butlast last), before-last] |
|
[last, (butlast before-last)]) ] |
|
(-> begin reverse flatten vec |
|
(into (vec before-last')) |
|
(into (vec last')) |
|
(#(apply str %))))) |
|
|
|
(defn remove-last-vowels-shell [s word-fn] |
|
(->> (clojure.string/split s #" ") |
|
(map word-fn) |
|
(filter seq) |
|
(clojure.string/join " "))) |
|
|
|
(defn remove-last-vowels |
|
([s] ;; monolith impl |
|
(->> |
|
(clojure.string/split s #" ") |
|
(sequence (comp |
|
(map #(apply str (reverse %))) |
|
(map #(reduce (fn [[done? acc] x] |
|
(cond |
|
done? [done? (conj acc x)] |
|
(vowels x) [true acc] |
|
:else [done? (conj acc x)])) |
|
[nil []] %)) |
|
(map last) |
|
(map reverse) |
|
(map #(apply str %)) |
|
(filter seq))) |
|
(interpose " ") |
|
(apply str))) |
|
([s word-fn] ;; with plugin |
|
(remove-last-vowels-shell s word-fn))) |
|
|
|
(def test-phrases |
|
[["Those who dare to fail miserably can achieve greatly." |
|
"Thos wh dar t fal miserbly cn achiev gretly."] |
|
["Love is a serious mental disease." |
|
"Lov s serios mentl diseas."] |
|
["Get busy living or get busy dying." |
|
"Gt bsy livng r gt bsy dyng."] |
|
["Please Take A Number" |
|
"Pleas Tak Numbr"] |
|
["Hi, there!", |
|
"H, ther!"] |
|
["This is not a test.", |
|
"Ths s nt tst."] |
|
["Hippopotamus", |
|
"Hippopotams"] |
|
["Mary didn't have a big huge lamb", |
|
"Mry ddn't hav bg hug lmb"]] ) |
|
|
|
(defn test-all [] |
|
(let [pass? (fn [f] |
|
(->> test-phrases |
|
(map (fn [[input expected]] |
|
(= expected (f input)))) |
|
(every? identity)))] |
|
(->> [remove-last-vowels, |
|
#(remove-last-vowels % no-last-vowel-1) |
|
#(remove-last-vowels % no-last-vowel-2)] |
|
(every? pass?)))) |
Kenny Shen, Viktor P
You can use a set as a function:
(#{\a} \a) ; => \a (truthy)
(#{\a} \b) ; => nil (falsey)
If you know your set does not contain false or nil (
(#{false} false) ; => false
, whereas(contains? #{false} false) ; => true
), you do not needcontains?
.Viktor P
Check out complement. You could refactor to
(def not-vowel? (complement vowel?))