Best approach to make a reverse five-star calculator
<p>In the 5-star rating system, I have a known number of ratings.<br>
I have the final (weighted) average of all those N ratings, let's say it is R (float to two decimal places).<br>
I would like to write a python script which generates all possible combinations (Total of weighted averages) and print out only the one(s) which result in R. </p>

<p>How would I approach this problem?</p>

<p><strong>Example:</strong></p>

<p>N= 20 customers rated a product<br>
R = 3.85 is the average rating</p>

<p>Output I am looking for:</p>

<blockquote>
  <p>10 five-stars, 4 four-stars, 1 three-stars, 3 two-stars, and 2 one-star </p>
</blockquote>

<p>is one combination which would give 3.85 by 20 customers.</p>

<p>How would I test if there are any more combinations which could result in the given R and print them out as well? </p>

<p>Here is an algorithm that doesn't use brute force. The indented code shows an example.</p>

<p>You have the number of ratings N and their average R.<br>
Let <code>si</code> be the number of i-stars ratings (with <code>i in [1..5]</code>).<br>
We have <code>s1 + s2 + s3 + s4 + s5 = N</code>.<br>
We also have <code>s1 + 2*s2 + 3*s3 + 4*s4 + 5*s5 = R*N</code>.</p>

<pre><code>  s1 + s2 + s3 + s4 + s5 = 20
  s1 + 2*s2 + 3*s3 + 4*s4 + 5*s5 = 77
</code></pre>

<p>Hence <code>s2 + 2*s3 + 3*s4 + 4*s5 = R*N - N</code>.<br>
Now choose a value for <code>s1</code> and calculate <code>s2 + s3 + s4 + s5 = N - s1</code>.</p>

<pre><code>  s2 + 2*s3 + 3*s4 + 4*s5 = 57
  s1 = 4
  s2 + s3 + s4 + s5 = 16
</code></pre>

<p>We can continue with <code>s3 + 2*s4 + 3*s5 = (R*N - N) - (N - s1)</code>.<br>
Choose a value for <code>s2</code> and calculate <code>s3 + s4 + s5 = N - s1 - s2</code>.</p>

<pre><code>  s3 + 2*s4 + 3*s5 = 41
  s2 = 2
  s3 + s4 + s5 = 14
</code></pre>

<p>Repeat with <code>s3</code> and get the value for <code>s5</code> and <code>s4</code>.</p>

<pre><code>  s4 + 2*s5 = 27
  s3 = 9
  s4 + s5 = 5

  s5 = 22
  s4 = -17
</code></pre>

<p>Now, obviously, this produces incorrect solutions (in the example, <code>s5 &gt; 20</code> and <code>s4 &lt; 0</code>). In order to avoid that, we can constrain the value choices each time.<br>
We need to choose <code>s3</code> so that <code>s4 + s5 &gt;= (s4 + 2*s5)/2</code>, so that we end up with <code>s5 &lt;= s4 + s5</code>.<br>
This is possible only if <code>s3 + s4 + s5 &gt;= (s3 + 2*s4 + 3*s5)/3</code>, hence another constraint, this time for <code>s2</code>.<br>
And finally, the constraint for <code>s1</code> is <code>s2 + s3 + s4 + s5 &gt;= (s2 + 2*s3 + 3*s4 + 4*s5)/4</code>.</p>

python algorithm