最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - A counter keeping track of multiple values inside an array - Stack Overflow

programmeradmin6浏览0评论

This seems sort of plex so I'll do my best to be as clear as possible.The particular function I'm looking for dynamically creates a money spent | money won chart for a game of gambling.

I have a lottery of sorts that the user can bet on. There are 6 items the user can buy which each have 6 prizes:

These can be put into objects or arrays.

var prices = [5,10,28,50,56,280].

var possibleWins = [40,80,250,400,500,2500]

I'm trying to create a chart that calculates how much money you would have to spend on each particular item per game to guarantee you gain money - for 300 games out.

So here is an example of how the chart should start off:

investment = max possible winnings + total spent( which is negative )

The 2nd row is assuming the first game already happened and lost. And so on.

The idea is to start with the smallest item but give up once it can no longer get you positive even if you win. This is why on row 9 we switch to the rock. ( our investment is at 0 and if we play a twig again, the most we can win is 40. So even if we did win, we would actually have lost 5 overall. )

Also worth pointing out is that if you win on 1 item; you win on all items for that particular game. So you get all prizes bined.

I've been working on this for a few days now and some of these related questions have my initial attempts ( but I honestly have no idea ):

How to find the lowest possible bination of keys within an array

Counter that generates the lowest sum from a bination of indexes above the previous value

Add an arrays keys to themselves until exceeding a limit?

EDIT: At least 1 item(s) must be bought every game and games cannot be skipped

This seems sort of plex so I'll do my best to be as clear as possible.The particular function I'm looking for dynamically creates a money spent | money won chart for a game of gambling.

I have a lottery of sorts that the user can bet on. There are 6 items the user can buy which each have 6 prizes:

These can be put into objects or arrays.

var prices = [5,10,28,50,56,280].

var possibleWins = [40,80,250,400,500,2500]

I'm trying to create a chart that calculates how much money you would have to spend on each particular item per game to guarantee you gain money - for 300 games out.

So here is an example of how the chart should start off:

investment = max possible winnings + total spent( which is negative )

The 2nd row is assuming the first game already happened and lost. And so on.

The idea is to start with the smallest item but give up once it can no longer get you positive even if you win. This is why on row 9 we switch to the rock. ( our investment is at 0 and if we play a twig again, the most we can win is 40. So even if we did win, we would actually have lost 5 overall. )

Also worth pointing out is that if you win on 1 item; you win on all items for that particular game. So you get all prizes bined.

I've been working on this for a few days now and some of these related questions have my initial attempts ( but I honestly have no idea ):

How to find the lowest possible bination of keys within an array

Counter that generates the lowest sum from a bination of indexes above the previous value

Add an arrays keys to themselves until exceeding a limit?

EDIT: At least 1 item(s) must be bought every game and games cannot be skipped

Share Improve this question edited May 23, 2017 at 12:34 CommunityBot 11 silver badge asked Oct 26, 2016 at 6:29 user4330208user4330208 1
  • @carbo0nshel1 Do any of the present Answers resolve Question? – guest271314 Commented Dec 25, 2016 at 4:35
Add a ment  | 

3 Answers 3

Reset to default 9 +100

Basically this proposal relies on a function to get the next items

    getItems = function () {
        var price = 0,
            array = lottery.map(function (a) { return a.price; });

        return function () {
            var items;
            do {
                items = bine(array, price);
                price++;
            } while (!items.length)
            return items;
        }
    }(),

which starts at price with zero and increments the value by one until a bination of items is found. Then the items array is returned. The function works as generator.

The other important function is the bination of items with a given price and the try to get an array with the items.

function bine(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;
}

bine takes an array with prices and a wanted sum to reach with binating the given prices. If successfull, an array with the items is returned, otherwise an empty array.

The third part is to use the items as long as the investment is not negative. If that happens, a new items set is fetched.

function bine(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 = bine(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; }

Here is my solution

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>

You can create an object where property names are set the values of possibleWins. Set all of the possible binations of investing the limit at each round. The arrays do not contain all possible binations of numbers less than the limit for that particular round. That is, the numbers are not dispersed in every possible bination. For example, at round 40, [10, 10, 10, 10, 0, 0, 0, 0] is included as an array; though the array could also be rearranged to [10, 0, 10, 10, 0, 10, 0, 10], or other bination of indexes totaling less than 40.

Additional of the possible allowed binations less than the limit for that round be pushed to the array corresponding a specific round at the returned object.

This implementation does not attempt to locate the selection routes of each round which would lead to a positive oute. The entire set of arrays can be iterated as to each matching index in each array, bination of random indexes, or every possible bination of indexes.

The approach is a base template from which possible selections can be made. Further optional arrays containing binations of values less object property name, that is the particular round, or values within arrays from within arrays at properties of object having a property name value less than the current round, can be added to the array of arrays; to find the binations of selections which lead to the expected oute.

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);

发布评论

评论列表(0)

  1. 暂无评论