Random Numbers

yeah that was basically exactly what I would suggest. Here's rough code, untested.
const x = ...;
let allowedNumbers = Array.from(new Array(360)).map((_, i) => i + 1).filter(i => Math.abs(x - i) > 15 && Math.abs(x - i) < 100 && (i < 50 || i > 150));
const pickedNumbers = [];

function generateNumber() {
const randomChoiceIndex = Math.floor(Math.random() * allowedNumbers.length);
const randomChoice = allowedNumbers[randomChoiceIndex];
pickedNumbers.push(randomChoice);
allowedNumbers = allowedNumbers.filter(i => Math.abs(randomChoice - i) >= 5)

return pickedNumbers;
}
const x = ...;
let allowedNumbers = Array.from(new Array(360)).map((_, i) => i + 1).filter(i => Math.abs(x - i) > 15 && Math.abs(x - i) < 100 && (i < 50 || i > 150));
const pickedNumbers = [];

function generateNumber() {
const randomChoiceIndex = Math.floor(Math.random() * allowedNumbers.length);
const randomChoice = allowedNumbers[randomChoiceIndex];
pickedNumbers.push(randomChoice);
allowedNumbers = allowedNumbers.filter(i => Math.abs(randomChoice - i) >= 5)

return pickedNumbers;
}
36 Replies
Daniel Thorp
Daniel Thorp•4y ago
Ok, I'm back to this. Any idea why after 14 to 19 executions, this just adds undefined to pickedNumbers?
LukeAbby
LukeAbbyOP•4y ago
let's see well you exclude 50-150 so that leaves 0-49 and 151-360 (which btw why does it go up to 360 and not 256)
Daniel Thorp
Daniel Thorp•4y ago
Hue is in degrees
LukeAbby
LukeAbbyOP•4y ago
ah using hue gotcha okay so that's 50 + 210 = 260 possibilities left unexcluded BUT x excludes at least... 30 possibilities (less than or equal to 15)
Daniel Thorp
Daniel Thorp•4y ago
Ok, that makes sense since 260/15 is 17.3
LukeAbby
LukeAbbyOP•4y ago
right it's because you're basically running out of valid colours to pick from after you've generated enough hues for a full colour palette you can reset allowedNumbers to the initial value I showed
Daniel Thorp
Daniel Thorp•4y ago
I guess I can just "loop" the colors. i.e. after 14 colors, it starts reusing colors
LukeAbby
LukeAbbyOP•4y ago
well it starts reusing the domain of allowed hues it's still going to be generating randomly it's just that you're excluding hues close to ones you've generated before meaning you run out fast
Daniel Thorp
Daniel Thorp•4y ago
It would be best to have a dynamic tolerance for closeness. i.e. only check closeness of the last color generated
LukeAbby
LukeAbbyOP•4y ago
This would work work then, I believe.
const baseHue = ...;
const allAllowedHues = Array.from(new Array(360)).map((_, i) => i + 1).filter(h => Math.abs(baseHue - h) > 15 && Math.abs(baseHue - h) < 100 && (h < 50 || h > 150));
let lastHue;

function generateHue() {
let allowedHues;
if (lastHue == null) {
allowedHues = allAllowedHues;
} else {
allowedHues = allAllowedHues.filter(h => Math.abs(lastHue - h) >= 5);
}

const chosenHueIndex = Math.floor(Math.random() * allowedNumbers.length);
const chosenHue = allowedHues[chosenHueIndex];

lastHue = chosenHue;

return chosenHueIndex;
}
const baseHue = ...;
const allAllowedHues = Array.from(new Array(360)).map((_, i) => i + 1).filter(h => Math.abs(baseHue - h) > 15 && Math.abs(baseHue - h) < 100 && (h < 50 || h > 150));
let lastHue;

