다트와 Codegolf의 만남


11

나는 모든 사람들이 다트에 익숙하다고 생각합니다. 어떤 사람들은 점수를 이해하지 못하므로 여기 사람들을 위해 유용한 링크가 있습니다.

보드

다트 보드는 파이 조각 20 개로 비교할 수 있습니다. 각 조각은 4 개의 섹션으로 나뉩니다.

  • 이중이라는 작은 외부 고리 (점 x2)
  • 단일이라는 큰 고리 (점 x1)
  • 트리플이라는 또 다른 작은 고리 (포인트 x3)
  • single이라는 또 다른 큰 반지 (점 x1)

보드 중앙에는 2 개의 고리가 더 있습니다.

  • 레드 링, 보드의 중심은 땡기 또는 이중 황소라고하며 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는 싱글입니다.
    • bullseye는 bullseye 또는 DB, DBull 또는 유사한 것으로 불릴 수 있습니다.

가능한 체크 아웃

시작하기 위해 가능한 가장 높은 체크 아웃은 170입니다.
169,168,166,165,163,162,159는 3 개의 다트에서는 불가능합니다.
가장 낮은 체크 아웃은 2입니다.

게다가

이것은 필수 사항이 아니며 모든 점수에 대해 가능한 모든 체크 아웃을 표시 할 가능성을 추가합니다. 기본적으로 얼마나 많은 조합이 가능한지 궁금하기 때문에 : P

우승자는 가장 짧은 코드를 가진 사람이 될 것입니다.

행복한 코딩.


1
황소를 마칠 수도 있기 때문에 첫 번째로 나열된 규칙이 잘못되었습니다 (첫 번째 예가 무효화 됨). 프로그램, 기능 또는 둘 다를 기대하는지 명확히하는 것이 도움이 될 것입니다. 그리고 출력 형식에 얼마나 많은 유연성이 있는지.
피터 테일러

1
@PeterTaylor 나는 중간에있는 녹색 고리와 빨간 고리가 단일 황소와 황소 눈 또는 이중 황소라고하기 때문에 이것을 더 명확하게 할 것입니다.
Teun Pronk

1
훌륭한 질문에 +1. 이것은 컴퓨터가 잘 풀 수있는 일종의 실제 문제입니다. S2 D1 D1에서 6을 던질 수 있습니다.이 출력은 예제 출력에서 ​​누락되었습니다 (S2 S2 D1과 D1 D1 D1이 동일하다고 생각하지 않는 한 있어야합니다. 그러나 분명히 다르게 나열되어 있습니다.) 출력 형식 및 결과 계산에 대한 약간의 모호성. 내 답변에서 다룰 것입니다.
Level River St

답변:


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자인 경우에도 마찬가지입니다. 나는 이것이 플레이어와 더 관련이 있다고 생각하기 때문에 항상 (더블링과 떨림을 무시하고) 가장 높은 점수를 먼저 표시합니다 (첫 번째 다트를 놓치면 전략을 바꿀 수 있습니다.) 같은 이유로 나는 다트를 순서대로 나열합니다 두 번째 다트. 나는 3 번째 다트가 다른 2 개의 다트와 완전히 다른 것으로 생각하므로, D1 D2와 D2 D1은 다른 경우라고 생각하지만 OP는 그것들을 동일하게 나열했습니다.

이 계수 시스템을 사용하면 mmumboss 와 같은 42336의 총 가능성 을 얻습니다. 다른 첫 번째와 두 번째 다트를 다른 조합으로 세면 83349까지 올라갑니다.

다른 사람들이 한 것처럼 세트와 함께 for 루프를 사용하지 않았습니다 (C ++에 익숙하지 않으며 가능한지 모르겠습니다.) 대신 루프 증분의 조건을 남용하여 20에서 25로 점프합니다. 나는 단일 루프에서 변수를 사용하여 단일 다트에 대해 가능한 모든 점수를 다음과 같이 인코딩합니다. S1 D1 T1 S2 D2 T2 등. 이렇게하면 식을 더 복잡하게 만들지 만 더 많은 for 루프를 선언 할 수 있습니다.

이것의 결과는 사용되지 않은 다트가 T0으로 표시되지만, 특히 (다른 조합의 첫 번째와 두 번째 다트를 동일한 조합으로 고려하여) 처음에 모두 그룹화 할 수 있었던 것과 같이 의미가 분명하다고 생각합니다 내 출력의.

Ungolfed 버전은 여기입니다. 다른 기능 중 일부는 | 우선 순위를 부여하는 방식으로 대괄호없이 원합니다.

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 ( 299 개 249 241 문자)

이것은 나의 첫번째 진지한 골프이다. 첫 번째 시도 (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

죄송합니다 죄송합니다 lol, 코드 및 xD 위의 이야기를 읽지 않은 결과에 대해 궁금했습니다
Teun Pronk

이게 더 좋을 것입니다. 내가 생각할 수있는 유일한 것은 황소가 여전히 25로 표시된다는 것입니다. 그러나 이것은 하드 코딩 이외의 다른 가능성이 없기 때문에 이것이 좋기를 바랍니다.
mmumboss

25의 단일 황소는 실제로 허용됩니다, 그것은 당신이 어떻게

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

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;

1

Python 2.7 (270 자)

파이썬이 한 줄짜리를 허용할지는 확실하지 않지만, 그는 3입니다.

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

또는 'No Checkout'메시지가있는 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

여기 우리는 간다 :

에프 (170)

T20 T20 D25

에프 (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

에프 (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èì

꽤 느림. 목록의 목록으로 출력하거나 완료 할 수없는 경우 빈 목록으로 출력합니다. 내 황소는 S25~이다 D25. 이것이 허용되지 않으면 변경할 수 있습니다.

온라인으로 사용해 보거나 한 번에 몇 가지 테스트 사례를 확인하십시오 .

설명:

몇 가지 단계가 있습니다.

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

코 틀린 , 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!")}

온라인으로 사용해보십시오!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.