Fork me on GitHub
#braveandtrue
<
2018-08-21
>
moo17:08:07

anyone working through the do-stuff chapter?

moo17:08:39

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

moo17:08:24

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

manutter5117:08:21

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

moo19:08:26

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

moo19:08:15

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

fellshard21:08:11

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

moo21:08:51

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

moo21:08:02

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

moo21:08:18

; 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))))))))

moo21:08:11

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

moo21:08:20

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

moo21:08:26

or … more likely, I don’t get it

manutter5122:08:15

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.

manutter5122:08:33

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."

manutter5122:08:59

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.

manutter5122:08:12

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.

manutter5122:08:51

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

manutter5122:08:44

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 

manutter5122:08:40

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

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

manutter5122:08:36

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.

manutter5123:08:29

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.

manutter5123:08:40

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

moo23:08:26

@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 ]

moo23:08:34

also, thanks so much for making that explanation.

moo23:08:54

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