function generateHue() {
let allowedHues;
if (lastHue == null) {
allowedHues = allAllowedHues;
} else {
allowedHues = allAllowedHues.filter(h => Math.abs(lastHue - h) >= 5);
}

const chosenHueIndex = Math.floor(Math.random() * allowedNumbers.length);
const chosenHue = allowedHues[chosenHueIndex];

lastHue = chosenHue;

return chosenHueIndex;
}
I'd honestly write out allAllowedHues in a full loop and functional form, I just wrote it like that because I was doing it fast rather than nice
Daniel Thorp
Daniel Thorp•4y ago
That kept returning 0, so I switched the return value to chosenHue, but now it's just 16 and 21.
LukeAbby
LukeAbbyOP•4y ago
ah sorry you're right about chosenHueIndex -> chosenHue lemme look at the problem now what's your baseHue?
Daniel Thorp
Daniel Thorp•4y ago
0 I tried with 76 and now it's returning 1 and 6
LukeAbby
LukeAbbyOP•4y ago
lol probably got the filter wrong me that is try this:
const baseHue = 0;
const allAllowedHues = Array.from(new Array(360)).map((_, i) => i + 1).filter(h => Math.abs(baseHue - h) > 15 && Math.abs(baseHue - h) < 100 && (h < 50 || h > 150));
let lastHue;

function generateHue() {
let allowedHues;
if (lastHue == null) {
allowedHues = allAllowedHues;
} else {
allowedHues = allAllowedHues.filter(h => Math.abs(lastHue - h) >= 5);
}

const chosenHueIndex = Math.floor(Math.random() * allowedHues.length);
const chosenHue = allowedHues[chosenHueIndex];

lastHue = chosenHue;

return chosenHueIndex;
}
const baseHue = 0;
const allAllowedHues = Array.from(new Array(360)).map((_, i) => i + 1).filter(h => Math.abs(baseHue - h) > 15 && Math.abs(baseHue - h) < 100 && (h < 50 || h > 150));
let lastHue;

function generateHue() {
let allowedHues;
if (lastHue == null) {
allowedHues = allAllowedHues;
} else {
allowedHues = allAllowedHues.filter(h => Math.abs(lastHue - h) >= 5);
}

const chosenHueIndex = Math.floor(Math.random() * allowedHues.length);
const chosenHue = allowedHues[chosenHueIndex];

lastHue = chosenHue;

return chosenHueIndex;
}
Daniel Thorp
Daniel Thorp•4y ago
Nice! These seem perfect
[15, 46, 23, 40, 24, 29, 175, 24, 159, 15, 22, 164, 16, 157, 173, 157, 21, 167, 4, 44, 2, 47, 27, 38, 5, 36, 174, 44, 5, 162, 40, 166, 39, 3, 22, 1, 163, 34, 162, 44, 20, 174, 42, 159, 41, 14, 21, 157, 47, 165, 43, 158, 169, 43, 18, 49, 37, 162, 21, 2, 32, 160, 18, 153, 47, 24, 167, 2, 23, 161, 10, 166, 25, 42, 7, 161, 11, 17, 170, 13, 4, 27, 9, 15, 27, 20, 176, 34, 48, 153, 169, 18, 25, 154, 166, 31, 1, 170, 2, 27]
[15, 46, 23, 40, 24, 29, 175, 24, 159, 15, 22, 164, 16, 157, 173, 157, 21, 167, 4, 44, 2, 47, 27, 38, 5, 36, 174, 44, 5, 162, 40, 166, 39, 3, 22, 1, 163, 34, 162, 44, 20, 174, 42, 159, 41, 14, 21, 157, 47, 165, 43, 158, 169, 43, 18, 49, 37, 162, 21, 2, 32, 160, 18, 153, 47, 24, 167, 2, 23, 161, 10, 166, 25, 42, 7, 161, 11, 17, 170, 13, 4, 27, 9, 15, 27, 20, 176, 34, 48, 153, 169, 18, 25, 154, 166, 31, 1, 170, 2, 27]
LukeAbby
LukeAbbyOP•4y ago
yeah I had just a typo or two happens when I don't run the code and refactor it lol
Daniel Thorp
Daniel Thorp•4y ago
Ok, so this is my code now
// Generate the top hue from a random base
hueTop = scsApp.generateHue(Math.floor(Math.random() * 360));

