Fork me on GitHub
#beginners
<
2021-10-05
>
Sara Wänerskär06:10:58

Hi! I am working on https://exercism.org/tracks/clojure/exercises/interest-is-interesting, where I am supposed to calculate interest rate using BigDecimal. I am not able to get some of the tests to pass. There must be something that I am missing about multiplication and percentage with BigDecimal. Any help would be greatly appreciated! SRC

(defn interest-rate
  "Get interest rate for balance"
  [balance]
  (cond (< balance 0) -3.213
        (< balance 1000) 0.5
        (< balance 5000) 1.621
        :else 2.475)
  )

(defn annual-balance-update
  "Calculate balance update"
  [balance]
  (bigdec (* balance (+ (* (interest-rate balance) 0.01) 1)))
  )
TEST Test 1
(deftest annual-balance-update-large-positive-balance-test
  (is (= 1016.210101621M (interest-is-interesting/annual-balance-update 1000.0001M))))
Result 1 Assertion failed: Expected :920352587.26744292868451875M Actual :920352587.267443M Test 2 (deftest annual-balance-update-small-negative-balance-test (is (= -0.12695199M (interest-is-interesting/annual-balance-update -0.123M)))) Result 2 Assertion failed: Expected :-0.12695199M Actual :-0.11904801M

Tarasov Oleg07:10:27

(defn annual-balance-update   "Calculate balance update"   [balance]   ( balance (+ (bigdec ( (interest-rate balance) 0.01)) 1)))

Lennart Buit09:10:28

you can use triple-backtick to get a multiline code fragment in slack 🙂

Hello, World!

👍 1
Sara Wänerskär09:10:17

Thank you Lennart, I edited my post according to your suggestion to make it easier to read.

👍 1
Jonathan Chen17:10:36

Just for my understanding, the fix was to convert to bigdec earlier in the process so precision isn't lost?

Redbeardy McGee10:10:22

