Яка оцінка моєї руки Scopa?


14

Мені подобаються виклики в карткові ігри, тому я зробив цю для італійської карткової гри Scopa. Моя сім'я грає в цю гру споконвіку. Він має дуже цікаву систему підрахунку балів, яка повинна приємно грати в гольф. Я опублікую відповідь в R, щоб почати веселощі, що я впевнений, що люди покращаться.

Завдання: визначити кількість очок, набраних у раунді Scopa, з урахуванням карт, які гравець захопив під час раунду як вхід.

У колоді Scopa 40 карт. Якщо ви використовуєте міжнародну колоду, ви видалите 8s, 9s та 10s, залишаючи A, 2,3,4,5,6,7, Q, J, K у кожному костюмі. 1 Є два гравці або товариства, і після кожного раунду всі карти в кінцевому підсумку захоплюються одним або іншим з двох гравців. Оцінка рахується наступним чином (більше інформації тут ):

  • Гравець з найбільшою кількістю карт набирає 1 бал.
  • Гравець з найбільшою кількістю алмазів (або монет, якщо використовує італійську колоду) набирає 1 бал.
  • Гравець із 7 діамантами (або монетами), відомим як сет-белло або прекрасна сімка, набирає 1 бал.
  • Гравець з найвищими рівнями отримує 1 бал. Оцінка гравця за пер'єєра - це сума балів картки найвищої вартості, яку гравець взяв у кожному костюмі (див. Таблицю нижче). Якщо у вас немає хоча б однієї картки в кожному костюмі, ви програєте за замовчуванням, навіть якщо ваш рахунок перевищить бал вашого опонента. У надзвичайно рідкісному випадку, коли жоден гравець не має принаймні по одній картці у кожному костюмі, гравець із вищим рівнем першості отримує бал. 2

Таблиця балів примірії

| Rank  | Value |
| ----- | ----- |
| 7     | 21    |
| 6     | 18    |
| A     | 16    |
| 5     | 15    |
| 4     | 14    |
| 3     | 13    |
| 2     | 12    |
| Q,J,K | 10    |

Таким чином, гравець може набрати максимум 4 очки в раунді. 3 Якщо є краватка, яка можлива для карт, діамантів чи примірії , ніхто не забиває балів.

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

Правила виклику

Вхідні дані

Ваш код повинен приймати як вхідні картки, захоплені одним гравцем під час раунду Scopa.

Введення має бути в рядковому форматі, в якому один символ представляє ранг кожної картки, а один символ - її масть. Це видаляє потенційну лазівку проходженнябалів праймера безпосередньо як вхід. Конверсія карт звань primiera оцінки повинні бути зроблені в програмі. Однак ви можете використовувати один рядок, розділений пробілами чи комами, масив рядків або будь-який інший формат. Наприклад, якщо ви вирішили кодувати ранги як76A5432QJKі підходить, якDCHSви могли використовувати входи, такі як['7D', '6H', 'QD', 'JS']або'7D,6H,QD,JS'.

Вихідні дані

Ціле число від 0 до 4, що представляє рахунок гравця.

Перемога

Найкоротша відповідь у байтах виграє!

Тестові справи

["7D", "6D", "AD", "5D", "4D", "3D", "2D", "QD", "7C", "6C", "4C", "3C", "2C", "7H", "4H", "2H", "5S", "3S", "QS", "JS", "KS"]

Оцінки 4 : 1 бал за> 20 карток, 1 бал за> 5 алмазів, 1 бал за 7 алмазів і 1 бал за 78 балів у примірії (7,7,7,5, де у суперника 7,6,5, К для 64)

["3D", "7C", "6C", "AC", "5C", "4C", "3C", "2C", "QC", "4H", "7S"]

Оцінки 0 : <= 20 карт, <5 алмазів, не 7 алмазів, і лише 69 в примірії (7,7,4,3, де у суперника 7,7,6, K на 70)

