OR in a random block

I want to generate a random variable that is in 1 of 2 ranges. Either 30 to 60 OR -30 to -60. So, the number could be a value from one of either range, but not between -30 and +30. So far, I have a very long process of using %chance to choose one of the 2 ranges, then the random block to choose within that range. Is there a cleaner way to do this?

4 Likes

Is this what you want?

4 Likes

Yes! That’s much more elegant! Thanks so much!

2 Likes

Never as fast or elegant as @Blobbey, but an interesting challenge and here is my take:

2 Likes

I like this one too, but it’s a bit too complex for my students. I always like to see how other people see solutions to a challenge.

2 Likes

Hmm, that function call was really expensive.

Here’s a last take which is at least relatively fast, but just as many LOC cluttering On start() as your original solution.

(Please remove the loop and millis, this was just me playing around to benchmark the different solutions’ relative speeds)

I guess @Blobbey’s solution stands as the neatest and best used for teaching students. I am really surprised that it also performs relatively well compared to a function(even an almost empty function), with its 2-dimensional array created and populated for every iteration, 3 random operations and one traversal of and lookup in array…). What is a day without learning something new? :wink:

I would like to see somebody come up with an even more optimized solution; short, beautiful AND blazing fast! :wink:

I have to admit, Vegz78, your solution was a bit over my head. I’d have to really explore it to understand it. What is the speed that you are timing? The speed that the variable is selected or the speed until it populates the sprite in level 2 with a random velocity? I am not sure I’d even notice that.

1 Like

Looks smart. :slightly_smiling_face:

1 Like

Probably not, unless you are in need of A LOT of such random draws within those special ranges…

Yeah, it was initially an attempt to get the ranges you were looking for with only 1 throw of the dice pr. number in such special ranges which are on both sides of 0, but not continuous across 0, which quickly grew very complex when trying to figure it out. Not a very neat solution. But since the distribution should be uniform, it probably doesn’t matter with multiple random draws pr. number produced.

I am timing(or attempting to time) from just before to just after a large loop which which draws a huge number of random numbers inside those special ranges and storing it to the Random1 variable. Given that there are now 4 solutions presented, including your initial one, I got curious about their relative speeds.

Then I was surprised about how much time my first solution used, and closer investigation pointed me towards that it was the function call itself that spent most of the time, not the overly complex algorithm. I knew that function calls have a cost, but I did not know it was such a huge relative cost(but insignificant and more than fast enough for most use cases and programs, as you point out, except when there is a very high number of iterations…)

Just for the special geeky interest of it, I posted these results, because maybe someone a) had a better algorithm or b) more information/experience to share about the relatively slow function calls in MakeCode?

I should have posted only my last solution without all the measurement code, and the function part in its own thread. Sorry for hijacking/steering your thread a little away from its initial direction. :wink:

1 Like

I do a variation of your original algorithm: Pick a random value and, half the time, change it to a negative value.

@Blobbey 's version, though, seems easier to understand.

4 Likes

Wow, now that’s clean. Gotta be my favorite implementation so far!

2 Likes

No, I appreciate the details, it helps me (and likely others) learn! I love wandering into a thread that has someone’s though processes explained. It may not be useful for THIS problem, but someone, somewhere is going to need this bit of code.

3 Likes

Oh, this is an elegant solution! It would be really great for my students! Array’s are a bit harder to explain, whereas this is basic math that would be easier to understand for 10 yr olds! Thanks for sharing.

4 Likes

Okay, I can’t resist any longer, I must chime in with my take on the problem

Instead of doing two separate random generations, I instead set a negative multiplier half the time, generate a number from 30-60 and then multiply it with the multiplier. This way, half of the time the result is negative, achieving the desired effect.

BTW, I like how this thread has become a race of sorts to create the quickest and most elegant solution possible for this :smiley:

6 Likes

Nice!

But isn’t the <50% chance> equivalent to something like <pick_random(0, 1) = 1>, thus still having two random generations, like this?:
image

(pluss, the <50% chance> seems a bit slower than a <pick_random(0, 1) = 1> for some unknown reason…) :wink:

How about this (un)intuitive monster?:

You could drop the stop variable and range calculation, and operate instead only with start = 40 and range = 50 directly.

Me too! There’s a special beauty to an algorithm developing into its optimal self, especially through joint effort!

Here’s a collection of most of the contributions so far, with a testing loop:
https://makecode.com/_PLAL2RKL3ggd

1 Like


Here’s my take on this problem. It’s very similar to the other ones others have made, but I just wanted to post a more simple solution

2 Likes

Wait a minute, this is just the same thing as what @AlexK did, just a bit shuffled…
I’m sorry y’all I guess I misread his algorithm, I’m sorry it was like 2AM idk what I was even thinking then :sweat_smile:

2 Likes

3 Likes

Beautiful!

1 Like

Pure math, eh?