✅ preface

In real life, a very common scene is grabbing red envelopes. Holiday elders send red envelopes, birthday friends send blessing red envelopes, wedding friends send wedding red envelopes… There is no scene that does not run through every aspect of our lives.

However, many times there may be one or two hundred yuan in a red envelope, and we finally grabbed a few cents, it is really no harm without comparison… (No tears)

In the following article, we will achieve a wechat red envelope related bonus package function. Learn more about pa

☑️ 1. Demand analysis – bonus package problem

Suppose we now want to send a red envelope, the amount of this envelope is 100 yuan, the number of red envelopes is 10. So how do we distribute it in a way that’s fair?

So next, we from shallow to deep to achieve bonus package function.

🆙 2. Implementation version

Version 1: Cut watermelon

First attach the code:

HTML code:

<h2>Red envelope generator</h2>
<div id="setting">
  <div><label>Red envelope amount:<input id="amount" value=100.00></input></label></div>
  <div><label>Number of red packets:<input id="count" value="10"></input></label></div>
  <div><button id="generateBtn">Randomly generated</button></div>
</div>

<ul id="result">
</ul>
Copy the code

The CSS code:

#setting button {
  margin-top: 10px;
}

#result {
  padding: 0;
}

#result li {
  list-style: none;
}
Copy the code

JS code:

function generate(amount, count){
  let ret = [amount];
  
  while(count > 1) {// Select the largest piece to cut
    let cake = Math.max(... ret), idx = ret.indexOf(cake), part =1 + Math.floor((cake / 2) * Math.random()),
        rest = cake - part;
    
    ret.splice(idx, 1, part, rest);
    
    count--;
  }
  return ret;
}

const amountEl = document.getElementById('amount');
const countEl = document.getElementById('count');
const generateBtn = document.getElementById('generateBtn');
const resultEl = document.getElementById('result');

generateBtn.onclick = function(){
  let amount = Math.round(parseFloat(amountEl.value) * 100);
  let count = parseInt(countEl.value);
  
  let output = [];
  
  if(isNaN(amount) || isNaN(count) 
     || amount <= 0 || count <= 0){
    output.push('Input format is not correct! ');
  }else if(amount < count){
    output.push('Not enough money to share')}else{ output.push(... generate(amount, count)); output = output.map(m= > (m / 100).toFixed(2));
  }
  resultEl.innerHTML = '<li>' + 
                        output.join('</li><li>') +
                       '</li>';
}
Copy the code

Generally speaking, if we directly take the random way to share out the bonus package, there is a great possibility that the first direct 99 yuan, and the other may appear unable to share the problem. So, we should deal with this problem.

What about this algorithm up here, commonly known as the watermelon cutting algorithm.

Each time we divide the amount into two parts, there will always be a large part and a small part, so at this time, we pick the large part and divide it, and then we have three parts.

So let’s go ahead and take the largest of these three parts and divide them, and so on. That way, we will always have points, and not lose points.

Version 2: The fence method

First attach the code:

HTML code:

<h2>Red envelope generator</h2>
<div id="setting">
  <div><label>Red envelope amount:<input id="amount" value=100.00></input></label></div>
  <div><label>Number of red packets:<input id="count" value="10"></input></label></div>
  <div><button id="generateBtn">Randomly generated</button></div>
</div>

<ul id="result">
</ul>
Copy the code

The CSS code:

#setting button {
  margin-top: 10px;
}

#result {
  padding: 0;
}

#result li {
  list-style: none;
}
Copy the code

JS code:

function * draw(cards){
  const c = [...cards];

  for(let i = c.length; i > 0; i--) {
    const pIdx = Math.floor(Math.random() * i);
    [c[pIdx], c[i - 1]] = [c[i - 1], c[pIdx]];
    yield c[i - 1]; }}function generate(amount, count){
  if(count <= 1) return [amount];
  const cards = Array(amount - 1).fill(0).map((_, i) = > i + 1);
  const pick = draw(cards);
  const result = [];
  for(let i = 0; i < count; i++) {
    result.push(pick.next().value);
  }
  result.sort((a, b) = > a - b);
  for(let i = count - 1; i > 0; i--) {
    result[i] = result[i] - result[i - 1];
  }
  return result;
}

const amountEl = document.getElementById('amount');
const countEl = document.getElementById('count');
const generateBtn = document.getElementById('generateBtn');
const resultEl = document.getElementById('result');

generateBtn.onclick = function(){
  let amount = Math.round(parseFloat(amountEl.value) * 100);
  let count = parseInt(countEl.value);
  
  let output = [];
  
  if(isNaN(amount) || isNaN(count) 
     || amount <= 0 || count <= 0){
    output.push('Input format is not correct! ');
  }else if(amount < count){
    output.push('Not enough money to share')}else{ output.push(... generate(amount, count)); output = output.map(m= > (m / 100).toFixed(2));
  }
  resultEl.innerHTML = '<li>' + 
                        output.join('</li><li>') +
                       '</li>';
}
Copy the code

The other algorithm, we could call it the fence algorithm.

Let’s say I have 100 yuan, so we can view it as a bamboo. So if you were to divide it into 10 pieces, you would have to make 9 cuts in the middle, and where would those 9 cuts go? It’s all random. If you have to make 9 cuts in a $100 bill, there are 9,999 ways to do it. That is, how much money does it have, so how much money does it have – 1 way to cut.

Finally, let’s look at the effect. As shown below:

✳️ 3

Online address for the above two versions:

  • Version 1: Cut watermelon
  • Version 2: The fence method

🆗 4. Conclusion

In the above article, we first talked about the randomness of the bonus bag problem, and at the same time, the method of cutting watermelon and fence method to achieve the bonus bag function. I do not know whether we have a further understanding of the bonus package problem?

If you think this article is helpful to you, you might as well like to support yo ~~😉

🆚 previous recommendation

👉 Follow the steps of moon Shadow big guy, let’s learn how to write good JS (1)

👉 Follow the steps of moon Shadow big guy to learn how to write good JS (2)

👉 every day in front of the traffic lights shuttle line, how about their own to achieve a traffic light?

👉 idempotent problem vs how to determine if it is a power of 4

👉 how to shuffle cards to be more fair?