8
\$\begingroup\$

I recently bought this math-based boardgame for my little cousins, and am now trying to verify its design with some MATLAB code. The relevant parts of the game are:

  • A board with numbers from 1 to 100 in one tile each, and each tile colored in one of nine colors
  • There are three dice, the usual kind (1-6)
  • In your turn, you roll all three dice. You have three numbers x, y and z now, from the dice. Now, using these three numbers, and applying the four basic math operations on them (+, -, *, /) in any order, you must arrive at one of the numbers on the board (i.e. from 1 to 100). The catch is, the resulting numbers have scores based on their color on the board, so that for eg. arriving at 13 or 26 (red tile) gives you a much higher score compared to arriving at 25 (pink). So if you die values are 5, 5, 1, you're much better off going with (5*5+1) = 26 than with (5*5*1) = 25. Choosing these operations right in each turn is the crux of the game.

Now, the part I had doubts about was the coloring of the tiles - were they really colored according to the difficulty of arriving at them? That seemed easy enough to verify - find the frequency of occurrence of each number from 1 to 100 given three dice and four mathematical operations - and so that's what this MATLAB code attempts to do:

function freq = compute_freq
idx = 1;
for x = 1:6
 for y = 1:6
 two_die_combos = get_combos(x, y);
 for z = 1:6
 three_die_combos = get_combos(two_die_combos, z);
 valid_combos = three_die_combos(three_die_combos > 0 & ...
 three_die_combos <= 100 & ...
 (three_die_combos == floor(three_die_combos))); % only integer values
 all_combos(idx:idx + length(valid_combos) - 1) = valid_combos;
 idx = idx+length(valid_combos);
 end
 end
end
freq = tabulate(all_combos);
end
function combos = get_combos(a, b)
num_results = length(a) * 6 * length(b);
combos = zeros(1, num_results);
idx = 1;
for x = a
 for y = b
 combos(idx) = x + y;
 combos(idx + 1) = x - y;
 combos(idx + 2) = -x + y;
 combos(idx + 3) = x * y;
 combos(idx + 4) = x / y;
 combos(idx + 5) = x \ y;
 idx = idx + 6;
 end
end
end

