Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Created February 9, 2021 15:29
Show Gist options
  • Select an option

  • Save ericnormand/bf1178a04c7b28cdaf26e0fb3257defe to your computer and use it in GitHub Desktop.

Select an option

Save ericnormand/bf1178a04c7b28cdaf26e0fb3257defe to your computer and use it in GitHub Desktop.
413 - PurelyFunctional.tv Newsletter

Minimum steps to palindrome

A string is a palindrome if it is equal to its reverse.

(= "racecar" (str/reverse "racecar")) ;=> true, so palindrome

Your task is to write a function that adds a minimum of letters to the end of a string to make it a palindrome.

Examples

(->palindrome "race") ;=> "racecar"
(->palindrome "mad") ;=> "madam"
(->palindrome "mirror") ;=> "mirrorrim"

Note: the generated string does not have to be a real English word.

Thanks to this site for the challenge idea where it is considered Expert in JavaScript. The problem has been modified from the original.

Please submit your solutions as comments on this gist.

@cloojure

cloojure commented Feb 9, 2021

Copy link
Copy Markdown
(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require
    [schema.core :as s]
    [tupelo.string :as str]))

(s/defn palindome? :- s/Bool
  [arg :- s/Str] (= arg (str/reverse arg)))

(dotest
  (is (palindome? "racecar"))
  (isnt (palindome? "racecar9")))

(s/defn ->palindrome :- s/Str
  [orig :- s/Str]
  (loop [cnt 0]
    (let [extra-chars (str/join (reverse (take cnt orig)))
          candidate   (str orig extra-chars)]
      (if (palindome? candidate)
        candidate
        (recur (inc cnt))))))

(dotest
  (is= (->palindrome "race") "racecar")
  (is= (->palindrome "mad") "madam")
  (is= (->palindrome "mirror") "mirrorrim"))

@SneakyPeet

Copy link
Copy Markdown

Today I (and my entire company) learned about reductions

@miner

miner commented Feb 10, 2021

Copy link
Copy Markdown

Refactoring some other solutions to use transducers:

(defn ->palindrome [s]
  (let [r (str/reverse s)]
    (first (sequence (comp (map #(str (subs s 0 %) r))
                           (filter #(str/starts-with? % s))
                           (take 1))
                     (range (count s))))))

@alex-gerdom

alex-gerdom commented Feb 11, 2021

Copy link
Copy Markdown
(defn palindrome? [w] (= (seq w) (reverse w)))
(defn ->palindrome [w]
  "Return `w` with minimum number of letters added to end to make it a palindrome"
  (let [possible-endings (->> (range (count w))
                              (map #(take % w))
                              (map reverse))
        possible-palindromes (->> possible-endings
                                  (map (partial concat w))
                                  (map (partial apply str))
                                  (filter palindrome?))]
    (first possible-palindromes)))

Somewhat reduced:

(defn palindrome? [w] (= (seq w) (reverse w)))
(defn ->palindrome [w]
   (->> (reductions conj '() w)
        (map #(concat w %))
        (filter palindrome?)
        (first)
        (apply str)))

@dfuenzalida

dfuenzalida commented Feb 15, 2021

Copy link
Copy Markdown

A little late to this one, but similar to the others above:

(defn palin? [s]
  (= (seq s) (reverse s)))

(defn ->palindrome [s]
  (->> s reverse rest (reductions str s) (filter palin?) first))

;; (->palindrome "race") ;; => "racecar"
;; (->palindrome "mad") ;; => "madam"
;; (->palindrome "mirror") ;; => "mirrororrim"

@RedPenguin101

Copy link
Copy Markdown
(defn ->palindrome [string]
  (->> (range 1 (count string))
       (map #(str string (str/reverse (subs string 0 %))))
       (some #(#{%} (str/reverse %)))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment