Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;; first implementation -- kinda naive
- (defn expand-wildcards [input-str alphabet-str]
- "Given an input string replaces '?'s with all possible characters as
- expressed in the alphabet string parameter.
- ex. user> (expand-wildcards \"1?0110?1\" \"ab\")
- => (1a0110a1 1a0110b1 1b0110a1 1b0110b1)
- user> (expand-wildcards \"1?0110?1\" \"abc\")
- => (1a0110a1 1a0110b1 1a0110c1 1b0110a1 1b0110b1 1b0110c1 1c0110a1 1c0110b1 1c0110c1)"
- (loop [expansion (seq [input-str])
- times (count (filter #(= % \?) (seq input-str)))]
- (if (= times 0)
- expansion
- (recur (mapcat
- (fn [expand]
- (map #(.replaceFirst expand "\\?" (str %))
- (seq alphabet-str)))
- expansion)
- (dec times)))))
- ;;; testing
- ;(count (expand-wildcards "1?011????" "abcdefghijklmnopqrstuvwxyz"))
- ;(count (expand-wildcards "1?011????" "abc"))
- ;(println (expand-wildcards "1?0110?1" "ab"))
- ;(println (expand-wildcards "1?0110?1" "abc"))
- ;;;;;;;;;;;;;;;;;; Alternative Implementations ;;;;;;;;;;;;;;;;;;;
- (defn to-word [ith-word pad alphabet]
- "Returns the ith word of pad length given an alphabet.
- ex. user> (to-word 5 5 \"abc\")
- => \"aaabc\"
- "
- (let [alphabet-size (count alphabet)]
- (loop [quotient ith-word
- word nil]
- (if (< quotient 1)
- (if (< (count word) pad)
- (apply str (concat (repeat (- pad (count word))
- (.charAt alphabet 0))
- word))
- (apply str word))
- (recur (quot quotient alphabet-size)
- (cons (.charAt alphabet (rem quotient alphabet-size)) word))))))
- (defn fill-wildcards [input fill]
- "Given an input string and a fill string, wildcards in the input string
- will be replaced with characters from the fill string."
- (loop [input-pos (dec (count input))
- fill-pos (dec (count fill))
- result nil]
- (if (< input-pos 0)
- (apply str result)
- (let [current-char (.charAt input input-pos)
- wildcard? (= \? current-char)]
- (recur (dec input-pos)
- (if wildcard?
- (dec fill-pos)
- fill-pos)
- (cons (if wildcard?
- (.charAt fill fill-pos)
- current-char) result))))))
- ;; second impl - a bit different approach... working towards laziness
- (defn expand-wildcards [input-str alphabet]
- "Given an input string replaces '?'s with all possible characters as
- expressed in the alphabet string parameter.
- ex. user> (expand-wildcards \"1?0110?1\" \"ab\")
- => (1a0110a1 1a0110b1 1b0110a1 1b0110b1)
- user> (expand-wildcards \"1?0110?1\" \"abc\")
- => (1a0110a1 1a0110b1 1a0110c1 1b0110a1 1b0110b1 1b0110c1 1c0110a1 1c0110b1 1c0110c1)"
- (let [expansion (seq [input-str])
- num-wildcards (count (filter #(= % \?) (seq input-str)))
- alphabet-size (count alphabet)
- num-results (Math/pow alphabet-size num-wildcards)]
- (map #(fill-wildcards input-str (to-word % num-wildcards alphabet)) (range 0 (long num-results)))))
- ;; this version is lazy
- (defn expand-wildcards [input-str alphabet num-to-generate]
- "Given an input string replaces '?'s with all possible characters as
- expressed in the alphabet string parameter.
- ex. user> (expand-wildcards \"1?0110?1\" \"ab\" 3)
- => (1a0110a1 1a0110b1 1b0110a1)
- user> (expand-wildcards \"1?0110?1\" \"abc\" 5)
- => (1a0110a1 1a0110b1 1a0110c1 1b0110a1 1b0110b1)"
- (lazy-seq
- (let [expansion (seq [input-str])
- num-wildcards (count (filter #(= % \?) (seq input-str)))
- alphabet-size (count alphabet)
- num-results (Math/pow alphabet-size num-wildcards)
- f (fn [num] (fill-wildcards input-str (to-word num num-wildcards alphabet)))]
- (when-let [s (seq (range 0 (long num-to-generate)))]
- (cons (f (first s)) (map f (rest s)))))))
- ;(take 10 (expand-wildcards "1?011????" "abcdefghijklmnopqrstuvwxyz" 50))
Advertisement
Add Comment
Please, Sign In to add comment