// Generate the bottom hue with the top hue as the base
hueBottom = scsApp.generateHue(hueTop);
// Generate the top hue from a random base
hueTop = scsApp.generateHue(Math.floor(Math.random() * 360));

// Generate the bottom hue with the top hue as the base
hueBottom = scsApp.generateHue(hueTop);
and in the scsApp class:
// Returns an array of hues that validate certain rules from a given base hue
static allAllowedHues = base => Array.from(new Array(360)) // Hue is in degrees
.map((_, i) => i + 1) // Insert numbers into the Array from 1 to 300
.filter(h => // Filter the Array
Math.abs(base - h) > 15 // Must be sufficiently different than the base
&& Math.abs(base - h) <= 100 // Must not be too different
&& (h < 50 || h > 150) // Must not be green
);

// Last hue generated
static lastHue;

// Generate a new hue from a base hue
static generateHue(base) {

// Initialize an Array that will contain the valid hues
let validHues = [];

// If there isn't any last hue, set the valid hues to the allowed hues for the current base
if (!scsApp.lastHue) {
validHues = scsApp.allAllowedHues(base);
} else { // If there is a last hue, set the valid hues to everything that isn't within 25 from the last hue
validHues = scsApp.allAllowedHues(base).filter(h => Math.abs(scsApp.lastHue - h) >= 25);
};

// Pick the a random hue from the valid hues
let chosenHue = validHues[Math.floor(Math.random() * validHues.length)];

// Set lastHue to the chosen hue for the next generation
scsApp.lastHue = chosenHue;

return chosenHue; // Return the chosen hue
};
// Returns an array of hues that validate certain rules from a given base hue
static allAllowedHues = base => Array.from(new Array(360)) // Hue is in degrees
.map((_, i) => i + 1) // Insert numbers into the Array from 1 to 300
.filter(h => // Filter the Array
Math.abs(base - h) > 15 // Must be sufficiently different than the base
&& Math.abs(base - h) <= 100 // Must not be too different
&& (h < 50 || h > 150) // Must not be green
);

// Last hue generated
static lastHue;

// Generate a new hue from a base hue
static generateHue(base) {

// Initialize an Array that will contain the valid hues
let validHues = [];

// If there isn't any last hue, set the valid hues to the allowed hues for the current base
if (!scsApp.lastHue) {
validHues = scsApp.allAllowedHues(base);
} else { // If there is a last hue, set the valid hues to everything that isn't within 25 from the last hue
validHues = scsApp.allAllowedHues(base).filter(h => Math.abs(scsApp.lastHue - h) >= 25);
};

// Pick the a random hue from the valid hues
let chosenHue = validHues[Math.floor(Math.random() * validHues.length)];

// Set lastHue to the chosen hue for the next generation
scsApp.lastHue = chosenHue;

return chosenHue; // Return the chosen hue
};
It seems to be that I'll need to add support for two "lastHue" values or else I will get alternating top/bottom's that are the same
LukeAbby
LukeAbbyOP•4y ago
I'd simplify it to:
// Initialize an Array that will contain the valid hues
let validHues = scsApp.allAllowedHues(base);

if (scsApp.lastHue != null) {
validHues = validHues.filter(h => Math.abs(scsApp.lastHue - h) >= 25);
};
// Initialize an Array that will contain the valid hues
let validHues = scsApp.allAllowedHues(base);

