Darts meets Codegolf

MATLAB (299 249 241 chars)

This is my first serious golfing. My first attempt (136 chars) gives the correct result, but not with the correct formatting. It gives all possibilities looking at the number of points for each dart. This means that single 20 and double 10 do have a separate entry, however, they are both displayed as 20. Of course the last dart is always a double.

function f(x);u=[1:20 25].';y=[u;2*u; 3*u(1:end-1)];v=combvec([combnk(y,2);[y y];[zeros(62,1) y];[0 0]].',y(22:42).').';v(sum(v,2)==x,:)

In the second attempt the formatting is improved, which has of course increased the number of characters:

function f(x);h=.1;u=h+[1:20,25].';y=[u;2*u;3*u(1:20)];v=combvec([combnk(y,2);[y,y];h*ones(62,1),y];[h,h]].',y(22:42).').';t='SDT';r=@fix;strrep(arrayfun(@(x)[t(int8((x-r(x))/h)),num2str(h*r(x)/(x-r(x)))],v(sum(r(v),2)==x,:),'un',0),'S0','')

Improved from 299 to 249 characters, while at the same time even improving the output formatting. For this improved version the output for the example cases is:

f(170):

'T20'    'T20'    'D25'

f(6):

'S1'    'S3'    'D1'
'S1'    'T1'    'D1'
'S2'    'D1'    'D1'
'S2'    'S2'    'D1'
'D1'    'D1'    'D1'
''      'S4'    'D1'
''      'D2'    'D1'
'S1'    'S1'    'D2'
''      'S2'    'D2'
''      'D1'    'D2'
''      ''      'D3'

f(169):

Empty cell array: 0-by-3

Additional:

According to my calculation skills there are a grand total of 42336 possibilities to end the dart game.


Ruby (260 chars)

"The last one should be a double" was the missing piece - couldn't figure out why 168 should not have results...:

c=->n,d=3{d=d-1;r=[];n==0?[r]:(d>=0&&n>0?(o='0SDT';((1..20).map{|p|(1..3).map{|h|c.(n-p*h,d).map{|m|r<<["#{o[h]}#{p}"]+m}}};c.(n-50,d).map{|m|r<<['DB']+m};c.(n-25,d).map{|m|r<<[?B]+m})):1;r.select{|*i,j|j[?D]}.tap{|x|d!=2?1:puts(x.map{|i|"#{i.join(?,)};"})})}

c.(170)

T20,T20,DB;

c.(6)

S1,S1,D2;
S1,T1,D1;
S1,S3,D1;
D1,D1,D1;
D1,S2,D1;
D1,D2;
T1,S1,D1;
S2,D1,D1;
S2,S2,D1;
S2,D2;
D2,D1;
S3,S1,D1;
D3;
S4,D1;

C++ 248 / 228 230 / 214 chars

Rev 0:

int f(int s){char m[4]="SDT";int t=0;for(int b=2;b<77;b+=1+(b==62)*12)for(int a=2;a<77;a+=1+(a==62)*12){int c=s-a/3*(a%3+1)-b/3*(b%3+1);if(((c+38)/40==1)|(c==50)&&(c%2==0)&(a>=b)){printf("%c%d %c%d D%d\n",m[a%3],a/3,m[b%3],b/3,c/2);t++;}}return t;}

Rev 1. Saved some characters by declaring all variables at once, and by eliminating unnecessary brackets. It turns out that in C++ all logic and bitwise and/or are lower precedence than comparisions.

int f(int s){char m[4]="SDT";int a,b,c,t=0;for(b=2;b<77;b+=1+(b==62)*12)for(a=2;a<77;a+=1+(a==62)*12){c=s-a/3*(a%3+1)-b/3*(b%3+1);if(c>1&c<41|c==50&&c%2==0&a>=b){printf("%c%d %c%d D%d\n",m[a%3],a/3,m[b%3],b/3,c/2);t++;}}return t;}

I did a function rather than program, as others have done. It returns the total number of possibilities found. It can be reduced from 230 to 214 characters by eliminating the totalising feature.

Sample output, score 6:

enter image description here

I count different first and second darts as the same combination, as the OP has done (example:

T1 S1 D1 = S1 T1 D1) even though this costs an extra 7 characters. I always list the higher score first (ignoring doubling and trebling) as I figure this is more relevant to the player (who may change his strategy if he misses with the first dart.) For the same reason I list the darts in order according to the second dart. I consider the 3rd dart to be completely different to the other two, therefore I consider D1 D2 and D2 D1 to be different cases whereas the OP has them listed as the same.

With this system of counting I get 42336 total possibilities, the same as mmumboss. Counting different first and second darts as different combinations, this goes up to 83349.

I haven't used a for loop with sets as others have done (I'm fairly new to C++ and I don't even know if it's possible.) Instead I abuse a conditional in the loop increment to jump from 20 up to 25. I use the variable from a single loop to encode all possible scores for a single dart, like this: S1 D1 T1 S2 D2 T2 etc. with modulus and division to decode. This saves on the verbosity of declaring more for loops, although it makes expressions more complicated.

The result of this is that an unused dart is shown as T0, but I think it's clear what is meant, especially as (by considering different first and second darts as the same combination) I have been able to group them all together at the beginning of my output.

Ungolfed version here. A couple of other features are use of the & and && operators selectively with | in such a way as to give the order of precedence I want without brackets.

int f(int s)
{
  char m[4] = "SDT";
  int a,b,c,t=0;
    for (b = 2; b < 77; b += 1 + (b == 62) * 12)
      for (a = 2; a < 77; a += 1 + (a == 62) * 12){
        c = s - a / 3 * (a % 3 + 1) - b / 3 * (b % 3 + 1);
        if (c>1 & c<41 | c == 50 && c % 2 == 0 & a >= b){
          printf("%c%d %c%d D%d\n", m[a % 3], a / 3, m[b % 3], b / 3, c / 2);
          t++;
        }
     }
   return t;
}

Tags:

Code Golf