11
\$\begingroup\$

Your task is to calculate the expected chance of winning for 2 players in some game, each with their own ELO Rating. Player A has ELO Ra and player B has ELO Rb

The expected score for Player A (Ea) is: 1 / (1 + 10(Rb - Ra) / 400). There is a similar equation for Player B (Eb): 1 / (1 + 10(Ra - Rb) / 400).

If you want a more copiable version: 1 / (1 + 10^((a-b) / 400))

Ea + Eb should be equal to 1.

Therefore, the score for a player is their expected chance of winning some match, in decimal.

Your program/function should take 2 inputs, Player A's ELO, and Player B's ELO, and print/return their respective chance to win in decimal format. The output must add up to one, and you must be accurate to at least 5 decimal places (0.00000). After 5 decimal places, you may have inaccurate digits, provided the two outputs still add up to one.

Examples:

1200 2100 -> 0.005591967 0.994408033
1 1 -> 0.5 0.5
60 20 -> 0.557312 0.442688
9999 9998 -> 0.501439 0.498561
9999 1 -> 0.999999 0.000001

In the final test case, some answers use scientific exponentiation to represent the value. This is not valid.

You can see in test case 3 here that 0.557312 is not quite accurate, because the 2 should be a 1, but this is fine because it is after five decimal places and the outputs still add up to one.

This is an example of invalid output:

9999 9998 -> 0.5014391117091516, 0.49856088829084844

This looks like it satisfies the requirements at first glance, but the numbers add up to 1.00000000000000004 and therefore the output is not valid.

Trailing zeroes in the output is fine.

You may assume a player's ELO will always be greater than 0, and nobody will have an ELO higher than 9999.

The input and output format is flexible, but the input and output must still be in base 10.

As this is , the answer with the lowest byte count will win!

\$\endgroup\$
6
  • 1
    \$\begingroup\$ +1 for ELO rating, even though I was disappointed to find you are talking about something called Elo rating instead. \$\endgroup\$ Feb 22, 2017 at 3:43
  • \$\begingroup\$ You should also add the test case [9999, 998] which most answers seem to fail for. \$\endgroup\$
    – Emigna
    Feb 22, 2017 at 7:42
  • \$\begingroup\$ @Emigna added, but made it more extreme ;) \$\endgroup\$
    – Okx
    Feb 22, 2017 at 7:45
  • \$\begingroup\$ @Okx: Nice. Need to go back to the drawing board to handle that one :) \$\endgroup\$
    – Emigna
    Feb 22, 2017 at 8:13
  • \$\begingroup\$ It seems all answers fail on 9999, 1 including my own, so I can't post it :-( \$\endgroup\$
    – Metoniem
    Feb 22, 2017 at 8:50

9 Answers 9

5
\$\begingroup\$

Jelly, 9 bytes

÷400⁵*÷S$

Try it online! or View all test cases.

The input is an array [Ra, Rb] and the output is an array [Ea, Eb].

Explanation

÷400⁵*÷S$  Input: array [Ra, Rb]
÷400       Divide each by 400, makes [Ra/400, Rb/400]
    ⁵*     Raise 10 to that power, makes [10^(Ra/400), 10^(Rb/400)]
        $  Monadic chain operating on previous result
      ÷      Divide each by
       S     The sum of the whole
           Makes [10^(Ra/400)/(10^(Ra/400) + 10^(Rb/400)),
                  10^(Rb/400)/(10^(Ra/400) + 10^(Rb/400))]
               = [1/(1 + 10^((Rb-Ra)/400)), 1/(1 + 10^((Ra-Rb)/400))]
\$\endgroup\$
3
  • \$\begingroup\$ What is going on here? \$\endgroup\$
    – Okx
    Feb 22, 2017 at 7:49
  • \$\begingroup\$ @Okx That is scientific notation. I'm sure you know what it is since you just edited the challenge to require standard notation after you originally said input/output format were up to us. \$\endgroup\$
    – miles
    Feb 22, 2017 at 8:23
  • \$\begingroup\$ Did you look at the other output? It's 1.0! \$\endgroup\$
    – Okx
    Feb 22, 2017 at 11:52
3
\$\begingroup\$

Python 3, 55 47 bytes

lambda a,b:[1/(1+10**(x/400))for x in[b-a,a-b]]

-8 bytes thanks to @math_junkie

\$\endgroup\$
2
  • \$\begingroup\$ Why not use a for comprehension: 1/(1+10**(x/400))for x in [b-a,a-b] \$\endgroup\$ Feb 21, 2017 at 20:57
  • \$\begingroup\$ @math_junkie It's called a "list comprehension" \$\endgroup\$
    – mbomb007
    Feb 22, 2017 at 16:21