[7D", "6D", "AD", "5D", "4D", "3D", "2D", "7C", "6C", "AC", "5C", "4C", "3C", "2C", "7H", "6H", "AH", "5H", "4H", "3H", "2H"]

Оцінки 3 : 1 бал за> 20 карток, 1 бал за> 5 алмазів, 1 бал за 7 алмазів. Primiera буде 63 (7,7,7) і противник може тільки набрати 51 (7, Q, Q, Q) , але так як ця рука не має лопат вона втрачає точку за замовчуванням.

["7D", "6D", "AD", "5D", "4D", "3D", "2D", "QD", "JD", "KD", "QC", "QH", "QS"]

Оцінки 3 : <= 20 карток, 1 бал за> 5 алмазів, 1 бал за 7 алмазів. Primiera тільки бали 51 (7, Q, Q, Q) , і противник може набрати 63 (7,7,7) , але так як рука опонента не має алмазів ця рука виграє primiera точку за замовчуванням.

["7D", "6D", "AD", "5D", "4D", "3D", "2D", "QD", "JD", "KD", "7C", "7H"]

Оцінки 3 : <= 20 карток, 1 бал за> 5 алмазів, 1 бал за 7 алмазів. Незважаючи на те, що ця рука не має лопат, вона все одно виграє праймері на результат від 63 до 57 (7,7,7 проти 7,6,6), оскільки рука суперника не має алмазів.

["7D", "6D", "AD", "5D", "4D", "3D", "2D", "QD", "JD", "KD", "QC", "QH"]

Оцінки 2 : <= 20 карток, 1 бал за> 5 алмазів, 1 бал за 7 алмазів. У цієї руки немає лопат, а в руці суперника немає діамантів. Суперник виграє пер'єра з рахунком від 63 до 41 (7,7,7 проти 7, Q, Q).

[] (порожній масив)

Оцінки 0


1: Принаймні, в нашій родині Джек випереджає королеву в Скопі, але це не має значення для цілей озброєння.

2: Я граю в цю гру з дитинства і ніколи не бачив, щоб це сталося, але ваш код краще міг би впоратися з цим випадком!

3: Є бонусні бали за "зачистки", набрані під час раунду, які я ігнорую з метою цього виклику.


1
Чи кожне звання має бути представлене чітким символом?
Дверна ручка

@Doorknob Ні, не обов'язково, але, принаймні, в рішенні, над яким я працюю, я вважав за необхідне мати унікальний характер для кожного рангу, щоб правильно виконати всі тестові справи.
qdread

@Grimy гарний улов. дякую
qdread

Відповіді:


6

Рубі, 156 153 байт

->a{b='';([a[40],a.scan(/.d/)[5],a=~/;d/,'dchs'.gsub(/./){l=a.scan /.(?=#$&)/;l.size<10&&b+=(';865432'.tr(l*'','')+?0)[0];l.max}.sum>b.sum||p]-[p]).size}

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

->a{
b='';                # stores primiera of other player
([                   # this array stores all checks
a[40],               # check if >20 cards (>40 characters)
a.scan(/.d/)[5],     # check if >5 diamonds
a=~/;d/,             # check if 7 of diamonds
'dchs'.gsub(/./){    # for each suit, build a string with...
l=a.scan /.(?=#$&)/; # find all cards with this suit
l.size<10&&          # if there are less than 10, the other person has some, so
b+=                  # append to their score string the following:
(';865432'           #   start with all the cards
.tr(l*'','')         #   remove the ones we have
+?0)                 #   add back the JQK at the end
[0];                 #   take the highest
l.max}               # return the highest card that we have
.sum                 # take the sum of the codepoints
>b.sum               # check if it's greater than the other player's sum
||p                  # if not, evaluate to nil
]-[p])               # remove all nils
.size}               # count how many are left

Це використовується ;865432000для представлення76A5432QJK відповідно, а костюми - малі. (Вибір символів полягає в тому, що віднімання 38 з кожного дає значення їх первістки, але ми насправді цього не робимо, оскільки має значення лише відносна різниця.)

Ми не перевіряємо, чи не вистачає жодному гравцеві костюм, оскільки він непотрібний - оскільки всі картки рахуються як 38 плюс їх фактична вартість, якщо хтось не вистачає костюму, найвищий бал, який вони можуть отримати, є (21 + 38) * 3 = 177, що менше (10 + 38) * 3 + 21 + 38 = 203, найнижчий бал, який може отримати інший гравець. Ми не можемо, щоб два гравці пропустили неоднакову ненульову кількість костюмів, тому що гравцеві може бути відсутнє лише 0, 1 або 2 костюми, а якщо комусь не вистачає 2 костюми, у них є всі картки інших 2 костюмів.


4

R, 320 298 265 238 229 224 211 209 179 байт

Це рішення в основному завдяки @digEmAll, у вигляді функції.

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

function(h,S=sum,A=apply,l=99+c(11,8,5:2,6,!1:3)%o%!!1:4)S(S(p<-outer(c(7:2,'A','K','J','Q'),c('D','C','H','S'),paste0)%in%h)>20,S(p[1:10])>5,p[1],S(A(l*p,2,max)-A(l*!p,2,max))>0)

Нижче - найкращі мої старі посередні спроби на 209 байт.

редагувати: гольф вниз шляхом згладжування деяких функцій, потім, використовуючи ідею Дорнобба про додавання константи до рахунку замість перевірки костюмів.

Наступна редакція: позбулася деякої надмірності, а потім включила деякі вдосконалення від Джузеппе

наступна редакція: -2 байти завдяки digEmAll

Мені це страшно, тому я впевнений, що хтось може покращити це, якщо дбати про те, щоб витратити час. Я відчуваю, що sapplyі functionсупер довго і могли б позбутися від них , але я не можу зрозуміти, яким чином . Вхідні дані - це двозначні рядки у стандартній нотації.

function(h,s=sum,l=c(11,8,5:2,6,!1:3)+99)s(length(h)>20,s(grepl('D',h))>5,'7D'%in%h,s(sapply(c('D','C','H','S'),function(i,r=c(7:2,'A','K','J','Q')%in%substr(h[grep(i,h)],1,1))s(l[r][1],-l[!r][1],na.rm=T)))>0)

1
Можливо, вам вдасться отримати допомогу в кімнаті для спілкування з гольфом R , digEmAll навіть є італійцем!
Джузеппе

1
Просто кілька порад, але якщо ви можете поміняти крапку з двокрапкою на новий рядок (схоже, що це один байт у R), це безкоштовна заміна, яка зробить вашу відповідь більш зрозумілою. Крім того, ознайомтеся з " Спробуйте в Інтернеті", який є запущеним онлайн-кодом, якщо ви цього не зробили. Не потрібно, але знову ж таки, приємно користуватися. Він навіть може генерувати повідомлення про
CGCC

1
253 байти - Я не зовсім впевнений, що це спрацює, оскільки я в основному пробував звичайний набір гольфів, але сміливо тестуйте і дайте мені знати.
Джузеппе



2

JavaScript (ES6),  171  163 байт

Приймає дані як набір карток, використовуючи їх стандартне подання.

c=>(c.size>20)+((g=o=>[..."CHSD"].map(s=>[..."JQK2345A67"].map((v,i)=>(S=o^c.has(v+s))?m="111345679"[++n,i]||12:0,n=m=0)|(n?0:T=1,t-=m),T=t=4)|t*T)(1)>g``)+S+(n>5)

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

Прокоментував

c =>                                // c = set of cards
  (c.size > 20) + (                 // +1 point if we have more than 20 cards
    ( g = o =>                      // g is a function taking the flag o (for 'opponent')
      [..."CHSD"].map(s =>          // for each suit s, ending with diamonds:
        [..."JQK2345A67"]           //   for each rank v at position i, sorted from
        .map((v, i) =>              //   lowest to highest primiera score:
          (S = o ^ c.has(v + s)) ?  //     if the player owns this card, set S to 1 and:
            m = "111345679"[++n, i] //       increment n; update m to the score of this
                || 12               //       rank (we use the official score - 9)
          :                         //     else:
            0,                      //       do nothing
          n = m = 0                 //     start with n = m = 0
        ) |                         //   end of inner map()
        ( n ? 0 : T = 1,            //   if n = 0, set T to 1
          t -= m ),                 //   subtract m from t
        T = t = 4                   //   start with T = t = 4
      ) | t * T                     // end of outer map(); yield t * T
    )(1) > g``                      // +1 point if g(1) is greater than g(0)
  ) +                               // (we test this way because the scores are negative)
  S +                               // +1 point if we own the 7 of diamonds
  (n > 5)                           // +1 point if we own more than 5 diamonds

2

05AB1E , 41 байт

39ÝsK‚εg9y@Oy0å•Dδ¿m(/d•₆вy.γT÷}è€àO)}`›O

Спробуйте в Інтернеті або перевірте всі тестові випадки .

Костюми DCHSвідповідно представлені символом 0123. Ранги 7A65432KJQвідповідно представлені через0123456789 . Вони приймаються як рядки, а не цілі числа, як того вимагає виклик (але тоді 05AB1E перетворює їх у цілі числа, коли це потрібно).

Як і в інших рішеннях, ми додаємо велику константу (14) до кожної оцінки першості, щоб зробити перевірку на відсутність костюмів непотрібною.

39Ý                      # range 0..39 (the list of all cards in the game)
   sK                    # remove all elements that appear in the input
      ‚                  # pair with the input: [player's hand, opponent's hand]

ε                     }  # map each hand to a list of its 4 subscores:
 g                       #  first subscore: length (number of cards)
 9y@O                    #  second subscore: count elements <= 9 (diamonds)
 y0å                     #  third subscore: is 0 (representing 7D) in the list
            y.γT÷}       #  group the hand by suit
 •Dδ¿m(/d•₆в      è      #  map each rank to its primiera score
                   ۈ    #  maximum primiera score in each suit
                     O   #  fourth subscore: the sum of those

`›                       # for each subscore: is player's > opponent's?
  O                      # sum
```

2

MS SQL Server 2017 , 525 байт

CREATE FUNCTION f(@ NVARCHAR(MAX))RETURNS TABLE RETURN
SELECT q/21+IIF(d>6,2,IIF(d=6,1,0))+IIF(m=0,IIF(n=0 AND a>b,1,0),IIF(n=0 OR a>b,1,0))p
FROM(SELECT SUM(q)q,MAX(IIF(s='D',q,0))d,SUM(a)a,MIN(q)m,SUM(b)b,MIN(10-q)n
FROM(SELECT s,COUNT(k)q,MAX(IIF(r=k,v,0))a,MAX(IIF(r=k,0,v))b
FROM(SELECT LEFT(value,1)r,s,ASCII(RIGHT(value,1))-38 v
FROM STRING_SPLIT('7;,68,A6,5,4,3,2,Q0,J0,K0',','),(VALUES('D'),('C'),('H'),('S'))s(s))d
LEFT JOIN(SELECT LEFT(value,1)k,RIGHT(value,1)u FROM STRING_SPLIT(@,','))a
ON r+s=k+u GROUP BY s)t)t

Спробуйте його на db <> fiddle .


1

Сітківка 0,8,2 , 334 байти

$
 ¶234567JQKA
r`.\G
$&C $&D $&H $&S 
+`((\w\w).*¶.*)\2 
$1
T`67AJQK`8960
%O$`(\w)(\w)
$2$1
m`^(?=(...)*)(.C )*(.D )*(.H )*(.S )*
$3;$#1 $#2 $#3 $#4 $#5;${2}${3}${4}$5
m`^(?=(9D))?...;
$#1;
(;(?!.*10).* 0.*;).*
$1
\d[C-S] 
1$&
19\w 
21$*@
\d+(\w )?
$*@
(@)?;(@*) @* (@*).*;(@*)¶@?;((?!\2))?@* @* ((?!\3))?.*;((?!\4))?.*
$#1$#5$#6$#7
1

Спробуйте в Інтернеті! Посилання включає тестові випадки. Пояснення:

$
 ¶234567JQKA
r`.\G
$&C $&D $&H $&S 

Створіть список усіх 40 карток.

+`((\w\w).*¶.*)\2 
$1

Вийміть картки, які має гравець.

T`67AJQK`8960

Замініть кожен ранг на його порядок сортування, який на 9 7і на 10 менше, ніж його значення для інших карт.

%O$`(\w)(\w)
$2$1

Сортуйте картки за костюмом та рангом.

m`^(?=(...)*)(.C )*(.D )*(.H )*(.S )*
$3;$#1 $#2 $#3 $#4 $#5;${2}${3}${4}$5

Порахуйте кількість карток у кожному костюмі, а також захопіть карту найвищого рейтингу у кожному костюмі, захопивши найвищий діамант двічі.

m`^(?=(9D))?...;
$#1;

Перевірте, чи був найвищий діамант 7.

(;(?!.*10).* 0.*;).*
$1

Видаліть усі найвищі карти, якщо в одному з костюмів немає карт.

\d[C-S] 
1$&
19\w 
21$*@
\d+(\w )?
$*@

Перетворіть найвищі картки в їхні одинакові оцінки та підсумуйте їх. Також конвертуйте загальну кількість карток і довжину костюмів в одинакові.

(@)?;(@*) @* (@*).*;(@*)¶@?;((?!\2))?@* @* ((?!\3))?.*;((?!\4))?.*
$#1$#5$#6$#7

Набирайте бали, якщо сумарна сума, діаманти або примірія вище.

1

Загальна оцінка.



1

AWK , 235 байт

{s[9]=35;s[8]=32;s[7]=30;s[6]=29;s[5]=28;s[4]=27;s[3]=26;s[2]=s[1]=s[0]=24;a[$1 $2]=s[$1]}END{while(i++<4){D=0;for(j=0;j<10;j++){if(a[j i]<1){B[i]=s[j];D++}if(A[i]<a[j i])A[i]=a[j i]}x+=A[i];y+=B[i]}print(20<NR)+(D<5)+(1<a[9 4])+(y<x)}

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

Мапа костюмів до 1234 (4 діаманти), значення значень - 0123456789. Ця програма перетворює тестові випадки у прийнятий формат:

BEGIN{RS=", ";FS="";t[7]=9;t[6]=8;t["A"]=7;t[5]=6;t[4]=5;t[3]=4;t[2]=3;t["Q"]=2;t["J"]=1;t["K"]=0;u["D"]=4;u["C"]=1;u["H"]=2;u["S"]=3}{gsub("[\\[\"\\]]","",$0);print t[$1],u[$2]}

Моєю метою було просто перемогти провідну реалізацію Python: D


1

Python 3 , 249 245 239 238 байт

-4 байти завдяки @ovs

-6 байт завдяки @movatica

lambda C:sum([len(C)>20,'7D'in C,len([c for c in C if'E'>c[1]])>5,p(C)>p({n+s for n in'9876543210'for s in S}-C)])
p=lambda C:[not S.strip(''.join(C)),sum(max([(c[1]==s)*int('9gcdefil99'[int(c[0])],22)for c in C]+[0])for s in S)]
S='DcHS'

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


1
На 2 байти менше int('0734569c00'[int(x[0])],13)і if x[1]<'E'можна записати якif'E'>x[1]
впр

all(s in''.join(C)for s in S)можна скоротити до not S.strip(''.join(C))економії 6 байт
movatica
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.