Fork me on GitHub
#beginners
<
2019-10-03
>
neo255106:10:50

I would be interested into moving to tech. My background is from mathematics/statistics and I wondered if there was any book teaching how to solve algorithmic problems but on a playful manner. Something like many problems that you should be able to solve using ideas more than just coding endlessly?

neo255106:10:38

Something similar to project Euler, but less brutal for beginners? :)

alee07:10:50

Maybe 4clojure or clojure-koans

borkdude07:10:35

@neo2551 I haven't read this myself, but it looked interesting to me: https://www.manning.com/books/grokking-algorithms SICP might be worth going through as well.

alee07:10:03

With Clojure, you should find that most ideas are expressed succintly. If you find yourself debugging endlessly, maybe your ideas weren't as clear as they should have been originally, and you may find the debugging process helpful to clarify them. Or you may need to step back and rethink.

borkdude07:10:38

(which I also haven't read but looked interesting)

neo255107:10:29

These are great suggestions. I was more looking in a book that was presenting the material in the other direction than usual: first show problems, and then present some common algorithms that could be applied in several areas (like divide and conquer as a concept, or dynamic programming).

christian.gonzalez16:10:51

You might be interested in something like Concrete Mathematics, which provides algorithmic solutions for math problems. It’s really light on the actual coding part though so I would suggest supplementing the book with coding exercises or another book.

csd19:10:44

you might be interested in the book Algorithmic Puzzles https://www.amazon.com/Algorithmic-Puzzles-Anany-Levitin/dp/0199740445

neo255107:10:31

But I did 4-Clojure and Clojure koans, what i miss is a bit of an overview of the common algorithmic patterns (if this means anything) to solve problems.

alee07:10:22

Once you know how to solve some kinds of problems, the next trick is to learn how to see real problems as instances of those problems. Quite a lot of problems turn out to be graph traversals or spans, for example.

alee07:10:17

Rereading your question... there's always Knuth

neo255107:10:44

But thanks I will start with the grokking algorithm.

electricladyland15608:10:08

Is there any way to make clj -Spom to include paths from :extra-paths ? Another one, how to invoke deps.edn with clj in a certain path (not cwd)?

samuel.white10:10:47

Hi, I frequently see “NO_SOURCE_FILE” printed in my clojure logs, could anyone tell me what this means and how I might prevent this?

jaihindhreddy10:10:23

When you type forms into a REPL (or sends forms to the REPL), it doesn't really come from any file, which the logs reflect. Is this happening while using the REPL, or while running the program?

samuel.white10:10:22

This happens while running the program

abhi18av13:10:32

Hi guys, I think I’m missing some conceptual knowledge about the reduce function. Individually pieces here seem to work but together, my reduce function fails to return a map with {:d {1 {:value 42}}

(reduce
    (fn [new-map [a-path a-value]]
      (if-not (coll? a-value)
        (assoc-in new-map a-path a-value)))
    {}
    {[:d 1 :value] 42,
     [:top-tm]     [[:d 1] [:b 1]]})

Could anyone point out what I’m missing or doing wrong here please 🙂

bertofer13:10:17

@abhi18av the if-not is returning nil when the condition is met, so the new-map on next iteration is nil

bertofer13:10:03

(if-not (coll? a-value)
        (assoc-in new-map a-path a-value))
        new-map)
Should work

abhi18av13:10:08

Hi @, thanks for the quick response. Let me try this out

abhi18av13:10:51

Hmm, unless there’s a parens issue, still a nil

(reduce
    (fn [new-map [a-path a-value]]
      (if-not (coll? a-value)
        (assoc-in new-map a-path a-value)
      new-map))
    {}
    {[:d 1 :value] 42,
     [:top-tm]     [[:d 1] [:b 1]]}))



abhi18av13:10:29

Yup, got it working. The issue was with the parens ( not on a good text editor right now) - Thanks @

jaihindhreddy13:10:34