I get some frequency values from this, but:

  • first of all, I have no way of verifying the correctness of results themselves, so I would like to know if there are any logical errors in the code
  • secondly, I'd love feedback on the quality of the code itself. Loops within loops make me feel icky, but there doesn't seem to be any other reasonable way of doing this (one other option that occurred to me was having character arrays like ['1' '2' '3' '4' '5' '6'] and ['+' '-' '*' '/'], using MATLAB's permutation functions to get all possible expressions and then eval them, but that has complications with commutativity and order, and also... eval!). Am I missing some other better option?
200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jun 20, 2014 at 14:43
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

Discussion

You have three dice, which you can assume to hold three places for 1, 2, 3, 4, 5, 6 and the four operations +, -, *, / would hold the two in-between places, which are shown as square brackets and round brackets respectively as shown in this blueprint - [] () [] () [].

The total number of possible combinations would be 6*4*6*4*6 = 3456. Out of these, you need to find the valid ones based on flooring and values in the range [1 100].

Looking at your code, I don't think -x+y would be a valid one, because you can't just pre-append a operator. If that is to be allowed, why not multiplication operator too? Moreover -x essentially means -1*x, for which you are already using two operators - - and * and assuming one of y or z to be 1. For these reasons, I am guesstimating, -x+y to be an invalid one, unless it says in the instructions manual to be a valid one.

Again, x\y won't induce anything new, as we are already juggling through all values of 1 to 6 across all three places around the four operators, as shown in the blueprint earlier.

Code

Considering all the assumptions and avoiding the "scandalous" cases, we would have this vectorized code -

%// Define possible values of x, y and z, denoting values from three dice
x = 1:6;
y = 1:6;
z = 1:6;
%// t1 would take care of x and y and the one operator in between
t1 = [bsxfun(@plus,x',y) ; bsxfun(@minus,x',y) ; bsxfun(@times,x,y') ; bsxfun(@rdivide,x,y')]
%// t2 would take care of x, y and z and the two operators in between
t2 = [bsxfun(@plus,t1(:),z) ; bsxfun(@minus,t1(:),z) ; bsxfun(@times,t1(:),z) ; bsxfun(@rdivide,t1(:),z)]
%// Get the valid ones based on flooring and limiting within the range [1 100]
t2 = t2(t2==floor(t2) & t2<=100 & t2>=1)
freq = tabulate(t2)

Output

freq =
 1.0000 151.0000 7.6186
 2.0000 157.0000 7.9213
 3.0000 146.0000 7.3663
 4.0000 148.0000 7.4672
 5.0000 130.0000 6.5590
 6.0000 150.0000 7.5681
 7.0000 94.0000 4.7427
 8.0000 106.0000 5.3481
 9.0000 87.0000 4.3895
 10.0000 89.0000 4.4904
 11.0000 53.0000 2.6741
 12.0000 91.0000 4.5913
 13.0000 35.0000 1.7659
 14.0000 37.0000 1.8668
 15.0000 46.0000 2.3209
 16.0000 36.0000 1.8163
 17.0000 14.0000 0.7064
 18.0000 41.0000 2.0686
 19.0000 10.0000 0.5045
 20.0000 34.0000 1.7154
 21.0000 16.0000 0.8073
 22.0000 10.0000 0.5045
 23.0000 7.0000 0.3532
 24.0000 42.0000 2.1191
 25.0000 16.0000 0.8073
 26.0000 7.0000 0.3532
 27.0000 10.0000 0.5045
 28.0000 11.0000 0.5550
 29.0000 5.0000 0.2523
 30.0000 33.0000 1.6650
 ......

Observation

freq percentage value for 26 [red colored] is 0.3532 that is slightly lower than for 25 [pink colored] which has 0.8073. Similarly, for 13 [red colored] it is 1.7659, that is again slightly lower than for 15 [looks like pink colored], which has 2.3209.

To confirm, you can create another column to the "tabulated" one and mark different weights for each number from 1 to 100 based on their colors. Then, see if such a pattern continues across the entire board. Good luck and hope this would make sense!

answered Jun 21, 2014 at 10:29
\$\endgroup\$
9
  • 1
    \$\begingroup\$ Hi, and welcome to Code Review. Your answer shows a great understanding of the problem, but actually, for all the good content, it really just shows a different way to do things, without reviewing the OP's code. Your answer would be even better if you found more ways to show why your alternate code is an improvement over the OP's code. \$\endgroup\$ Commented Jun 21, 2014 at 11:23
  • \$\begingroup\$ @rolfl Thanks for the welcome! Well I have used a vectorized approach that looks different to avoid the "ickiness" as mentioned in the question. I believe the vectorized approach would be better with its very nature of performing on a larger dataset at a time instead of using for-loops. My review also included getting rid of two cases from the code in the question, as discussed in the Discussion section. \$\endgroup\$ Commented Jun 21, 2014 at 11:35
  • \$\begingroup\$ Thanks @Divakar, vectorization was definitely something I was hoping to be able to do, I'll look into bsxfun to understand the code. \$\endgroup\$ Commented Jun 21, 2014 at 15:49
  • \$\begingroup\$ I disagree about the omission of cases though: -x + y is just a fancy way of writing y - x, which is a value which has to be considered and counted for frequency calculation. Yes, the same result will be calculated when x and y values change too, but that is irrelevant as we want to count it every time it can be formed, independent of other turns. For eg., with 3, 4, 5 on die1, die2, die3, the combos are 3 + 4 + 5 = 12, 3 - 4 + 5 = 4, 3 - 4 - 5 = -6, 3 + 4 - 5 = 2, 4 - 3 - 5 = -4, 4 - 3 + 5 = 6, 5 - 4 - 3 = -2. Skipping (4 - 3) i.e. (-3 + 4) will make us miss some possible combos here. \$\endgroup\$ Commented Jun 21, 2014 at 16:00
  • \$\begingroup\$ @sundar Thank you for getting back with your concerns. I have just updated the code to make it more sense to what it tries to achieve. For your example case, for the calculation of t1, bsxfun(@minus,x',y) is included, which considers all cases of [x] (-) [y], where both x and y vary from 1 to 6. Thus, it would include case for [4] (-) [3], which you can verify if you display the output of bsxfun(@minus,x',y) and in it look for 4th row and 3rd col, which is 1. Let's hope this comment would make sense! \$\endgroup\$ Commented Jun 21, 2014 at 16:41

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.