飞镖遇到Codegolf


11

我认为每个人都熟悉飞镖,有些人不了解飞镖的得分,因此对于这些人来说,是一个有用的链接。

董事会

飞镖可以比作20块的馅饼。每件分为4个部分。

  • 一个称为double的小外圈(点x2)
  • 一个叫做单环的大环(点数x1)
  • 另一个称为三重的小环(点数x3)
  • 另一个称为单环的大环(点x1)

板子中间还有两个环,一个绿色和红色(经典板子)

  • 红色圆环,板的中心称为“靶心”或“双头牛”,有利于50分。这是一个双数,因此允许与它结帐。
  • 绿圈,称为多头,单头公牛或简称25,算作单头。

挑战

查找3支或更少的飞镖的所有结帐可能性。
用户可以输入一个整数,您将必须检查是否有可能用3支飞镖(或更少的飞镖)将分数设为0。

例子

范例1:

Input: 170  
Output: T20, T20, Bullseye

范例2:

Input: 6  
Output: D3;  
        S3,S1,D1;  
        S2,D2;  
        S2,S2,D1;  
        D2,D1;  
        S4,D1;  
        D1,D1,D1;  
        S1,S1,D2;  
        T1,S1,D1;

范例3:

Input: 169
Output: No possible checkout!

规则

  • 基本的飞镖规则,您必须以双打(木板或靶心的外圈)结尾
  • 不使用外部资源。
  • 允许对可能的结帐进行硬编码,但是请记住,这是codegolf,它不会使您的代码简短;)
  • 命中的单元格将以C + N格式显示,其中C = T(表示三重),D =表示双倍和S(表示单个)。
    • 靶心可以称为靶心或DB,DBull或类似的东西。

可能的结帐

为了让您入门,最高可能的结帐数量是
170。3支飞镖不能达到169,168,166,165,163,162,159。
最低可能的结帐为2。

此外

这不是必须的,添加一个可能性以显示所有分数的所有可能结帐。基本上是因为我想知道可能有多少种组合:P

获胜者将是代码最短的人。

快乐的编码。


1
列出的第一个规则不正确(并使第一个示例无效),因为您也可以在公牛上结束比赛。弄清您是期望一个程序,一个功能还是同时期望这两个功能将很有帮助。以及输出格式有多少灵活性。
彼得·泰勒

1
@PeterTaylor我将更清楚一点,因为中间的绿色环和红色环称为“单头牛和靶心”或“双头牛”。
Teun Pronk

1
+1是一个很好的问题。这是计算机擅长解决的现实问题。您可以在S2 D1 D1中丢一个6,这在示例输出中是缺失的(应该存在,除非您认为S2 S2 D1和D1 D1 D1是相同的,但显然列出它们是不同的。)关于输出格式和结果计数的小歧义,我将在回答中解决。
Level St

Answers:


2

C ++ 248/228230/214个字符

版本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;}

修订版1。通过一次声明所有变量并消除不必要的方括号来保存一些字符。事实证明,在C ++中,所有逻辑和按位和/或优先级均低于比较。

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;}

我做了一个函数而不是程序,就像其他人一样。它返回找到的可能性总数。通过消除总计功能,可以将其从230个字符减少到214个字符。

样本输出,得分6:

在此处输入图片说明

正如OP所做的那样,我将不同的第一支和第二支飞镖算作同一组合(例如:

T1 S1 D1 = S1 T1 D1),尽管这会额外花费7个字符。我总是首先列出较高的分数(忽略加倍和三倍),因为我认为这与玩家(如果他错过第一支飞镖的人可能改变其策略)更相关。出于同样的原因,我按照以下顺序列出了这些飞镖:第二支飞镖。我认为第三支飞镖与其他两个完全不同,因此我认为D1 D2和D2 D1是不同的情况,而OP将它们列为相同。

通过这种计数系统,我可以获得42336种可能性,与mmumboss相同。将不同的第一和第二把飞镖视为不同的组合,则上升到83349。

我没有像其他人那样对集合使用for循环(我对C ++还是很陌生,我什至不知道是否可能。)相反,我滥用了循环增量中的条件从20跳到25我使用单个循环中的变量来编码单个飞镖的所有可能得分,如下所示:S1 D1 T1 S2 D2 T2等,具有模数和除法进行解码。这省去了为循环声明更多的冗长性,尽管这使表达式更加复杂。

结果是未使用的飞镖显示为T0,但我认为这很清楚,尤其是(通过将不同的第一和第二把飞镖视为相同的组合),我能够在一开始就将它们全部分组在一起我的输出。

取消高尔夫版本。其他两个功能是&和&&运算符与|选择性地结合使用。以这样的方式给出我想要的优先顺序而没有括号。

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;
}


4

MATLAB(299249241 字符)

这是我第一次认真打高尔夫球。我的第一次尝试(136个字符)给出了正确的结果,但格式不正确。它为查看每个飞镖的点数提供了所有可能性。这意味着单打20和双打10确实有一个单独的条目,但是它们都显示为20。当然,最后一个飞镖总是双打。

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,:)

在第二次尝试中,格式化得到了改进,这当然增加了字符数:

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','')

从299个字符改进到249个字符,同时改善了输出格式。对于此改进的版本,示例案例的输出为:

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

额外:

根据我的计算技巧,总共有42336种结束飞镖游戏的可能性。


结果应显示要击中的单元格,因此在第一个提示中60 60 50应为T20 T20 Bullseye。我将在问题中更清楚地说明这一点。不错,但是几乎到了:)
Teun Pronk

1
是的,我已经指出了我自己。这是第一次未完成的尝试。;)
mmumboss 2014年