@abhi18av Just a style point... I know this might be a toy example but separating the collection filter and value might make it easier to grok. Like this:

(->> {[:d 1 :value] 42
      [:top-tm]     [[:d 1] [:b 1]]}
     (remove (fn [[_ v]] (coll? v)))
     (reduce #(apply assoc-in % %2) {}))
Here we've separated removing non-coll items, but introduced apply which comes with some performance overhead and makes it less clear because %2 will only ever contain two things, so we can do:
(->> {[:d 1 :value] 42
      [:top-tm]     [[:d 1] [:b 1]]}
     (remove (fn [[_ v]] (coll? v)))
     (reduce #(assoc-in % (first %2) (second %2)) {}))
That's clearer but here %2 is always a key-val pair and using first and second goes through the seq abstraction, coming with some overhead of itself. Enter key and val:
(->> {[:d 1 :value] 42
      [:top-tm]     [[:d 1] [:b 1]]}
     (remove #(coll? (val %)))
     (reduce #(assoc-in % (key %2) (val %2)) {}))

jaihindhreddy13:10:20

That being said, of course, all this is my subjective opinion, and YMMV.

abhi18av15:10:25

Thanks @ for being so clear in your explanation man! This way of thinking does seem more idiomatic parens

nicholas.jaunsen19:10:18

skykanin [9:40 PM] So I wrote a spec for this function which checks if the input argument is a vector or list and checks if the length is greater than 2. For some reason when I call the function with valid input arguments the spec assertion that (> (count %) 2) fails. What am I doing wrong here?

kailash.subscriptions19:10:26

(s/valid? (s/and #(s/or :vector? (vector? %) :list? (list? %)) #(> (count %) 2)) [1] => false

abhi18av11:10:34

A bit of a side-question @nicholas.jaunsen, how did you put in this kind of code? I mean I’m only aware of the triple backtip notation

nicholas.jaunsen11:10:21

There is a button for text/code snippets @abhi18av

seancorfield19:10:47

@nicholas.jaunsen The :args part of s/fdef is the whole argument list. You want s/cat for the argument list.

seancorfield19:10:22

:args (s/cat :ns (s/and #(s/or ,,,) #(> (count %) 2)))

seancorfield19:10:07

What you're testing above is essentially that you should be calling highest-prod with three or more arguments.

seancorfield19:10:24

But you could use (s/coll-of number? :min-count 3) instead

seancorfield19:10:41

(s/fdef highest-prod
  :args (s/cat :ns (s/coll-of int? :min-count 3))
  :ret int?)
(just noticed you spec to return an integer so the ns argument would be a collection of int? as well)

nicholas.jaunsen20:10:33

@seancorfield thank you

nicholas.jaunsen21:10:04

Should I be using clojure.test or clojure.spec.test.alpha to test specs? I wasn't able to run clojure.spec.alpha/valid? on the function spec (`fdef`).

borkdude21:10:12

@nicholas.jaunsen I've written a small lib to tests fdefs:

nicholas.jaunsen14:10:36

This is exactly what I wanted. Thank you!

nicholas.jaunsen15:10:30

hmm, seems that leiningen can't find the respeced dep even though the jar is downloaded and I've imported it in the test file as [respeced :as r]

borkdude15:10:52

respeced.test :as r

borkdude21:10:53

I'm not sure if that's what you're looking for.

seancorfield22:10:13

@nicholas.jaunsen fdef is intended for two different uses: clojure.spec.test.alpha/instrument will enable checking of :args specs during calls to the function -- so you might instrument code during dev or test work; clojure.spec.test.alpha/check will perform generative testing of the :ret/`:fn` specs explicitly.

seancorfield22:10:44

Generative testing can often take time so it isn't generally intended to be run as part of your "unit tests" (which should complete quickly).

seancorfield22:10:09

See if this blog post helps at all @nicholas.jaunsen https://corfield.org/blog/2019/09/13/using-spec/