braveandtrue

https://www.braveclojure.com/
moo 2018-08-21T17:06:07.000100Z

anyone working through the do-stuff chapter?

moo 2018-08-21T17:06:39.000100Z

I’m having trouble following what’s happening within the hobbit violence section

moo 2018-08-21T17:07:24.000200Z

the (loop … ) part makes sense. But I can’t follow the let part

2018-08-21T17:54:21.000100Z

Are you doing the online version of Brave? Can you link to the part you’re having trouble with?

moo 2018-08-21T19:04:52.000100Z

Yeah, I’m doing the online version. https://www.braveclojure.com/do-things/#Hobbit_Violence

moo 2018-08-21T19:05:26.000100Z

basically I don’t quite understand let or loop/recur

moo 2018-08-21T19:08:15.000100Z

actually, maybe I’m jumping to asking questions too soon. 🙂 I’ll keep struggling some more

fellshard 2018-08-21T21:00:11.000100Z

I've set a reminder for myself to check in again once I'm off work.

moo 2018-08-21T21:30:55.000100Z

thanks!

moo 2018-08-21T21:31:33.000100Z

Back to the violence here: https://www.braveclojure.com/do-things/#Hobbit_Violence

moo 2018-08-21T21:31:51.000100Z

I think I figured it out, but I don’t understand how it weights the hits based on the body part size

moo 2018-08-21T21:32:02.000200Z

I tried to put comments to explain what I think is happening

moo 2018-08-21T21:32:18.000100Z

; here we define a function called hit that takes one parameter asym-body-...;
; it's going to return the body part that we want to hit
(defn hit 
  [asym-body-parts]

  ; let defines 3 scoped variables, it looks like it happens in order
  ; first, sym-parts is defined as the output of the better-sym... function
  ; second, body-part-size is the sum of all body parts
  ; target is a number < body-part-size...
  (let [sym-parts (better-symmetrize-body-parts asym-body-parts)
        body-part-size-sum (reduce + (map :size sym-parts))
        target (rand body-part-size-sum)]
    
    ; now we start he loop, the [[]] causes destructuring, we take just the 
    ; first element from sym parts and assign it to "part" and "remaining"
    ; for tail-recursion
    ; we accumulate size 
    (loop [[part & remaining] sym-parts
           accumulated-size (:size part)]
      (if (> accumulated-size target)
        ; if acc-size > target, then we've found a large enough body part
        part
        ; otherwise recurse and add up the size of the next remaining item
        (recur remaining (+ accumulated-size (:size (first remaining))))))))

moo 2018-08-21T21:33:11.000100Z

it seems to me like this will hit the next body part in the list after the accumulated weight of those parts listed beforehand reaches the target

moo 2018-08-21T21:33:20.000100Z

so it’s not exactly a weighted likelihood of hitting a larger part

moo 2018-08-21T21:33:26.000100Z

or … more likely, I don’t get it

2018-08-21T22:44:15.000100Z

No, I think you're understanding it correctly. Maybe it would help to picture it graphically. Imagine we've got 4 body parts of different sizes, represented by an vector like this: [1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 3 3 3 4 4 ]. Body part #1 is the biggest, so it takes up twice as much space in the vector as body part #2 for example. If I've counted right, that's 20 elements in the array. So now we pick a random number between 0 and 19 (since vectors are zero based). On average, it'll pick body part 1 half the time since it occupies half the vector. Body part 2 occupies about 25% of the vector, so it would get picked a quarter of the time.

2018-08-21T22:45:33.000100Z

So the code above is basically walking through the vector and saying "Did our random target land in the first 10 element of the vector? No? Ok, let's look at the other half of the vector."

2018-08-21T22:46:59.000100Z

By subtracting 10 from the target, and dropping off the first 10 elements of the vector, we can continue to check whether the target landed in the next 5 elements, i.e. body part 2.

2018-08-21T22:48:12.000100Z

Is that clear? It all seems so clear in my head, but it's been a long day and I'm afraid I'm just confusing the issue with my graphical metaphor.

2018-08-21T22:50:51.000100Z

Let me try an even more graphical example. Suppose target is 13. So, to use my graph metaphor, that would look like this:

[1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 3 3 3 4 4 ]
[= = = = = = = = = = = = = ^             ] ;; target

2018-08-21T22:53:44.000100Z

So target is 13, and the :size of body part 1 is 10. So we know it didn't hit body part number 1, and we can discard it

[X X X X X X X X X X 2 2 2 2 2 3 3 3 4 4 ]
[X X X X X X X X X X = = ^               ] ;; target 

2018-08-21T22:54:40.000100Z

Let's just remove all those X's to clean things up.

[ 2 2 2 2 2 3 3 3 4 4 ]
[ = = ^               ] ;; target

2018-08-21T22:56:36.000100Z

So, we removed 10 from target to account for the 10 elements we deleted, since they were body part 1. That leaves us with a target of 3, and we're ready to check body part 2. The :size of body part 2 is 5, and the target is less than that, so boom, there's our hit.

2018-08-21T23:02:29.000100Z

Or another way to put it is that by subtracting the :size of body part 1 from the target of 13, we're keeping the pointer lined up with the original target.

2018-08-21T23:03:40.000100Z

Does that help or am I just muddying the waters here?

moo 2018-08-21T23:41:26.000100Z

@manutter51 that made sense. But is that vector sorted? I thought it wasn’t sorted which makes it like:

[1 1 1 1 1 1 1 2 2 3 3 3 3 3 3 3 3 3 4 4 4 5 5 5 5 5 5 5 5 5 ]

moo 2018-08-21T23:42:34.000100Z

also, thanks so much for making that explanation.

moo 2018-08-21T23:42:54.000100Z

if the vector is sorted, could you point out where that happens? (That would help me understand)