Дартс зустрічається з Кодегольфом


11

Я думаю, що всі знають дартс, деякі люди не розуміють балів, тому для цих людей тут корисне посилання.

Дошка

Дартс можна порівняти з пирігом, розрізаним на 20 штук. Кожен твір розділений на 4 розділи.

  • невелике зовнішнє кільце, яке називається подвійним (точки x2)
  • велике кільце, яке називається одинарним (точки x1)
  • ще одне невелике кільце під назвою потрійне (точки x3)
  • ще одне велике кільце, яке називається одинарним (точки x1)

В середині дошки - ще 2 кільця, зелене та червоне (класична дошка)

  • Червоне кільце, центр дошки називається бичачим чи подвійним биком і добре на 50 очок. Цей вважається подвійним, і тому йому дозволяється оформити каси з ним.
  • Зелене кільце, яке називається биком, одиночним биком або просто 25 і вважається одиничним.

Виклик

Знайдіть усі можливості оформлення замовлення з 3 дартсами або менше.
Користувач може ввести ціле число, і вам доведеться перевірити, чи можливо отримати результат до 0 за допомогою 3 дартс (або менше).

Приклади

приклад 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!

Правила

  • Основне правило дартса, ви повинні закінчуватися подвійним (зовнішнє кільце дошки або бичаче око)
  • Немає використання зовнішніх ресурсів.
  • Дозволено жорстке кодування можливих замовлень, але пам’ятайте, що це кодовий гольф, він не матиме ваш код короткий;)
  • Осередки, які потрапляють, відображатимуться у форматі C + N, де C = T для Triple, D для double та S для одиночних.
    • bullseye можна назвати bullseye або DB, DBull або щось подібне.

Можливі каси

Щоб розпочати, Найвищий можливий замовлення - 170.
169,168,166,165,163,162,159 неможливо за 3 дротики.
Найнижчий можливий замовлення - 2.

На додачу

Це не вимога, додайте можливість показувати всі можливі замовлення на всі результати. В основному тому, що мені цікаво, скільки можливих комбінацій: P

Переможцем стане той, хто має найкоротший код.

Щасливе кодування.


1
Перше перераховане правило є невірним (і визнає недійсним перший приклад), оскільки ви також можете закінчити бика. Було б корисно уточнити, чи очікуєте ви програми, функції чи обох; і скільки гнучкості у вихідному форматі.
Пітер Тейлор

1
@PeterTaylor Я зроблю це більш зрозумілим, оскільки зелене кільце та червоне кільце посередині називаються одиноким биком та бичком або подвійним биком.
Теун Пронк

1
+1 за відмінне запитання. Це така реальна проблема, яку комп’ютери добре вирішують. Ви можете кинути 6 в S2 D1 D1, якого немає у вашому прикладі виводу (воно повинно бути там, якщо ви не вважаєте, що S2 S2 D1 і D1 D1 D1 однакові, але вони чітко перераховані як різні.) Є деякі незначні двозначності щодо формату виводу та підрахунку результатів, про які я торкнуся у своїй відповіді.
Рівень річки Св.

Відповіді:


2

C ++ 248/228 230/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;}

Rev 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:

введіть тут опис зображення

Я рахую різні перші та другі дартси як однакові комбінації, як це робило ОП (приклад:

T1 S1 D1 = S1 T1 D1), хоча це коштує додаткових 7 символів. Я завжди перераховую вищий бал першим (ігноруючи подвоєння та требля), оскільки вважаю, що це більше стосується гравця (який може змінити свою стратегію, якщо він пропустить з першим дартсом.) З тієї ж причини я перераховую дартс у порядку відповідно до другий дротик. Я вважаю, що 3-й дартс повністю відрізняється від двох інших, тому вважаю, що D1 D2 і D2 D1 є різними випадками, тоді як в ОП вони вказані як однакові.

Завдяки цій системі підрахунку я отримую 42336 загальних можливостей , таких самих як mmumboss. Зарахувавши різні перші та другі дартси як різні комбінації, це сягає 83349.

Я не використовував цикл з наборами, як це робили інші (я досить новачок у 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 ( 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

ой вибачте, хай, мені було цікаво коду, і результат я не читав історію вище xD
Teun Pronk

Це має бути краще. Єдине, про що я можу подумати - це те, що бик все ще відображається як 25. Але я сподіваюся, що це нормально, оскільки в іншому випадку немає іншої можливості, ніж жорсткий код цього, що просто не цікаво.
mmumboss

Одинокий бик як 25 - це дійсно прийнятно. Єдиний спосіб, коли ви можете кинути 25 з 1 дротиком
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(?,)};"})})}

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 символів)

Не впевнений, що пітон дозволить однолінійному, але він у трьох.

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èì

Досить повільно. Виводиться як список списків, або порожній список, якщо завершення неможливо. Мої бики є 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 байти

Примітка: алгоритм заснований на відповіді C ++ рівня River River St.

{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!")}

Спробуйте в Інтернеті!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.