Как сделать чтобы ответ примера всегда был целым и был в заданном диапазоне?
Как сделать так, чтобы ответ примера всегда был цельным и был в диапазоне от 0 до 100?
Код:
function rn() {
return Math.floor(Math.random() * 100);
}
function example_generator(level) {
const operator = {
0: Math.random() > 0.5 ? '+' : '-',
1: '*',
2: '/',
3: '%',
4: `% ${this.rn()} ${
[Math.random() > 0.5 ? '+' : '-', '*', '/'][
Math.floor(Math.random() * 4)
]
}`,
};
return `${this.rn()} ${operator[level]} ${this.rn()}`;
}
console.log(example_generator(0));
console.log(example_generator(1));
console.log(example_generator(2));
console.log(example_generator(3));
console.log(example_generator(4));
Ответы (4 шт):
function rn() {
return Math.floor(Math.random() * 100);
}
function example_generator(level) {
const operator = {
0: Math.random() > 0.5 ? '+' : '-',
1: '*',
2: '/',
3: '%',
4: `% ${this.rn()} ${
[Math.random() > 0.5 ? '+' : '-', '*', '/'][
Math.floor(Math.random() * 3)
]
}`,
};
let exp = `${this.rn()} ${operator[level]} ${this.rn()}`;
var r = eval(exp);
if (r < 0)
exp = `${exp} + ${-r}`;
if (r > 100)
exp = `${exp} - ${r-100}`;
return exp;
}
console.log(example_generator(0));
console.log(example_generator(1));
console.log(example_generator(2));
console.log(example_generator(3));
console.log(example_generator(4));
Все числа, результат и все промежуточные результаты от 1 до 100 включительно.
А вот удачность распределения не гарантирую. Вполне возможно, что некоторые комбинации выпадают чаще других.
function rand(min, max) {
return min + ~~(Math.random() * (max - min + 1))
}
var fs = {
'+'(min = 1, max = 100, lim = 100) {
var x = rand(min, max - 1)
var y = rand(1, max - x)
return [x + y, `${x} + ${y}`]
},
'-'(min = 1, max = 100, lim = 100) {
var x = rand(min + 1, lim)
var y = rand(Math.max(1, x - max), x - min)
return [x - y, `${x} - ${y}`]
},
'*'(min = 1, max = 100, lim = 100) {
if (min !== 1) throw new Error("Not implemented")
var x = rand(1, max) // TODO: поменять распределение
var y = rand(1, max / x | 0)
return [x * y, `${x} * ${y}`]
},
'/'(min = 1, max = 100, lim = 100) {
if (min !== 1) throw new Error("Not implemented")
var r = rand(1, max) // TODO: поменять распределение
var y = rand(1, max / r | 0)
var x = r * y
return [x / y, `${x} / ${y}`]
},
'%'(min = 1, max = 100, lim = 100) {
var x = rand(1, lim)
var y = rand(min + 1, max)
if (x % y < min && (x += min) % y < min) x = min
return [x % y, `${x} % ${y}`]
},
'*+'(min = 1, max = 100, lim = 100) {
var [x, e] = this['*'](min, max - 1, lim)
var y = rand(1, max - x)
return [x + y, `${e} + ${y}`]
},
'*-'(min = 1, max = 100, lim = 100) {
var [x, e] = this['*'](min, max, lim)
var y = rand(Math.max(1, x - max), x - min)
return [x - y, `${e} - ${y}`]
},
}
var levels = [
['+', '-'],
['*'],
['/'],
['%'],
['*+', '*-'],
]
function randof(arr) {
return arr[Math.random() * arr.length | 0]
}
function generate(lev) {
return fs[randof(levels[lev])]()
}
setInterval(() => {
var lev = Math.random() * levels.length | 0
var [r, e] = generate(lev)
if ((0,eval)(e) !== r) throw new Error(`${e} is not equal to ${r}`)
console.log(`[${lev}] ${e} = ${r}`)
}, 1000)
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
Все числа, результат и все промежуточные результаты от 1 до 100 включительно. Требуется предподсчёт некоторых значений, но в дальнейшем генерация работает быстро.
Распределение довольно хорошее. Для простых случаев (уровни 0-3) равномерное, для сложных (4-7) - равномерное по второй операции и равномерное среди способов получить её первый аргумент (но не равномерное относительно всех возможных примеров). Если добавить веса, то можно допилить до полностью равномерного.
var lim = 100
var ops = {
'+': [],
'-': [],
'*': [],
'/': [],
'%': [],
}
var byRes = {
'+': Array(lim + 1),
'-': Array(lim + 1),
'*': Array(lim + 1),
'/': Array(lim + 1),
'%': Array(lim + 1),
}
var fs = {
'+'(x, y) { return x + y },
'-'(x, y) { return x - y },
'*'(x, y) { return x * y },
'/'(x, y) { return x / y },
'%'(x, y) { return x % y },
}
~function prepare() {
for (var x=1; x<=lim; ++x) {
for (var y=1; y<=lim; ++y) {
for (var op of Object.keys(fs)) {
var res = fs[op](x, y)
if (res >= 1 && res <= lim && res === ~~res) {
ops[op].push([op, x, y])
void (byRes[op][res] = byRes[op][res] || []).push([op, x, y])
}
}
}
}
var missing = 0
for (var res=1; res<=lim; ++res) {
for (var op of Object.keys(byRes)) {
if (!(res in byRes[op])) {
console.log(`Unable to get ${res} using '${op}'`)
++missing
}
}
}
if (missing > 3) { // +1, -100, %100
throw new Error("The map is incomlete, consider reworking algorithm")
}
}()
function randof(...arrs) {
var len = arrs.reduce((r, a) => r + a.length, 0)
var i = Math.random() * len | 0
return arrs.find(a => i < a.length || (i -= a.length, false))[i]
}
var simpleLevels = [
[ops['+'], ops['-']],
[ops['*']],
[ops['/']],
[ops['%']],
]
function generate(lev) {
if (lev < simpleLevels.length) {
var [op, x, y] = randof(...simpleLevels[lev])
return [fs[op](x, y), `${x} ${op} ${y}`]
}
var lev2 = 0
var levOp1 = '*/%'[lev - simpleLevels.length]
while(1) {
var [op2, l, z] = randof(...simpleLevels[lev2])
if (!byRes[levOp1][l]) {
console.log(`Retry at level ${lev}`) // Очень редко
continue
}
var [op1, x, y] = randof(byRes[levOp1][l])
return [fs[op2](fs[op1](x, y), z), `${x} ${op1} ${y} ${op2} ${z}`]
}
}
var LEVELS_COUNT = simpleLevels.length * 2 - 1
setInterval(() => {
var lev = Math.random() * LEVELS_COUNT | 0
var [r, e] = generate(lev)
if ((0,eval)(e) !== r) throw new Error(`${e} is not equal to ${r}`)
console.log(`[${lev}] ${e} = ${r}`)
}, 1000)
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
Допиленый ответ @Igor ` а
function rn() {
return Math.floor(Math.random() * 100);
}
function generator(level) {
const operator = {
0: Math.random() > 0.5 ? '+' : '-',
1: '*',
2: '/',
3: '%',
4: `% ${rn()} ${
[Math.random() > 0.5 ? '+' : '-', '*', '/'][Math.floor(Math.random() * 3)]
}`,
};
let exp = `${rn()} ${operator[level]} ${rn()}`;
var r = eval(exp);
if (r < 0 || r > 100 || r.toFixed(0) != r) {
return generator(level);
}
return [r, exp];
}
const zero = generator(0);
const one = generator(1);
const two = generator(2);
const three = generator(3);
const four = generator(4);
console.log(`${zero[1]} = ${zero[0]}`);
console.log(`${one[1]} = ${one[0]}`);
console.log(`${two[1]} = ${two[0]}`);
console.log(`${three[1]} = ${three[0]}`);
console.log(`${four[1]} = ${four[0]}`);