Счетчик, отслеживающий несколько значений внутри массива
Это кажется сложным, поэтому я сделаю все возможное, чтобы быть как можно более ясным. Специальная функция, которую я ищу динамически, создает потраченные деньги | деньги выиграли график для игры в азартные игры.
У меня есть лотерея, на которую пользователь может делать ставки. Есть 6 предметов, которые пользователь может купить, каждый из которых имеет 6 призов:
![введите описание изображения здесь]()
Они могут быть помещены в объекты или массивы.
var prices = [5,10,28,50,56,280]
.
var possibleWins = [40,80,250,400,500,2500]
Я пытаюсь создать диаграмму, которая вычисляет, сколько денег вам нужно потратить на каждый конкретный предмет за игру, чтобы гарантировать вам заработать деньги - за 300 игр.
Итак, вот пример того, как начать диаграмму:
![введите описание изображения здесь]()
investment = максимально возможные выигрыши + общая сумма (отрицательная)
Вторая строка предполагает, что первая игра уже была и проиграна. И так далее.
Идея состоит в том, чтобы начать с самого маленького предмета, но отказаться от него, когда он больше не сможет получить положительный результат, даже если вы выиграете. Вот почему в строке 9 мы переключаемся на рок. (наши инвестиции равны 0, и если мы снова сыграем в twig, мы можем выиграть всего 40. Так что, даже если бы мы выиграли, мы бы проиграли всего 5.)
Также стоит отметить, что если вы выиграете на 1 пункт; вы выигрываете по всем предметам для этой конкретной игры. Таким образом, вы получаете все призы вместе.
Я работаю над этим в течение нескольких дней, и некоторые из этих связанных вопросов имеют мои первоначальные попытки (но я честно не знаю):
Как найти минимально возможную комбинацию ключей внутри массива
Счетчик, который генерирует самую низкую сумму из комбинации индексов выше предыдущего значения
Добавить ключи массивов для себя до превышения лимита?
РЕДАКТИРОВАТЬ: по крайней мере 1 предмет должен быть куплен в каждой игре, и игры не могут быть пропущены
Ответы
Ответ 1
В основном это предложение основывается на функции для получения следующих элементов
getItems = function () {
var price = 0,
array = lottery.map(function (a) { return a.price; });
return function () {
var items;
do {
items = combine(array, price);
price++;
} while (!items.length)
return items;
}
}(),
который начинается с цены с нулем и увеличивает значение на единицу до тех пор, пока не будет найдено комбинация элементов. Затем возвращается массив items
. Функция работает как генератор.
Другая важная функция - это комбинация предметов с заданной ценой и попытка получить массив с элементами.
function combine(array, sum) {
function c(left, right, sum) {
if (!sum) {
result = right;
return true;
}
return left.some(function (a, i, aa) {
return a <= sum && c(aa.slice(i + (a > sum - a)), right.concat(a), sum - a);
});
}
var result = [];
c(array.sort(function (a, b) { return b - a; }), [], sum);
return result;
}
combine
берет массив с ценами и требуемой суммой, чтобы достичь с комбинацией данных цен. Если успешно, возвращается массив с элементами, в противном случае - пустой массив.
Третья часть - использовать элементы, пока инвестиции не являются отрицательными. Если это произойдет, выберем новый набор элементов.
function combine(array, sum) {
function c(left, right, sum) {
if (!sum) {
result = right;
return true;
}
return left.some(function (a, i, aa) {
return a <= sum && c(aa.slice(i + (a > sum - a)), right.concat(a), sum - a);
});
}
var result = [];
c(array.sort(function (a, b) { return b - a; }), [], sum);
return result;
}
var lottery = [{ name: 'twig', price: 5, win: 40 }, { name: 'rock', price: 10, win: 80 }, { name: 'shell', price: 28, win: 250 }, { name: 'chip', price: 50, win: 400 }, { name: 'gold', price: 56, win: 500 }, { name: 'diamond', price: 280, win: 2500 }],
lotteryByPrice = lottery.reduce(function (r, a) { r[a.price] = a; return r; }, Object.create(null)),
getItems = function () {
var price = 0,
array = lottery.map(function (a) { return a.price; });
return function () {
var temp;
do {
temp = combine(array, price);
price++;
} while (!temp.length)
return temp;
}
}(),
createTableRow = function (element) {
var table = document.createElement('table'),
tr = document.createElement('tr');
['Game', 'Items', 'Types', 'Spend Per Game', 'Total Spend', 'Max. Possible Winnigs', 'Investment'].forEach(function (a) {
var th = document.createElement('th');
th.appendChild(document.createTextNode(a));
tr.appendChild(th);
});
table.appendChild(tr);
element.appendChild(table);
return function (row) {
var tr = document.createElement('tr');
['game', 'items', 'types', 'spend', 'total', 'potential', 'investment'].forEach(function (k) {
var td = document.createElement('td');
td.appendChild(document.createTextNode(row[k]));
tr.appendChild(td);
});
if (row.topBorder) {
tr.style.borderTop = '2px solid #666';
}
table.appendChild(tr);
};
}(document.body),
row = { game: null, items: null, types: null, spend: null, total: 0, potential: null, investment: null },
i,
items = getItems(),
add = function (a, b) { return a + b; },
winP = function (a) { return lotteryByPrice[a].win; },
nameP = function (a) { return lotteryByPrice[a].name; };
for (i = 1; i <= 70; i++) {
row.topBorder = false;
while (row.total - items.reduce(add) + items.map(winP).reduce(add) < 0) {
items = getItems();
row.topBorder = true;
}
row.game = i;
row.items = items.length;
row.types = items.map(nameP).join(' + ');
row.spend = -items.reduce(add);
row.total += row.spend;
row.potential = items.map(winP).reduce(add);
row.investment = row.potential + row.total;
createTableRow(row);
}
table { border-collapse: collapse; font-family: Sans-Serif; }
th { border: 1px solid #ccc; padding: 0 10px; }
td { text-align: center; border: 1px solid #ccc; }
Ответ 2
Вот мое решение
let items = [{
name: 'twig',
price: 5,
win: 40
}, {
name: 'rock',
price: 10,
win: 80
}, {
name: 'shell',
price: 28,
win: 250
}, {
name: 'chip',
price: 50,
win: 400
}, {
name: 'gold',
price: 56,
win: 500
}, {
name: 'diamond',
price: 280,
win: 2500
}];
let moves = [];
Move.prototype.numberItems = function() {
let count = 0;
for (let n = 0; n < 6; n++) {
count += this.counts[n];
}
return count;
}
Move.prototype.nameItems = function() {
let name = '';
for (let n = 0; n < 6; n++) {
for (let x = 0; x < this.counts[n]; x++) {
if (name != '') {
name += ' - ';
}
name += items[n].name;
}
}
return name;
}
Move.prototype.getWin = function() {
let win = 0;
for (let n = 0; n < 6; n++) {
win += this.counts[n] * items[n].win;
}
return win;
}
function Move(cost, counts) {
this.cost = cost;
this.counts = counts.slice();
}
function run() {
createMoves(100);
moves.sort(function(a, b) {
return (a.cost - b.cost);
});
print();
}
function createMoves(maxCost) {
let counts = [];
for (let n = 0; n < 6; n++) {
counts.push(0);
}
counts[0] ++;
while (true) {
let cost = whatCost(counts);
if (cost < maxCost) {
moves.push(new Move(cost, counts));
counts[0] ++;
continue;
}
if (!escalate(counts)) {
break;
}
}
}
function whatCost(counts) {
let cost = 0;
for (let n = 0; n < 6; n++) {
cost += counts[n] * items[n].price;
}
return cost;
}
function escalate(counts) {
for (let n = 0; n < 5; n++) {
if (counts[n] != 0) {
counts[n] = 0;
counts[n + 1] ++;
return true;
}
}
return false;
}
function print() {
let domResult = document.getElementById('results');
let game = 1;
let moveInx = 0;
let spent = 0;
for (let moveInx = 0; moveInx < moves.length; moveInx++) {
let myMove = moves[moveInx];
let items = myMove.numberItems();
let win = myMove.getWin();
let cost = myMove.cost;
for (let repeat = 1;; repeat++) {
let investment = win - spent - cost;
if (investment < 0) {
break;
}
spent += cost;
let row = document.createElement('tr');
if (repeat == 1) {
row.className = 'first';
}
let cell = document.createElement('td');
cell.innerHTML = game;
row.appendChild(cell);
cell = document.createElement('td');
cell.innerHTML = items;
row.appendChild(cell);
cell = document.createElement('td');
cell.innerHTML = myMove.nameItems();
row.appendChild(cell);
cell = document.createElement('td');
cell.innerHTML = cost;
row.appendChild(cell);
cell = document.createElement('td');
cell.innerHTML = spent;
row.appendChild(cell);
cell = document.createElement('td');
cell.innerHTML = win;
row.appendChild(cell);
cell = document.createElement('td');
cell.innerHTML = win - spent;
row.appendChild(cell);
domResult.appendChild(row);
game++;
if (game > 300) {
return;
}
}
}
}
table {
border-collapse: collapse;
}
tr * {
border: solid 1px black;
}
.first {
border-top: solid 4px blue;
}
<button onclick="run()">Run</button>
<table>
<thead>
<tr>
<th>Game</th>
<th>Items</th>
<th>Types</th>
<th>Spent</th>
<th>Total Spent</th>
<th>Max win</th>
<th>Profit</th>
</tr>
</thead>
<tbody id="results">
</tbody>
</table>
Ответ 3
Вы можете создать объект, в котором именам свойств заданы значения possibleWins
. Установите все возможные комбинации вложения лимита в каждом раунде. Массивы не содержат всех возможных комбинаций чисел, меньших предела для этого конкретного раунда. То есть цифры не разбросаны во всех возможных сочетаниях. Например, при раунде 40
, [10, 10, 10, 10, 0, 0, 0, 0]
включается как массив; хотя массив также может быть перенесен на [10, 0, 10, 10, 0, 10, 0, 10]
или другую комбинацию индексов, суммарно меньше 40
.
Дополнительные возможные допустимые комбинации, меньшие, чем limit
для этого раунда, будут перенесены в массив, соответствующий конкретному раунду на возвращаемом объекте.
Эта реализация не пытается найти маршруты выбора каждого раунда, что приведет к положительному результату. Весь набор массивов можно повторить по каждому совпадающему индексу в каждом массиве, комбинации случайных индексов или любой возможной комбинации индексов.
Подход - это базовый шаблон, из которого можно сделать возможный выбор. В массив массивов могут быть добавлены дополнительные необязательные массивы, содержащие комбинации значений меньше имени свойства объекта, то есть конкретного раунда, или значения внутри массивов из массивов в свойствах объекта, имеющего значение имени свойства меньше текущего раунда; чтобы найти комбинации выборов, которые приводят к ожидаемому результату.
const [prices, possibleWins] = [
[5, 10, 28, 50, 56, 280],
[40, 80, 250, 400, 500, 2500]
];
const counteropts = (prices, possibleWins) => {
let rounds = {};
for (let price of prices) {
let [chance, limit] = [[], possibleWins[prices.indexOf(price)]];
for (let buyin = price - price; buyin <= limit; buyin += price) {
chance[chance.length] = buyin;
}
if (chance[chance.length - 1] !== limit) {
chance = [...chance, limit]
}
for (let odd of Array.of(chance)) {
let options = Array();
for (let choice of odd) {
options[options.length] = [...odd.map(
v => v !== choice && v + choice <= limit ? v + choice : 0
)];
if (options.length === prices.length -1) {
for (let option of options[0]) {
let keys = options[0].map((_, index) => index + 1)
.filter(key => key * option <= limit);
let opt = Array(keys.length).fill(option);
options = [...options
, opt.length < options[0].length
? [...opt, ...Array(options[0].length - opt.length).fill(0)]
: opt
];
}
rounds[limit] = [...options];
}
}
}
}
return rounds
}
let opts = counteropts(prices, possibleWins);
console.log(opts);