if (scsApp.lastHue != null) {
validHues = validHues.filter(h => Math.abs(scsApp.lastHue - h) >= 25);
};
as for lastHues honestly it might be good practice for you to figure out a way yourself, no? I mean I'm not opposed necessarily to helping you if you're stuck
Daniel Thorp
Daniel Thorp•4y ago
Sure, I'm not here asking for help xD
LukeAbby
LukeAbbyOP•4y ago
haha
Daniel Thorp
Daniel Thorp•4y ago
just progress reports
LukeAbby
LukeAbbyOP•4y ago
gotcha looks good so far though
Daniel Thorp
Daniel Thorp•4y ago
I might ask later though 🙂
LukeAbby
LukeAbbyOP•4y ago
definitely do
Daniel Thorp
Daniel Thorp•4y ago
Is there a reason why you put != null?
LukeAbby
LukeAbbyOP•4y ago
Habit I suppose but I don't like the boolean casting
Daniel Thorp
Daniel Thorp•4y ago
Ok, I thought it was "cleaner". I'll do it that way if it's better
LukeAbby
LukeAbbyOP•4y ago
It's an opinion but if (!x) checks if it's falsy so could be expanded like so: if (x === false || x === "" || x === NaN || x === 0 || x === null || x === undefined) there's actually a handful more but idr of the top of my head whereas you probably just mean if (x === undefined || x === null) which if (x != null) 'expands' to
Daniel Thorp
Daniel Thorp•4y ago
Well, there's an issue if it equals to NaN, "", or false as well...
LukeAbby
LukeAbbyOP•4y ago
right which is why it's an opinion haha I honestly prefer it explode in my face rather than reinitialise because if I have like x is an integer I have to remember the if (!x) will trigger when it's 0 and go back to refactor the conditions
Daniel Thorp
Daniel Thorp•4y ago
Actually, shouldn't it be?
let validHues = scsApp.allAllowedHues(base);

if (scsApp.lastHue == null) {
validHues = validHues.filter(h => Math.abs(scsApp.lastHue - h) >= 25);
};
let validHues = scsApp.allAllowedHues(base);

if (scsApp.lastHue == null) {
validHues = validHues.filter(h => Math.abs(scsApp.lastHue - h) >= 25);
};
LukeAbby
LukeAbbyOP•4y ago
don't you only filter if the lastHue isn't null? here's what I mean
let lastHue;
if (lastHue == null) {
// will run
validHues = validHues.filter(h => Math.abs(lastHue - h) >= 25);
}
let lastHue;
if (lastHue == null) {
// will run
validHues = validHues.filter(h => Math.abs(lastHue - h) >= 25);
}
let lastHue = 123;
if (lastHue == null) {
// will not run
validHues = validHues.filter(h => Math.abs(lastHue - h) >= 25);
}
let lastHue = 123;
if (lastHue == null) {
// will not run
validHues = validHues.filter(h => Math.abs(lastHue - h) >= 25);
}
also wait ah nvm hue goes from 1-360 not 0-360 nvm if it included 0 you definitely couldn't do if (x)
Daniel Thorp
Daniel Thorp•4y ago
In my code here, I only filter if lastHue is truthy which translates to
if (scsApp.lastHue) { // If there is a last hue, set the valid hues to everything that isn't within 25 from the last hue
validHues = scsApp.allAllowedHues(base).filter(h => Math.abs(scsApp.lastHue - h) >= 25);
};
if (scsApp.lastHue) { // If there is a last hue, set the valid hues to everything that isn't within 25 from the last hue
validHues = scsApp.allAllowedHues(base).filter(h => Math.abs(scsApp.lastHue - h) >= 25);
};
or this right? oh, nvm
LukeAbby
LukeAbbyOP•4y ago
yeah I was trying to write up an explanation but you probably figured it out
Daniel Thorp
Daniel Thorp•4y ago
Yeah, I was mixed up, but you are right about it being != null since that's the same as == true
LukeAbby
LukeAbbyOP•4y ago
well not exactly but close let x; is actually the same as let x = undefined; but we also have null let x = null if (x == null) will trigger whenever x is set to either undefined or null (because double equals is weird)
Want results from more Discord servers?
Add your server