7
\$\begingroup\$

Write the shortest function that takes a two-dimensional square array representing the scores of a chess round, and outputs an array of the Neustadtl scores of the players.

The two-dimensional array is structured so that array[i][j] is the score earned by the player i against player j.

The Neustadtl score is used to tie-break in chess tournaments when their conventional scores tie. The Neustadtl score is calculated by adding the scores of the player defeated and half of the scores the player drew with.

Here is an example data for a 5 on 5 match.

               cs  ns
1. X 1 ½ 1 0 | 2½  4.25
2. 0 X 1 ½ 0 | 1½  2.5
3. ½ 0 X ½ ½ | 1½  3.5  
4. 0 ½ ½ X 1 | 2   4
5. 1 1 ½ 0 X | 2½  4.75

where cs stands for conventional score and ns stands for Neustadtl score.

For example, the Neustadtl score of the 4th player is:

  0(player 1's cs) + ½(player 2's cs) + ½(player 3's cs) + 1(player 5's cs)
= 0(2½) + ½(1½) + ½(1½) + 1(2½)
= 4

For more details and another example data, see its Wikipedia article.

Some notes:

  1. Assume the diagonal is always zero (array[j, j] = 0)
  2. No need to check if the array is square
  3. No need to check if the data makes sense (a valid scoretable has the property array[i, j] + array[j, i] = 1, i != j)
\$\endgroup\$
7
\$\begingroup\$

Mathematica 11 10 8

#.Tr/@#&

(Thanks @chyanog!) Usage

m = {{0,  1, .5, 1, 0}, {0, 0, 1, .5, 0}, {.5, 0, 0, .5, .5}, 
     {0, .5, .5, 0, 1}, {1, 1, .5, 0, 0}}

#.Tr/@#&[m]

Result {4.25, 2.5, 3.5, 4., 4.75}

Edit

Some explanations:

Tr is "Trace". When applied to a one-dimensional list returns the elements sum
/@ is "Map". Feeds the preceding operator with one element at a time and returns a list
. is "dot product". Multiplies vectors (or matrices and vectors)
the set # ... & is a functional construct. The &feeds the #with its arguments

\$\endgroup\$
  • \$\begingroup\$ How about Tr? \$\endgroup\$ – chyanog Mar 24 '13 at 7:45
  • \$\begingroup\$ @chyanog Hey! Yesss \$\endgroup\$ – Dr. belisarius Mar 24 '13 at 7:52
7
\$\begingroup\$

APL 31 29 24 or 10 or 7

If you will accept decimal input and output then the following takes your score array as screen input via ←⊃⎕ with each row of the array enclosed in parentheses.

((m,'|'),+/m),m+.×+/m←⊃⎕

Your example would look as follows:

Input: 

(0 1 0.5 1 0)(0 0 1 0.5 0)(0.5 0 0 0.5 0.5)(0 0.5 0.5 0 1)(1 1 0.5 0 0)

Output:

0.0 1.0 0.5 1.0 0.0 | 2.5 4.25
0.0 0.0 1.0 0.5 0.0 | 1.5 2.50
0.5 0.0 0.0 0.5 0.5 | 1.5 3.50
0.0 0.5 0.5 0.0 1.0 | 2.0 4.00
1.0 1.0 0.5 0.0 0.0 | 2.5 4.75

with the input displayed along with the separator and the two scores as the output. Or if you just want the Neustadtl score then:

m+.×+/m←⊃⎕

If the input scores array exists as a global m then:

m←⊃(0 1 0.5 1 0)(0 0 1 0.5 0)(0.5 0 0 0.5 0.5)(0 0.5 0.5 0 1)(1 1 0.5 0 0)

m+.×+/m

4.25 2.5 3.5 4 4.75

Latest mods prompted by marinus. Thanks.

\$\endgroup\$
  • 1
    \$\begingroup\$ What APL are you using? Doesn't only read one line? How can ⍎⍞ get you a matrix? Also, isn't ⍎⍞ the same as ? \$\endgroup\$ – marinus Mar 24 '13 at 4:03
  • \$\begingroup\$ @marinus APL+WIN v5. Yes or a variable. By entering your matrix as, for example, 2 2⍴⍳4. Yes you are right. Another senior moment!!! \$\endgroup\$ – Graham Mar 24 '13 at 9:41
  • \$\begingroup\$ @marinus Another useful alternative for matrix entry is to use ⊃⎕ and enter each row enclosed in parentheses. In this case: (0 1 0.5 1 0)(0 0 1 0.5 0)(0.5 0 0 0.5 0.5)(0 0.5 0.5 0 1)(1 1 0.5 0 0) \$\endgroup\$ – Graham Mar 24 '13 at 9:47
4
\$\begingroup\$

K,13

{+/'x*\:+/'x}

.

k)input:(0 1 0.5 1 0;0 0 1 0.5 0;0.5 0 0 0.5 0.5;0 0.5 0.5 0 1;1 1 0.5 0 0)
k)input
0   1   0.5 1   0  
0   0   1   0.5 0  
0.5 0   0   0.5 0.5
0   0.5 0.5 0   1  
1   1   0.5 0   0  
k){+/'x*\:+/'x}[input]
4.25 2.5 3.5 4 4.75

It's unclear whether you just want a 1-d array of Neustadtl scores or if you want the output that's in your example. If it's the latter then:

K, 23

{x!,:'b,'+/'x*\:b:+/'x}

.

k){x!,:'b,'+/'x*\:b:+/'x}[input]
0   1   0.5 1   0  | 2.5 4.25
0   0   1   0.5 0  | 1.5 2.5 
0.5 0   0   0.5 0.5| 1.5 3.5 
0   0.5 0.5 0   1  | 2 4     
1   1   0.5 0   0  | 2.5 4.75
\$\endgroup\$
3
\$\begingroup\$

R - 25

function(x)x%*%rowSums(x)

R> input <- matrix(c(0,  1, .5,  1,  0,
                     0,  0,  1, .5,  0,
                    .5,  0,  0, .5, .5,
                     0, .5, .5,  0,  1,
                     1,  1, .5,  0,  0), nrow=5, byrow=TRUE)

R> (function(x)x%*%rowSums(x))(input)
     [,1]
[1,] 4.25
[2,] 2.50
[3,] 3.50
[4,] 4.00
[5,] 4.75
\$\endgroup\$
2
\$\begingroup\$

C# 106 (88 function body + 18 required using stetement)

float[]N(float[][]s){return s.Select(l=>l.Select((v,i)=>v*s[i].Sum()).Sum()).ToArray();}

This function requires the using System.Linq; directive to be present in the file, so I added that to the character count as well.

IdeOne link: http://ideone.com/cPcfwg

OK, I know it's not very short, but I love C# and LINQ so much that I just had to do it. :)

Here's a more readable version of the code:

public float[] Neustadl(float[][] scoreTable)
{
    return scoreTable.Select(scoreLine => 
                        scoreLine.Select((lineValue, otherPlayerIndex) => 
                            lineValue * scoreTable[otherPlayerIndex].Sum())
                        .Sum()
                    ).ToArray();
}
\$\endgroup\$
0
\$\begingroup\$

Ruby, 62

N=->a{a.map{|l|z=0
l.zip(a.map{|l|eval l*?+}){|k,s|z+=k*s}
z}}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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