This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-05-23
Channels
- # announcements (29)
- # babashka (6)
- # beginners (55)
- # biff (4)
- # clj-kondo (5)
- # clojure (162)
- # clojure-austin (2)
- # clojure-europe (38)
- # clojure-nl (1)
- # clojure-norway (9)
- # clojure-sweden (2)
- # clojure-uk (10)
- # clojuredesign-podcast (5)
- # clojurescript (7)
- # conjure (8)
- # core-async (4)
- # cursive (34)
- # datahike (13)
- # datomic (9)
- # fulcro (5)
- # holy-lambda (2)
- # honeysql (1)
- # hugsql (3)
- # hyperfiddle (22)
- # jobs (5)
- # london-clojurians (1)
- # malli (2)
- # matrix (3)
- # off-topic (32)
- # pedestal (26)
- # polylith (18)
- # reitit (5)
- # releases (1)
- # ring (29)
Hi there, I would need some help to clean up a little bit that code I wrote with regard to https://projecteuler.net/problem=39...
I can surely define few functions, but also wondering if I've been smart in the way I went about that problem. I got the right solution, it seems simple in the end, but doesn't read quite as simple as I'd like... actually any review/comment appreciated. I feel there might be a better way without a for
... took me a while to figure out how to actually "incrementally build a map of list... (still learning!)
(defn problem-39 []
(first (apply max-key second
(map #(vector (first %) (count (second %)))
(let [my-map {}]
(apply (partial merge-with set/union my-map)
(for [a (range 1 1000)
b (range 1 1000)
c (range 1 1000)
:when (and (= (* a a) (+ (* b b) (* c c))) ; could be its own function
(<= (+ a b c) 1000))
:let [sum (+ a b c)]]
{sum #{(sort (list a b c))}})))))))
I feel it does
(defn problem-39 []
(->> (let [my-map {}]
(apply (partial merge-with set/union my-map)
(for [a (range 1 1000)
b (range 1 1000)
c (range 1 1000)
:when (and (= (* a a) (+ (* b b) (* c c))) ; could be its own function
(<= (+ a b c) 1000))
:let [sum (+ a b c)]]
{sum #{(sort (list a b c))}})))
(map #(vector (first %) (count (second %))))
(apply max-key second)
(first)))
you could remove one of the for bindings and just compute the value for it, rather than checking all the possibilities
let me know if you see any other issue with the style or what I'm doing, I'm still a fairly early writer of code in clojure, even if I have been reading some for many years.
I think I might also bind b
to (range a 1000)
, and that should make it such that none of the triples would be checked more than once, which would eliminate the need for sets and/or sorting. And then, frequencies
is quite a useful function that could come in handy here, especially if the for
just returns the sum (because if the triples don't overlap, then the values of a, b, and c aren't really needed any longer).
Ok that's where I'm at from your great advices:
(defn right-triangle? [a b p]
(let [c (- p a b)]
(= (* c c) (+ (* a a) (* b b)))))
(defn problem-39 []
(->> (frequencies
(for [perimeter (range 12 1001)
a (range 2 perimeter)
b (range a (- perimeter a))
:when (right-triangle? a b perimeter)]
perimeter))
(apply max-key second)
(first)))
also renaming sum to perimeter makes more sense >_< and iterating through the perimeter makes it much faster: 2s vs ~13
let me know if you see any improvement or such that I could be missing at this point.
I did something pretty similar:
(->> (for [a (range 1 1000)
b (range a 1000)
:let [c (math/sqrt (+ (* a a) (* b b)))
sum (+ a b (int c))]
:when (and (zero? (mod c 1)) ; is c a whole number?
(<= sum 1000))]
sum)
frequencies
(apply max-key second)
first)
Hello everyone! How to pass :jvm-opts
to uberjar? Is it possible?
If you mean like embedding them, thatβs not possible
Hi! doing a little bit of the http://exercism.org exercises. The goal of the exercise I'm working on is transforming a map like this:
{1 ["APPLE" "ARTICHOKE"], 2 ["BOAT" "BALLERINA"]}
into
{"apple" 1 "artichoke" 1 "boat" 2 "ballerina" 2}
here in the 𧡠what I came up with as a solution. Any comments/ideas/more idiomatic way to write this would be appreciated.(defn transform [source] ;; <- arglist goes here
(reduce-kv
(fn [m k v]
(apply merge
(for [val v]
(assoc m (str/lower-case val) k)))) {} source))
:woman-shrugging: took me more time than I wanted to come up with a solution (like 45min/1h) and a lot of try and fail in the repl... still loving so much this language :smiling_face_with_3_hearts:
here is another solution, maybe a little bit more incremental to build
(defn transform [source]
(let [m (->> source
(mapv (fn [[n v]] (zipmap v (repeat n))))
(reduce merge))]
(update-keys m String/.toLowerCase)))
it is using String/.toLowerCase
which needs Clojure 1.12, but you can replace it with your str/lower-case
with more incremental I mean you can start with :
(->> {1 ["APPLE" "ARTICHOKE"], 2 ["BOAT" "BALLERINA"]}
(mapv (fn [[n v]] (zipmap v (repeat n)))))
[{"APPLE" 1, "ARTICHOKE" 1} {"BOAT" 2, "BALLERINA" 2}]
Oh I didn't know about update-keys
... nice one.
Curious on when to use String/.toLowerCase
vs str/lower-case
in general
I'm not yet super familiar with zipmap
, gonna read the doc now.
yeah, there is update-keys
and update-vals
, pretty useful
regarding the lowerCase, since strings in Clojure are java.lang.String
you can call the .toLowerCase
method on them, without any extra ns require
so create a map from a collection of keys and collection of values with the lowest size of both.
exactly
Thank you so very much it's super helpful to see other solutions. Do you think anything was wrong or not readable in my solution? I'm really trying to be good at writing understandable clojure.
I like your solution... It's probably what I wanted to do at first, but didn't find another solution that what I did.
Do you think anything was wrong or not readable in my solution? I'm really trying to be good at writing understandable clojure.I don't think there is anything wrong. Going the reduce way you can also do :
(defn transform [source]
(reduce-kv
(fn [m k v]
(reduce (fn [mm val]
(assoc mm (str/lower-case val) k))
m
v))
{}
source))
it think that is also a common pattern, where the inner reduce starts with the "accumulator so far"

using a transducer
(let [data {1 ["APPLE" "ARTICHOKE"], 2 ["BOAT" "BALLERINA"]}]
(into {} (mapcat (fn [[k vs]] (map (fn [v] [(str/lower-case v) k]) vs))) data))
I need to get to the level where this would be natural to me. I don't think I could have come up with that one.
(let [data {1 ["APPLE" "ARTICHOKE"], 2 ["BOAT" "BALLERINA"]}
xtrans (mapcat
(fn [[k vs]]
(map (fn [v] [(str/lower-case v) k]) vs)))]
(into {} xtrans data))
more legibleit's still not natural to me π just figured it would be a good way to do it there that wasn't shown yet
I think I start getting transducer... I understand it's about composing the transformations... But I haven't practice or try it yet.
Like most functions without the collection parameter returns a transducers, so we can compose them, and only pass the collection in the end... Is that the idea?
it's good to see one example on an exercise I tried to solve. Thank you so very much Nazral!
That's only one transducer there though, not being composed. You could probably make a very similar definition but that isn't a transducer, if you wanted to keep things simpler
I'm afk rn but I'd probably end up doing a mix between @U0739PUFQ's and @UGH9KH1DF's
Hi all I am following the play-clj tutorial to learn a little bit about that library, and I am trying to follow the tutorial at this page: https://github.com/oakes/play-clj/blob/master/TUTORIAL.md
The verrrrry first step says
"Now let's find an image to use as a texture in the game. Find one you'd like to use, such as https://upload.wikimedia.org/wikipedia/commons/8/85/Clojure-icon.png, and save it to the desktop/resources
folder. Next, simply change the line where the label entity is being created, so it creates a texture from that file instead:"
(texture "Clojure-icon.png")
->I have created a default play-clj file with lein per the instructions of the guide, but I do not know where in the file core.clj "the line where the label entity is being created" is....
Furthermore, as a part two to this question, even without making changes - I cannot figure out how to make the game actually run. I think I am in the default folder "desktop" with /src/ in it and I have tried many commands to get it to work like lein run -m src/core.clj and clj -M -m src/hello-world.clj and basically all the variants on those commands that I can think of.
I will post the core file as a comment on this thread for the first question of where the texture line goes...This is the default code with one change suggested by the tutorial in the namespace
(:require [play-clj.core :refer :all]
[play-clj.g2d :refer :all]))
(defscreen main-screen
:on-show
(fn [screen entities]
(update! screen :renderer (stage))
(label "Hello world!" (color :white)))
:on-render
(fn [screen entities]
(clear!)
(render! screen entities)))
(defgame hello-world-game
:on-create
(fn [this]
(set-screen! this main-screen)))