Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Last active August 1, 2022 21:50
Show Gist options
  • Select an option

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

Select an option

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

@RedPenguin101

Copy link
Copy Markdown
(defn regroup [string group-size]
  (->> string
       (remove #{\-})
       (reverse)
       (partition-all group-size)
       (interpose \-)
       (flatten)
       (reverse)
       (apply str)))

@nbardiuk

nbardiuk commented Jul 13, 2022

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

(defn regroup [plate-code group-size]
  (let [symbols (str/replace plate-code #"-" "")
        cug-off (mod (count symbols) group-size)
        [incomplete complete] (split-at cug-off symbols)]
    (->> (into (if (seq incomplete) [incomplete] [])
               (partition group-size complete))
         (map str/join)
         (str/join "-"))))

@harwood19

Copy link
Copy Markdown

(defn regroup [lic-plate group]
(let [hyphened (apply str (interleave (repeat -) (partition group (re-seq #"[a-z0-9]" lic-plate))))]
(if (= group (count lic-plate))
hyphened
(str (first lic-plate) hyphened (last lic-plate)))))

@harwood19

Copy link
Copy Markdown

eh...maybe just

(defn regroup-license-plate [license-plate group-size] (apply str (interleave (repeat "-") (partition group-size (re-seq #"[a-zA-Z0-9-]" license-plate)))))

... tricky one.

@adamrenklint

Copy link
Copy Markdown
(defn regroup [license-plate group-size]
  (->> (str/replace license-plate "-" "")
       (reverse)
       (partition-all group-size)
       (map str/join)
       (reverse)
       (str/join "-")))

@harwood19

harwood19 commented Jul 13, 2022

Copy link
Copy Markdown

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
Copy Markdown
(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
Copy Markdown
(defn regroup
  [s n]
  (->> s
       (remove #{\-})
       reverse
       (partition-all n)
       (map reverse)
       reverse
       (map str/join)
       (str/join "-")))

@rhishikeshj

Copy link
Copy Markdown
(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

jarohen commented Jul 14, 2022

Copy link
Copy Markdown

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

l4e21 commented Jul 14, 2022

Copy link
Copy Markdown

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

TheGreatCatAdorer commented Jul 14, 2022

Copy link
Copy Markdown

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
Copy Markdown
(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

sw1nn commented Jul 14, 2022

Copy link
Copy Markdown

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

vpetruchok commented Jul 14, 2022

Copy link
Copy Markdown
(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

burnall commented Jul 14, 2022

Copy link
Copy Markdown
(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
Copy Markdown
(defn regroup [plate-number n]
  (->> plate-number
       reverse
       (remove #{\-})
       (reduce #(str %2 (if (= n (mod (count %1) (inc n))) "-") %1) "")))

@rotaliator

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

@thomas-shares

Copy link
Copy Markdown
(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

esciafardini commented Jul 16, 2022

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

@mchampine

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

@miner

miner commented Jul 16, 2022

Copy link
Copy Markdown
(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

reborg commented Jul 18, 2022

Copy link
Copy Markdown

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
Copy Markdown
(defn regroup [text size]
    (->> text
        (filter #(not= "-" %))
        (reverse) 
        (partition size size nil)
        (reverse)
        (map reverse)
        (interpose "-")
        (flatten)
        (apply str)))```

@KingCode

KingCode commented Jul 20, 2022

Copy link
Copy Markdown
(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
Copy Markdown

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
Copy Markdown

@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
Copy Markdown
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