To add a little variant of James Reeve's code: You can avoid the loop/recur 
by using reduce:


(defn valid-parens? [s]
  (let [opening-brackets {\( \), \[ \], \{ \}}
        closing-brackets (clojure.set/map-invert opening-brackets)]
    (empty?
      (reduce
        (fn [stack c]
          (if (opening-brackets c)
            (conj stack c)
            (if-let [b (closing-brackets c)]
              (if (= (peek stack) b)
                (pop stack)
                (reduced [false]))
              stack)))
        []
        (seq s)))))


HTH

On Sunday, June 26, 2016 at 4:06:27 PM UTC+2, Botond Balázs wrote:
>
> Thanks guys.
>
> Very nice and simple solution, James.
>
> On Sunday, June 26, 2016 at 3:21:56 PM UTC+2, James Reeves wrote:
>>
>> The easiest way would be to factor out the bracket matching code, since 
>> that's the only thing that changes between your different case statements. 
>> For instance:
>>
>>   (defn valid-parens? [s]
>>     (let [opening-brackets {\( \), \[ \], \{ \}}
>>           closing-brackets (clojure.set/map-invert opening-brackets)]
>>       (loop [cs (seq s), stack []]
>>         (if-not cs
>>           (empty? stack)
>>           (let [c (first cs), cs (next cs)]
>>             (if (opening-brackets c)
>>               (recur cs (conj stack c))
>>               (if-let [b (closing-brackets c)]
>>                 (if (= (peek stack) b)
>>                   (recur cs (pop stack))
>>                   false)
>>                 (recur cs stack)))))))
>>
>> Another way you could do it is to replace your recursive call with a 
>> continuation.
>>
>> - James
>>
>> On 26 June 2016 at 13:43, Botond Balázs <balazs...@gmail.com> wrote:
>>
>>> Hi,
>>>
>>> Here is my solution to 4clojure problem #177:
>>>
>>> Write a function that takes in a string and returns truthy if all square 
>>>> [ ] round ( ) and curly { } brackets are properly paired and legally 
>>>> nested, or returns falsey otherwise.
>>>>
>>>
>>> (defn valid-parens?
>>>   [s]
>>>   (loop [[ch & chs] s stack []]
>>>     (if (nil? ch)
>>>       (empty? stack)
>>>       (case ch
>>>         (\( \[ \{) (recur chs (conj stack ch))
>>>         \) (if (= (peek stack) \()
>>>              (recur chs (pop stack))
>>>              false)
>>>         \] (if (= (peek stack) \[)
>>>              (recur chs (pop stack))
>>>              false)
>>>         \} (if (= (peek stack) \{)
>>>              (recur chs (pop stack))
>>>              false)
>>>         (recur chs stack)))))
>>>
>>> This works but I don't like the repetition in the case branches. But 
>>> the repeated code contains a recur call so I can't simply refactor it 
>>> into a helper function. How can I achieves something like the following, 
>>> but without consuming the stack?
>>>
>>> (defn valid-parens?
>>>   ([s]
>>>    (valid-parens? s []))
>>>   ([[ch & chs] stack]
>>>    (if (nil? ch)
>>>      (empty? stack)
>>>      (letfn [(match? [p]
>>>                (if (= (peek stack) p)
>>>                  (valid-parens? chs (pop stack))
>>>                  false))]
>>>        (case ch
>>>          (\( \[ \{) (valid-parens? chs (conj stack ch))
>>>          \) (match? \()
>>>          \] (match? \[)
>>>          \} (match? \{)
>>>          (valid-parens? chs stack))))))
>>>
>>> Thanks!
>>> Botond
>>>
>>> -- 
>>> You received this message because you are subscribed to the Google
>>> Groups "Clojure" group.
>>> To post to this group, send email to clo...@googlegroups.com
>>> Note that posts from new members are moderated - please be patient with 
>>> your first post.
>>> To unsubscribe from this group, send email to
>>> clojure+u...@googlegroups.com
>>> For more options, visit this group at
>>> http://groups.google.com/group/clojure?hl=en
>>> --- 
>>> You received this message because you are subscribed to the Google 
>>> Groups "Clojure" group.
>>> To unsubscribe from this group and stop receiving emails from it, send 
>>> an email to clojure+u...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to