I have a map of maps. I need the inner map where the value of a particular key matches a given string. Perhaps naively, I started with (filter #(= "string" (:key %)) map-of-maps). This does extract the correct map, but the result is a lazy seq now so I cannot use normal hashmap fns to work with the data contained within. As a workaround, I just used (into {} inner-map) to get a hashmap back instead. It works, but it feels like I've gone roundabout by having the intermediate lazy seq.

flowthing10:10:59

Can you give an example of what map-of-maps looks like?

Redbeardy McGee10:10:56

{:k1 foo :k2 bar, :k3 {:inner-k1 foo, :inner-k2 "correct map", :inner-k3 bar}, :k4 quux, :k5 {:inner-k1 foo, :inner-k2 "wrong map", :inner-k3 bar}}

Redbeardy McGee10:10:12

oh that did not let me fix the formatting

Redbeardy McGee10:10:05

The outer map has some irrelevant key-value pairs. There is 1 singular inner map which is important, but is only denoted by the "important value" inside the map.

flowthing10:10:15

There are two inner maps with "important value" there?

Redbeardy McGee10:10:51

i only want 1 of the inner maps.

Redbeardy McGee10:10:07

the other inner maps will not have the same value at :inner-k2

flowthing10:10:28

So you want one inner map whose :inner-k2 equals "important value"?

flowthing10:10:41

Right, I was just about to say that your example input doesn't really match with what you're saying. 🙂

Redbeardy McGee10:10:24

in that example, i need to extract :k3 's value, where :inner-k2 is "correct map"

Redbeardy McGee10:10:49

In another case, i may need the map at :k5 instead, but that's another day

flowthing10:10:50

If you just want to avoid the intermediate lazy seq, you can use the transducer arity of into:

user=> (def map-of-maps
         {:k1 {}
          :k2 {}
          :k3 {:inner-k1 "foo" :inner-k2 "correct map" :inner-k3 "bar"}
          :k4 {}
          :k5 {:inner-k1 "foo" :inner-k2 "wrong map" :inner-k3 "bar"}})
#'user/map-of-maps
user=> (into {}
         (filter (comp #{"correct map"} :inner-k2 val))
         map-of-maps)
{:k3 {:inner-k1 "foo", :inner-k2 "correct map", :inner-k3 "bar"}}
However, whenever I find myself doing linear search, I start thinking about whether I should maybe restructure my data instead. One option is to index the input first and then look up the value by the index:
user=> (into {}
         (map (juxt (comp :inner-k2 val) identity))
         map-of-maps)
{nil [:k4 {}],
 "correct map" [:k3 {:inner-k1 "foo", :inner-k2 "correct map", :inner-k3 "bar"}],
 "wrong map" [:k5 {:inner-k1 "foo", :inner-k2 "wrong map", :inner-k3 "bar"}]}
user=> (peek (get *1 "correct map"))
{:inner-k1 "foo", :inner-k2 "correct map", :inner-k3 "bar"}

Redbeardy McGee11:10:43

I'm not sure what approach to take. Something about producing an intermediate sequence seemed incorrect because I just need the single inner map with the correct key-value pair, and then will be using some of the values in that map.

Fredrik11:10:21

Filtering a map does produce a sequence, but it is lazy, so it only computes as much as is needed. Putting something like

(->> (vals m)
     (filter (comp #{"correct map"} :inner-k2))
     first)
in a function so you can parametrize the key and value to match against. This is functionally equivalent to a loop that stops as soon as it finds the correct map.

Redbeardy McGee11:10:49

so I shouldn't be concerned with the intermediate sequence, and just take more care to recognize when one will be generated

Redbeardy McGee11:10:11

Thanks to both of you for clarifying some of these things for me!

Fredrik11:10:35

Ideally you don't want to traverse data. Better than searching your data is querying it. But when restructuring like in the second example of @U4ZDX466T is impractical or has too much overhead, yes you shouldn't have to worry about intermediate lazy sequences.

Redbeardy McGee11:10:54

I don't want to be doing this, but I received it from an API in this outlandish format

Fredrik11:10:44

Then you can consider whether normalizing it in some way up front makes sense for further processing

Redbeardy McGee11:10:42

And that would be like the example above, finding the kv i'm after and then turning that value into a key of a new map?

Fredrik11:10:41

Creating an index like that would be an example, yes

Matheus Silva13:10:44

I wanted to get an id list according to a numeric string, I believe I'm doing the wrong map, do not know how to proceed, can someone help me

Apple15:10:54

user> (distinct (map {\1 "a" \2 "a" \3 "b" \4 "b"} "1234"))
("a" "b")

Fredrik15:10:54

Mapping over the input string like above is a nice way to go about it. A substitution map ch->opt can be built up like

(let [id-list [{:id "b" :option [2 4]} {:id "a" :option [1 3]}]
      ch->opt   (into {}
                      (map (fn [{:keys [id option]}]
                             (zipmap (map #(Character/forDigit % 10) option) (repeat id))))
                      id-list)]
  (distinct (map ch->opt "1234")))

Fredrik15:10:55

You might also prefer

(let [id-list   [{:id "b" :option [2 4]} {:id "a" :option [1 3]}]
      ch->opt   (into {} (map (fn [{:keys [id option]}] (zipmap option (repeat id)))) id-list)]
  (distinct (map ch->opt (map #(Integer/parseInt %) (str/split "1234" #"")))))

Apple16:10:30

distinct of course not dedupe. i edit mine.

Sebastian17:10:23

Does anybody know good resources for Clojure live coding? I am still having trouble adapting to the Clojure way of programming and it would be nice if I could see someone implement a solution to a problem while hearing their thoughts going into the implementation? Any books, blogs, etc that can help in this regard are also highly appreciated

seancorfield18:10:04

I did a pretty long live coding demo for London Clojurians a while back https://www.youtube.com/watch?v=gIoadGfm5T8 and their are a few shorter ones on my YouTube channel https://www.youtube.com/c/SeanCorfield_A

seancorfield18:10:38

I think there's some videos linked from the Practicalli site as well. There are probably quite a few other videos out there from individuals.

❤️ 1
dgb2318:10:35

I watched the above video and can recommend it! This is one Iquite enjoyed too: https://youtu.be/lU3awBr5C7E

dgb2318:10:55

Oh and I think there is a very friendly tutorial like channel that someone recommended recently: “on the code again”

practicalli-john21:10:58

The 4Clojure walkthrough videos are examples of thinking through code decisions, most challenges have several approaches to solving the problem https://youtube.com/playlist?list=PLpr9V-R8ZxiDB_KGrbliCsCUrmcBvdW16

Sebastian23:10:56

Thank you all very much 🙌

Rob Haisfield22:10:22

Anyone know of a good Web3 library? I couldn’t find anything recent. I saw this but it hasn’t been updated in a while so idk if it still works. https://github.com/district0x/cljs-web3