抱歉,我很想知道代码,结果我没有读xD之上的故事
Teun Pronk 2014年

这样应该更好。我唯一能想到的是,公牛仍显示为25。但是我希望这是可以的,因为否则除非进行硬编码,否则别无其他可能性,这简直无济于事。
mmumboss 2014年

公牛25确实可以接受,无论如何它是唯一可以用1支飞镖投25的唯一方法
Teun Pronk

2

红宝石(260个字符)

缺少的部分是“最后一个应该是双打”-无法弄清楚为什么168不应该有结果...:

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(?,)};"})})}

约(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;

1

Python 2.7(270个字符)

不确定python是否允许单线,但他是三分之一。

def f(n):
 a={'%s%s'%('0SDT'[i],n):n*i for n in range(1,21)+[25] for i in [1,2,3] if n*i<75};a['']=0
 for r in [' '.join(h[:3]) for h in [(x,y,z,a[x]+a[y]+a[z]) for x in a for y in a for z in {k:a[k] for k in a if 'D' in k}] if h[3]==n and len(h[0])<=len(h[1])]:print r

或278个以上带有正确的“不签出”消息的字符(例如,此处为290个字符):

def f(n):
 a={'%s%s'%('0SDT'[i],n):n*i for n in range(1,21)+[25] for i in [1,2,3] if n*i<75};a['']=0;
 for r in [' '.join(h[:3]) for h in [(x,y,z,a[x]+a[y]+a[z]) for x in a for y in a for z in {k:a[k] for k in a if 'D' in k}] if h[3]==n and len(h[0])<=len(h[1])] or ['No Checkout']:print r

开始了:

f(170)

T20 T20 D25

f(6)

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

f(169)

No Checkout

我不满意的事情:

for x in a for y in a for z in

这是总数的10%以上。没有itertools等,还有没有更紧凑的方法?

and len(h[0])<=len(h[1])

这用于防止在两个飞镖表面上出现重复(例如[“,'S1','D1']和['S1','','D1'])。我认为顺序很重要(嘿-最后一个飞镖必须是双飞镖,所以顺序很重要),但是不摔是一种特殊情况。


1

05AB1E,43 个字节

20L25ª3Lâ¨Ðʒθ<}Uã«XâXìε˜2ô}ʒPOQ}εε`…TSDsèì

相当慢。输出为列表列表,如果无法完成则输出为空列表。我的公牛是S25D25; 如果不允许这样做,我可以更改它。

在线尝试或一次验证一些测试用例

说明:

有几个步骤:

1)创建所有可能的单,双和三镖的列表:

20L         # Create a list in the range [1,20]
   25ª      # Append 25 to this list
      3L    # Create a list in the range [1,3]
        â   # Create all possible pairs of these two lists
         ¨  # Remove the last pair (which is the Triple Bull)
            # Now we have a list of all possible darts:
            #  [[1,1],[1,2],[1,3],[2,1],...,[20,3],[25,1],[25,2]]

2)获取所有可能的最多3支飞镖的修整器(以双结束):

Ð           # Triplicate this list
 ʒ  }       # Filter the top copy by:
  θ         #  Where the last value
   <        #  Decremented by 1 is truthy (==1), so all doubles
     U      # Pop this filtered list of doubles, and store it in variable `X`
 ã          # Create all possible pairs of the list of darts with itself
  «         # Merge it with the list of darts
            # We now have a list containing all possible variations for 1 or 2 darts
 Xâ         # Then create all possible pairs of these with the doubles from variable `X`
   Xì       # And prepend the doubles themselves as well
            # Now we have all possible variations of 1 double; 1 dart + 1 double;
            # or 2 darts + 1 double
     ε   }  # Map each to:
      ˜     #  Deep-flatten the list
       2ô   #  And split it into parts of size 2
            #  (this is to convert for example a 2 darts + 1 double from
            #   [[[20,3],[5,1]],[1,2]] to [[20,3],[5,1],[1,2]])
            # Now we have a list of all possible finishers of up to 3 darts

3)只保留总分等于输入整数的那些分数:

ʒ   }       # Filter this list by:
 P          #  Get the product of each inner-most lists
            #   i.e. [[20,3],[5,1],[1,2]] → [60,5,2]
  O         #  Take the sum of those
            #   i.e. [60,5,2] → 67
   Q        #  Check if this value is equal to the (implicit) input-integer
            # Now we only have the finishers left with a total value equal to the input

4)将数据转换为漂亮的结果列表(即[[20,3],[5,1],[1,2]]成为["T20","S5","D2"]):

ε           # Map each of the remaining finishers of up to 3 darts to:
 ε          #  Map each inner list to:
  `         #   Push both values separately to the stack ([20,3] → 20 and 3)
   TSD     #   Push string "TSD"
       s    #   Swap to get the integer for single/double/triple at the top of the stack
        è   #   Use it to index into the string
            #   NOTE: 05AB1E has 0-based indexing with automatic wraparound,
            #   so the triple 3 will wrap around to index 0 for character "T"
         ì  #   Prepend this character in front of the dart-value
            # (after which the result is output implicitly as result)

0

Kotlin,254字节

注意:算法基于Level River St的C ++答案。

{s:Int->val m="SDT"
var c=0
val r=(2..62).toList()+listOf(75,76)
for(t in r)for(o in r){val l=s-o/3*(o%3+1)-t/3*(t%3+1)
if((l>1&&l<41||l==50)&&l%2==0&&o>=t){println("${m[o%3]}${o/3},${m[t%3]}${t/3},D${l/2}")
c++}}
if(c<1)println("No possible checkout!")}

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.