0

So I have a problem that I'm stuck on it since 3 days ago.

You want to participate at the lottery 6/49 with only one winning variant(simple) and you want to know what odds of winning you have:

-at category I (6 numbers)

-at category II (5 numbers)

-at category III (4 numbers)

Write a console app which gets from input the number of total balls, the number of extracted balls, and the category, then print the odds of winning with a precision of 10 decimals if you play with one simple variant.

Inputs:

40

5

II

Result I must print:

0.0002659542

static void Main(string[] args)
        {
            int numberOfBalls = Convert.ToInt32(Console.ReadLine());
            int balls = Convert.ToInt32(Console.ReadLine());
            string line = Console.ReadLine();
            int theCategory = FindCategory(line);
            double theResult = CalculateChance(numberOfBalls, balls, theCategory);
            Console.WriteLine(theResult);
        }
        static int FindCategory (string input)
        {
            int category = 0;
            switch (input)
            {
                case "I":
                    category = 1;
                    break;
                case "II":
                    category = 2;
                    break;
                case "III":
                    category = 3;
                    break;
                default:
                    Console.WriteLine("Wrong category.");
                    break;
            }
            return category;
        }
        static int CalculateFactorial(int x)
        {
            int factorial = 1;
            for (int i = 1; i <= x; i++)
                factorial *= i;
            return factorial;
        }
        static int CalculateCombinations(int x, int y)
        {
            int combinations = CalculateFactorial(x) / (CalculateFactorial(y) * CalculateFactorial(x - y));
            return combinations;
        }
        static double CalculateChance(int a, int b, int c)
        {
            double result = c / CalculateCombinations(a, b);
            return result;
        }

Now my problems: I'm pretty sure I have to use Combinations. For using combinations I need to use Factorials. But on the combinations formula I'm working with pretty big factorials so my numbers get truncated. And my second problem is that I don't really understand what I have to do with those categories, and I'm pretty sure I'm doing wrong on that method also. I'm new to programming so please bare with me. And I can use for this problem just basic stuff, like conditions, methods, primitives, arrays.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • You should find useful reading that you shouldn't divide `int`s: https://stackoverflow.com/questions/661028/how-can-i-divide-two-integers-to-get-a-double – Camilo Terevinto Aug 16 '20 at 18:01

1 Answers1

2

Let's start from combinatorics; first, come to terms:

  • a - all possible numbers (40 in your test case)
  • t - all taken numbers (5 in your test case)
  • c - category (2) in your test case

So we have

t - c + 1 for numbers which win and c - 1 for numbers which lose. Let's count combinations:

All combinations: take t from a possible ones:

A = a! / t! / (a - t)! 

Winning numbers' combinations: take t - c + 1 winning number from t possible ones:

W = t! / (t - c + 1)! / (t - t + c - 1) = t! / (t - c + 1)! / (c - 1)!

Lost numbers' combinations: take c - 1 losing numbers from a - t possible ones:

L = (a - t)! / (c - 1)! / (a - t - c + 1)!

All combinations with category c, i.e. with exactly t - c + 1 winning and c - 1 losing numbers:

C = L * W

Probability:

P = C / A = L * W / A =

t! * t! (a - t)! * (a - t)! / (t - c + 1)! / (c - 1)! / (c - 1)! / (a - t- c + 1)! / a!

Ugh! Not let's implement some code for it:

Code:

// double : note, that int is too small for 40! and the like values
private static double Factorial(int value) {
  double result = 1.0;

  for (int i = 2; i <= value; ++i)
    result *= i;

  return result;
}

private static double Chances(int a, int t, int c) =>
  Factorial(a - t) * Factorial(t) * Factorial(a - t) * Factorial(t) /
    Factorial(t - c + 1) /
    Factorial(c - 1) / 
    Factorial(c - 1) /
    Factorial(a - t - c + 1) /
    Factorial(a); 

Test:

 Console.Write(Chances(40, 5, 2));

Outcome:

 0.00026595421332263435

Edit:

in terms of Combinations, if C(x, y) which means "take y items from x" we have

A = C(a, t); W = C(t, t - c + 1); L = C(a - t, c - 1)

and

P = W * L / A = C(t, t - c + 1) * C(a - t, c - 1) / C(a, t)

Code for Combinations is quite easy; the only trick is that we return double:

// Let'g get rid of noisy "Compute": what else can we do but compute?
// Just "Combinations" without pesky prefix.
static double Combinations(int x, int y) =>
  Factorial(x) / Factorial(y) / Factorial(x - y);

private static double Chances(int a, int t, int c) =>
  Combinations(t, t - c + 1) *
  Combinations(a - t, c - 1) /
  Combinations(a, t); 

You can fiddle the solution

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • Hey @Dmitry Bychenko. First I want to thank you for the solution. Second even if your solution is good, I can't pass the tests because they wanted me to do it with other formula. I'm still waiting for my mentor to answer me and help me with this problem. But thank you for your effort. – Catalin Urcan Aug 17 '20 at 09:43
  • @Catalin Urcan: there's only one possible answer, so we have the only one formula; if you want *Combinations*, not *factorials* the formula is `P = C(t, t - c + 1) * C(a - t, c - 1) / C(a, t)` where `C(x, y)` means "number of ways to take y items from x", which corresponds to your `CalculateCombinations(int x, int y)` code – Dmitry Bychenko Aug 17 '20 at 18:41
  • The formula of the solution is this : Combinations (k, j) * Combinations (n - k, k - j) / Combinations (n, k) where n is totalBalls = 40,k is balls = 5 and j is category. It's also wrong in my FindCategory method. There should be case 1 category = 6, case 2 category = 5, case 3 category = 4. And I'm still trying to figure it out because I still get the wrong answer. @Dmitry Bychenko – Catalin Urcan Aug 18 '20 at 11:16
  • @Catalin Urcan: Well, you can fiddle the solution here: https://dotnetfiddle.net/5As69k test case is `Chances(40, 5, 2)` which returns excpected `0.000265954213322634` – Dmitry Bychenko Aug 18 '20 at 12:10
  • You don't understand me @Dmitry Bychenko. Instead of 2 in Chances has to be 5. Category I means int category = 6, Category II means int category = 5 and Category III means int category = 4. – Catalin Urcan Aug 18 '20 at 12:43
  • @Catalin Urcan: I've taken your *roman* numbers (I,II and III) for `category`, so I have 1,2 and 3. As far as I can see, category shows how many numbers are winning ones; 1st category - all numbers are winning, 2nd - all except one, 3d - all except 2. Please note, that in your case with `40` numbers in total and `5` numbers taken you can't declare 1st category to be **6** (!) numbers – Dmitry Bychenko Aug 18 '20 at 13:15