Reputation: 31
I have a program that simulates the rotation of a clock's hand and it randomly jumps 2x the normal rotation amount. I need to guarantee that in a full rotation, I get at least n jumps. How should I go about randomizing it but ensuring at least n jumps?
I thought about having a guaranteed jump every x iterations but then it's not random.
Here is the code of my rotation loop:
for (let i = 0; i < ticks; i++) {
// Move the clockhand by a position, sometimes by a greater amount
setTimeout(() => {
let d = Math.random();
jump = false;
// Randomize and keep track of jumps
if (d < (probabilty/100)) {
jump = true;
}
}
}
Upvotes: 3
Views: 136
Reputation: 1198
One way is to set a MAX_JUMPS
and MAX_TICKS
amount per full rotation then track the amount of jumps and ticks performed in each iteration. If both jumps and ticks still didn't reach their max amount then randomly choose between them. If one of them maxed out then just choose the other one untill the rotation completes.
Here is a working example in which exactly 5
jumps are guaranteed. Note that I set DISTANCE
to only 30
because the snippet console doesn't show lots of lines. Also, the time out delay is set to 0
just to quickly show the full result.
const DISTANCE = 30 // change to 60
const MAX_JUMPS = 5
const MAX_TICKS = DISTANCE - 2 * MAX_JUMPS
const PROBABILITY = 0.25
let currentDistance = 0
let normalTicks = 0
let jumps = 0
function oneTick() {
if (currentDistance === DISTANCE) {
// Completed full rotation
console.log('normalTicks = ', normalTicks, ', jumps = ', jumps)
return
}
setTimeout(() => {
if (normalTicks === MAX_TICKS) {
// If we are out of normal ticks then just jump
// to satisfy the MAX_JUMPS amount
jump()
} else if (jumps === MAX_JUMPS) {
// If we run out of jumps, do normal tick
normal()
} else {
// If both ticks and jumps are available then randomly choose one
if (Math.random() > PROBABILITY) {
normal()
} else {
jump()
}
}
console.log(currentDistance)
oneTick()
}, 0 /* change to 1000 */)
}
function normal() {
normalTicks += 1
currentDistance += 1
}
function jump() {
jumps += 1
currentDistance += 2
console.log('JUMPED! Jumps left: ', MAX_JUMPS - jumps)
}
oneTick()
.as-console-wrapper {
min-height: 200px;
top: 0;
}
EDIT: To make it do at least MAX_JUMPS
and randomly do more jumps after that just remove the if (jumps === MAX_JUMPS)
block:
const DISTANCE = 30 // change to 60
const MAX_JUMPS = 5
const MAX_TICKS = DISTANCE - 2 * MAX_JUMPS
const PROBABILITY = 0.25
let currentDistance = 0
let normalTicks = 0
let jumps = 0
function oneTick() {
if (currentDistance >= DISTANCE) {
console.log('normalTicks = ', normalTicks, ', jumps = ', jumps)
return
}
setTimeout(() => {
if (normalTicks === MAX_TICKS) {
jump()
} else {
if (Math.random() > PROBABILITY) {
normal()
} else {
jump()
}
}
console.log(currentDistance)
oneTick()
}, 0 /* change to 1000 */ )
}
function normal() {
normalTicks += 1
currentDistance += 1
}
function jump() {
jumps += 1
currentDistance += 2
console.log('JUMPED! Jumps performed: ', jumps)
}
oneTick()
.as-console-wrapper {
min-height: 200px;
top: 0;
}
Note that this may cause it to jump at the very last tick of the rotation so you will have to decide if that should count as a single tick or if the extra tick should be added to the next rotation.
Upvotes: 2