3
\$\begingroup\$

MATL, 11 bytes

10i400/^ts/

Takes input as a list and outputs a list.

10       % push number literal
i        % push input
400      % push number literal
/        % divide the list (by 400)
^        % power (10^list, element wise)
t        % duplicate the list
s        % sum the second one
/        % divide by the sum
         % (implicit) convert to string and display
\$\endgroup\$
1
\$\begingroup\$

CJam, 23 bytes

XAq~_W%\.m400df/f#:)f/p

Some other 23 byte solutions:

q~_W%\.m400df{/A\#)W#}p
Aq~_W%\.m400df/f{#)W#}p

Try it online!

Explanation

X                        Push 1
 A                       Push 10
  q~                     Push an eval the input, a list containing 2 numbers
    _W%                  Duplicate the list and reverse it
       \                 Swap top stack elements, so the order of answers matches the input
        .m               Vectorized subtraction: computes Ra - Rb and Rb - Ra
          400d           Push 400.0 (must be a double, otherwise / performs integer division)
              f/         Divide both values by 400
                f#       Raise 10 to the power of both numbers
                  :)     Increment both numbers
                    f/   Divide 1 by both numbers
                      p  Output the list nicely
\$\endgroup\$
3
  • \$\begingroup\$ Fails on 9999, 1 :( \$\endgroup\$
    – Metoniem
    Feb 22, 2017 at 8:49
  • \$\begingroup\$ @Metoniem That's odd... it definitely has something to do with rounding issues, or maybe something like how 0.1 + 0.2 = 0.30000000000000004. I'll look into it \$\endgroup\$ Feb 22, 2017 at 14:18
  • \$\begingroup\$ it actually looks fine now, ALL answers including Google's calculator return the same result as your code. I'm quite sure the test case is invalid :( \$\endgroup\$
    – Metoniem
    Feb 23, 2017 at 10:34
1
\$\begingroup\$

C, 63 bytes

#define M(a,b)1/(1+pow(10,(a-b)/400.)),1/(1+pow(10,(b-a)/400.))

Defines a (rather naive) parameterized macro M, the shortest working approach I could think of but probably still not the shortest. As such, any golfing suggestions are greatly appreciated.

Anyways, this returns 2 floating point values, E_b and E_a, respectively.

Try it online!

\$\endgroup\$
4
  • \$\begingroup\$ Fails on 9999, 1 \$\endgroup\$
    – Metoniem
    Feb 22, 2017 at 8:48
  • \$\begingroup\$ @Metoniem Yup. Most likely has to do with how C rounds floats. :/ I'm looking into it. \$\endgroup\$
    – R. Kap
    Feb 22, 2017 at 19:32
  • \$\begingroup\$ It actually seems to be correct, the test case might be invalid :( \$\endgroup\$
    – Metoniem
    Feb 23, 2017 at 10:33
  • \$\begingroup\$ Suggest exp10(x) instead of pow(10,x) \$\endgroup\$
    – ceilingcat
    Jun 27, 2020 at 6:00
1
\$\begingroup\$

JavaScript (ES7), 41 35 bytes

Saved 6 bytes thanks to @Neil

a=>b=>[b=1/(1+10**((b-a)/400)),1-b]
\$\endgroup\$
2
  • \$\begingroup\$ Since Ea + Eb = 1, just write a=>b=>[b=1/(1+10**((b-a)/400)),1-b]. \$\endgroup\$
    – Neil
    Feb 22, 2017 at 8:37
  • \$\begingroup\$ @Neil Really? I'm so shortsighted :P Thanks! \$\endgroup\$ Feb 22, 2017 at 12:35
0
\$\begingroup\$

SAS Macro Language, 70 bytes

%macro e(a,b);data t;p=1/(1+10**((&b-&a)/400));q=1-p;proc print%mend;

Output is a SAS data set where variables p and q are the players' chance of winning. 11 bytes can be saved by removing the print procedure.

\$\endgroup\$
0
\$\begingroup\$

C#, 92 bytes

Not the shortest, but it's C#, never the shortest..

Golfed

   static double[]f(int a,double b){b=1/(1+System.Math.Pow(10,(a-b)/400d));return new[]{1-b,b};

Ungolfed

static double[] f(int a, double b)
{
    b = 1/(1 + System.Math.Pow(10, (a - b)/400d));
    return new[] {1 - b, b};
}
\$\endgroup\$
0
\$\begingroup\$

q, 26 bytes

{1%1+10 xexp(y-x;x-y)%400}

Example

q){1%1+10 xexp(y-x;x-y)%400}[1200;2100]
0.0055919673088347735 0.99440803269116518
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.