This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-06-28
Channels
- # announcements (1)
- # beginners (128)
- # calva (15)
- # cider (1)
- # clerk (4)
- # clj-kondo (10)
- # clojure-berlin (5)
- # clojure-denmark (2)
- # clojure-europe (59)
- # clojure-nl (2)
- # clojure-norway (83)
- # clojure-sweden (3)
- # clojure-uk (4)
- # cursive (11)
- # datomic (8)
- # emacs (13)
- # events (1)
- # hyperfiddle (3)
- # juxt (2)
- # malli (13)
- # nrepl (10)
- # off-topic (46)
- # releases (2)
- # reveal (1)
- # rewrite-clj (6)
- # sci (6)
- # scittle (17)
- # shadow-cljs (2)
- # xtdb (2)
- # yamlscript (8)
I am doing the hobbit violence exercise from the clojure brave book. basically I am developing a recursive fn that implements the weighted random selection algo. what it does is that it hits a random part of a character's physical body and each part exists in a vector of maps with names and sizes. the way i do this is that i sum all the part sizes and then using an accumulator In which I put the sizes of random parts in i check if the accumulator is larger than the total sum of body part sizes and if it's not I continue adding more part sizes to the accumulator if it is, I return the part that exceeded the total body size sum. the reason it's weighted is that because each part has a different size, body parts with larger size have a bigger chance of going over the total body part sum on each call. the way I understand this everything is determined by that one recursion where the part exceeds the total sum of the body and the previous ones are largely irrelevant (as far as i can tell). given all that I'd like to understand - is measuring against the total body part size sum even meaningful or is setting any arbitrary number going to work just as well too?
> using an accumulator In which I put the sizes of random parts in And a single part can be repeated, right?
Hmm. Your description doesn't correspond to what the "Hobbit Violence" section describes.
There, the parts are not random, but the target
value is, with the upper boundary being the total body size.
target
cannot be too low - otherwise, e.g. feet would never be hit.
It also shouldn't be too high - otherwise, nothing will be hit and the loop will throw an NPE.
It seems that the algorithm is what Rich Hickey has implemented here, with some extra docstring: https://gist.github.com/dribnet/3399263/a9399bff5ce3de2b3731b17fd26d5048508e27c3#file-ants-clj-L84
is this ACO?
Ah, probably ant colony optimization. First time I see that code and hear that term, so no clue.
never mind, i just realized that I was thinking incorrectly about this exercise. now I have no clue why we are generating a random number between 0 and body-parts-size-sum. it doesn't seem to represent anything.
ahh I get it... the target represents the actual part being hit rather than the difficulty...
I'd say that target
represents the point where the hit lands if you lay out all the body parts in a single line.
isn't it much more intuitive to have a fixed body-size-sum target and pick parts randomly to accumulate, than to have a random target and then "discover" the correct part over iterating over the parts list?
Well, the fact that I can't understand what it means somewhat hints that it's less intuitive. :) Perhaps if you write an actual impl and share it I'll be able to get it.
something like this:
(defn alt-hit
[asym-body-parts]
(let [sym-parts (better-symmetrize-body-parts asym-body-parts)
body-part-size-sum (reduce + (map :size sym-parts))
target body-part-size-sum]
(loop [accumulated-size 0
selected-part nil]
(if (> accumulated-size target)
selected-part
(let [new-part (rand-nth sym-parts)]
(recur (+ accumulated-size (:size new-part)) new-part))))))
The original is like "model the vector of maps as a line and walk over it to see which part corresponds to the random target", mine is: "pick parts randomly until you exceed the totality of the body, larger parts have a bigger prob surpassing the threshold and getting "hit"". mine feels more like blackjack and i find it easier to reason about. I guess I don't like that the original code separates the "weighting" from the "random selection", in my impl everything happens at the part level and feels more integrated.
The distribution of the "ants" version if quite clearly exactly what the weights specify. The distribution of you version is unclear. Suppose you have two parts of size 1 and 2. The total amount of combinations is 8 (I'm too lazy to think about it, I just drew all the options). The part of size 2 is selected 4 times, the part of size 1 is also selected 4 times. So all the weighing had absolutely no effect.
two parts of 1 and 2 each or two parts in total one size 1 and the other size 2?
Here are all the combos:
(2, 2)
(1, 1, 2)
(1, 2, 1)
(2, 1, 1)
(1, 2, 2)
(2, 1, 2)
(1, 1, 1, 1)
(1, 1, 1, 2)
size 1 has a 3/8 chance to get hit
size 2 has a 5/8 chance to get hitAh, you're right - I should've used a differently colored pen for a vertical line. :) But is it that obvious that it is the case for all other size combinations? It's certainly not obvious to me, and the "roulette" variant is definitely obvious. It's just a step in the Monte Carlo method.
every time you are at (target -1) + n
you have a 100% chance of going over if n is 2 instead of 1 therefore no matter what the target is, the combinations that result in going over will favor the 2. try this to verify it with different combinations:
https://paste.rs/td0Tu.py
It might be so, but as I said - it's anything but obvious, at least to me. Perhaps there are areas where such an algorithm is common, but I don't know them. Whereas that method from "ants" is literally Monte Carlo, just in reverse - instead of randomly placing dots to find a distribution, you specify a distribution and randomly place a dot to select the bin. We've used it in school to find the value of pi.
Hold on. Maybe I'm not thinking straight, but you said: > size 1 has a 3/8 chance to get hit > size 2 has a 5/8 chance to get hit If sizes are weights, then we can normalize them to a total of 1, then weights become probabilities. 1 becomes 0.(3), 2 becomes 0.(6). Whereas 3/8 is 0.375 and 5/8 is 0.625.
In other words, if there are two body parts where one part is twice as large as the other part, the larger part should be hit twice as often. 5/8 is not twice as large as 3/8.
indeed, I think this has to do with the fact that in my implementation the order of parts introduces some bias. For larger numbers and more parts, I think the accumulate method would tend to converge closer to the probabilities of the random target method.
Are PWAs still a thing? I am thinking of creating an android app for a small web app and thinking if I should pursue the PWA direction or learn some hybrid framework?
isn't pwa just an app that loads a different amount of visuals depending on the ability of the device?
Its basically a web-app cached on the users device, which can be launched via a shortcut, rather than opening it in a browser.
only in EU I think?
I have a vague memory that they walked back that bit of aggression...?
They unkilled them yes
But, only in the EU it seems. YMMV
> I am thinking of creating an android app Apple isn't relevant in this case. --- I haven't done much with PWAs other than adding a manifest file so people can install it from the browser menu, but if you're only targeting Android then I think it's definitely worth looking into. (and as for ios, https://open-web-advocacy.org/walled-gardens-report/ is a good read)
I think Apple allowed pushes for PWA: https://developer.apple.com/documentation/usernotifications/sending-web-push-notifications-in-web-apps-and-browsers, but not sure how it works in practice, never got around to build a PWA app after their changes.
Recently I was to making a choice between PWA and React Native. Ended up using the latter and have no regrets. Each PWA demo I saw was really lacking in offline usability and persistent storage, despite both of these things being advertised as strengths. Overall, I am quite content with the combination of react native + nativewind (native widgets using tailwind for styling; works on PC and mobile). Deploying with Expo means you can build for both iOS and Android even if you dont own the corresponding device (but there are extra requirements for code signing on each platform)
I'm currently working on a PWA. Push notifications work and I've tested this with multiple users. There's also this to deploy to app stores https://github.com/pwa-builder/PWABuilder I haven't deployed it yet on the app stores (will very soon) but I have made an APK that works.