Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Last active August 1, 2022 21:50
Show Gist options
  • Save ericnormand/415c98b46e216978728156fecc20bac4 to your computer and use it in GitHub Desktop.
Save ericnormand/415c98b46e216978728156fecc20bac4 to your computer and use it in GitHub Desktop.
471 Eric Normand Newsletter

License plates

When you cross the border in a car, you have to abide by the local license plate regulations. (This is not true, but let's play pretend!) The order of the numbers and letters stays the same. But the groupings change from country to country.

Write a function that takes a license plate code (letters, digits, and hyphens in a string) and a group size (integer). The function should return a new string with the characters regrouped with hyphens between groups. All groups should be of the given size, except for perhaps the first, if there aren't enough characters to fill the group.

Examples

(regroup "A5-GG-B88" 3) ;=> "A-5GG-B88"
(regroup "A5-GG-B88" 2) ;=> "A-5G-GB-88"
(regroup "6776" 2) ;=> "67-76"
(regroup "F33" 1) ;=> "F-3-3"
(regroup "IIO" 7) ;=> "IIO"

Thanks to this site for the problem idea, where it is rated Expert in Swift. The problem has been modified.

Please submit your solutions as comments on this gist.

To subscribe: https://ericnormand.me/newsletter

@harwood19
Copy link

harwood19 commented Jul 13, 2022

Is there any collective feedback or sanctioning from Eric regarding ideal solutions, breakdowns, at the end of each challenge? I know I'm new here and want to be respectful; But also want to know if I'm wrong, where I could be better, etc. Just curious.

@kauppilainen
Copy link

(defn regroup [code size]
  (->> (clojure.string/replace code "-" "")
       reverse
       (partition-all size)
       reverse
       (map reverse)
       (map clojure.string/join) 
       (clojure.string/join "-")))

@mcuervoe
Copy link

(defn regroup
  [s n]
  (->> s
       (remove #{\-})
       reverse
       (partition-all n)
       (map reverse)
       reverse
       (map str/join)
       (str/join "-")))

@rhishikeshj
Copy link

(defn regroup
  [str size]
  (let [xform (comp (filter #(not= % "-"))
                    (partition-all size)
                    (map (comp clojure.string/join reverse)))]
    (->> str
         reverse
         (transduce xform conj)
         reverse
         (clojure.string/join "-"))))

@jarohen
Copy link

jarohen commented Jul 14, 2022

maybe went too far down the regex rabbit-hole - goodbye readability...?!

(defn regroup [plate group-size]
  (-> plate
      (str/replace #"-" "")
      (str/reverse)
      (str/replace (re-pattern (format "(.{%d})(?!$)" group-size)) "$1-")
      (str/reverse)))

@l4e21
Copy link

l4e21 commented Jul 14, 2022

I think this is the simplest :) if you have an abstraction like indexed reduce obviously it becomes even simpler (though you'd need it to come with some way to reset the index)

(defn nameplate [plate group-size]
  (->> plate
       reverse
       (reduce (fn [acc x]
                 (cond
                   (= x \-) acc
                   (= (:index acc) group-size) {:index 1 :string (str x \- (:string acc))}
                   :otherwise {:index (+ 1 (:index acc)) :string (str x (:string acc))}))
               {:index 0 :string ""})
       :string))

@TheGreatCatAdorer
Copy link

TheGreatCatAdorer commented Jul 14, 2022

Haskell:

import Data.Function ((&))
intersperse a as = take 1 as ++ (drop 1 as >>= (a :) . pure)
chunksOf i as = iterate (drop i) & map (take i) & takeWhile (not . null)
regroup str i = chars str & reverse & chunksOf i & intersperse "-" & concat & reverse

@mmisamore
Copy link

(require '[clojure.string :as str])
(defn regroup [s n]
  (->> (str/replace s "-" "") 
     (str/reverse) 
     (partition-all n) 
     (map #(apply str (reverse %))) 
     reverse 
     (interpose "-") 
     (apply str)))

@sw1nn
Copy link

sw1nn commented Jul 14, 2022

Regex soln without reversing for entertainment use only.

(require '[clojure.string :as str])
(defn regroup [s n]
  (let [patt (re-pattern (str "(?:^.{0," n "}$|^.{" n "}(?!..{" n ",})|^.{1," n "}?|(?<!^).{" n "}+)"))]
    (->> (str/replace s "-" "")
         (re-seq patt)
         (str/join "-"))))

With 'in-pattern documentation (see repl output)

(defn regroup [s n]
  (let [patt (re-pattern (str "(?x:\n"
                              "^.{0," n "}$|        # single short? group is whole pattern\n"
                              "^.{" n "}(?!..{" n ",})| # group match not followed by another full group\n"
                              "^.{1," n "}?|        # short? group match reluctant\n"
                              "(?<!^).{" n "}+      # full group match possessive not at the start\n"
                              ")"))]
    (println patt)
    (->> (str/replace s "-" "")
         (re-seq patt)
         (str/join "-"))))

@vpetruchok
Copy link

vpetruchok commented Jul 14, 2022

(defn regroup [license-plate-code group-size]
  (let [license-plate-code (clojure.string/replace license-plate-code "-" "")
        shift              (mod (count license-plate-code) group-size)]
    (cond
      (<= (count license-plate-code) group-size)
      license-plate-code

      (zero? shift)
      (->> (partition group-size license-plate-code)
           (map #(apply str %))
           (clojure.string/join "-"))

      :default
      (->> (partition group-size (subs license-plate-code shift))
           (map #(apply str %))
           (cons (subs license-plate-code 0 shift))
           (clojure.string/join "-")))))

@burnall
Copy link

burnall commented Jul 14, 2022

(defn re-group [s n]
  (let [chars (remove #{\-})
        pad (mod (count chars) n)
        groups (cons (take pad chars)
                     (partition n (drop pad chars)))]
    (->> groups
         (filter not-empty)
         (map (partial apply str))
         (clojure.string/join "-"))))

@jonasseglare
Copy link

(defn regroup [plate-number n]
  (->> plate-number
       reverse
       (remove #{\-})
       (reduce #(str %2 (if (= n (mod (count %1) (inc n))) "-") %1) "")))

@rotaliator
Copy link

(defn regroup [s n]
  (->> (str/replace s #"-" "")
       (str/reverse)
       (partition-all n)
       (map reverse)
       (map #(apply str %))
       (reverse)
       (str/join "-")))

@thomas-shares
Copy link

(defn regroup [string size]
  (let [replaced (str/replace string #"-" "")
        length (count replaced) ]
    (if (or (and (< size length) (zero? (rem length size))) (not (< size length)))
      (str/join "-" (map str/join (partition-all size replaced )))
      (let [f (first replaced)
            r (rest replaced) ]
        (str f "-" (str/join "-" (map str/join (partition-all size (str/join "" r)))))))))

Yeah, not as nice as some of the others... I hadn't thought about reversing it, that is clever.

@esciafardini
Copy link

esciafardini commented Jul 16, 2022

(defn regroup [s n]
  (->> s
       reverse
       (remove #{\-})
       (partition-all n)
       (interpose \-)
       flatten
       reverse
       (apply str)))

@mchampine
Copy link

(defn regroup [s n]
  (->> (remove #{\-} (reverse s))
       (partition-all n)
       (map #(apply str (reverse %)))
       reverse
       (str/join "-")))

@miner
Copy link

miner commented Jul 16, 2022

(require '[clojure.string :as str])

(defn regroup [s width]
  (let [base (str/replace s "-" "")
        cnt (count base)]
    (str (reduce (fn [sb i] (.insert ^StringBuilder sb ^int i \-))
                 (StringBuilder. base)
                 (range (- cnt width) 0 (- width))))))

@reborg
Copy link

reborg commented Jul 18, 2022

So, if I had to showcase Clojure expressiveness, I'd go with a version similar to many others above:

(defn regroup
  [plate n]
  (->> (s/replace plate #"-" "")
       reverse
       (partition-all n)
       (interpose "-")
       reverse
       (mapcat reverse)
       (apply str)))

When I'm told "ahhh but that's so slow" then I can say go with something like:

(defn regroup
  [plate n]
  (let [nodash (s/replace plate #"-" "")
        cnt (count nodash)]
    (str
     (reduce
      (fn [^StringBuilder sb idx]
        (let [i (- cnt idx)
              group (inc (mod idx n))
              ch (subs nodash (dec i) i)]
          (.insert sb 0 ch)
          (when (and (= group n) (> i 1))
            (.insert sb 0 "-"))
          sb))
      (StringBuilder.)
      (range cnt)))))

But then somebody might say "aahhh but this is passing through the string twice, what if the string is huge?"

(defn regroup
  [^String plate n]
  (loop [i (count plate) sb (StringBuilder.) group 1]
    (if (= 0 i)
      (str sb)
      (let [i (dec i)
            ch (subs plate i (inc i))]
        (cond (= "-" ch)
              (recur i sb group)
              (and (> i 0) (= group n))
              (recur i (.insert sb 0 (str "-" ch)) 1)
              :else
              (recur i (.insert sb 0 ch) (inc group)))))))

@maquirag
Copy link

(defn regroup [text size]
    (->> text
        (filter #(not= "-" %))
        (reverse) 
        (partition size size nil)
        (reverse)
        (map reverse)
        (interpose "-")
        (flatten)
        (apply str)))```

@KingCode
Copy link

KingCode commented Jul 20, 2022

(require '[clojure.string :as str])

(defn regroup [plate n]
  (->> plate reverse
       (transduce (comp 
                   (remove #{\-})
                   (partition-all n)
                   (map #(str/join [\-]))
                  into
                  ())
       (apply str)))

@harwood19
Copy link

So yeah, got a DM response to my prior post/inquiry saying that “…we don’t really select the best solution nor breakdown or encourage. We don’t teach nor do we collaborate. We simply respond with our best Closure solution per exercise. They go into a black hole. But hey, it’s something… all we got.”

Fair enough! Again, figure ya’ll been doing this awhile. Appreciate your grace as I learn the culture while’st playing with a new coding language.

@KingCode
Copy link

@harwood19 Welcome aboard!

To answer your question, there is no sanctioning except perhaps for non-courteous behavior (which I have never seen).
Basically, it is up to others to comment on your code, which usually happens for interesting solutions.

My only suggestion for your posts would be to use the nice formatting tool afforded here, by enclosing your code with triple backslashes and the word clojure above, and triple backslashes below. The Preview pane can be used before you submit the post.

@ericnormand
Copy link
Author

(defn regroup [s size]
  (->> s
       (remove #{\-})
       reverse
       (partition-all size)
       (interpose \-)
       flatten
       reverse
       (apply str)))

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