Jaki jest wynik mojej ręki Scopa?

14

Lubię wyzwania związane z grami karcianymi, więc zrobiłem to dla włoskiej gry karcianej Scopa. Moja rodzina gra w tę grę od niepamiętnych czasów. Ma bardzo interesujący system punktacji, który powinien sprawiać przyjemność golfowi. Wyślę odpowiedź w R, aby rozpocząć zabawę, jestem pewien, że ludzie poprawią się.

Wyzwanie: obliczyć liczbę punktów zdobytych w rundzie Scopa, biorąc pod uwagę karty, które gracz złapał podczas rundy jako wkład.

W talii Scopa znajduje się 40 kart. Jeśli używasz talii międzynarodowej, usuwasz 8s, 9s i 10s, pozostawiając A, 2,3,4,5,6,7, Q, J, K w każdym kolorze. 1 Jest dwóch graczy lub partnerów, a po każdej rundzie wszystkie karty zostają schwytane przez jednego lub dwóch graczy. Wynik liczony jest w następujący sposób (więcej informacji tutaj ):

  • Gracz z największą liczbą kart zdobywa 1 punkt.
  • Gracz z największą ilością diamentów (lub monet, jeśli używa talii włoskiej) zdobywa 1 punkt.
  • Gracz z 7 diamentami (lub monetami), znany jako Sette Bello lub Beautiful Seven, zdobywa 1 punkt.
  • Gracz z najwyższą primierą zdobywa 1 punkt. Wynik Primiera gracza jest sumą wyników karty o najwyższej wartości, którą gracz przechwycił w każdym kolorze (patrz tabela poniżej). Jeśli nie masz co najmniej jednej karty w każdym kolorze, domyślnie przegrywasz, nawet jeśli Twój wynik przekroczy wynik przeciwnika. W niezwykle rzadkim przypadku, gdy żaden z graczy nie ma co najmniej jednej karty w każdym kolorze, gracz z wyższą sumą primiera zdobywa punkt. 2)

Tabela wyników primiera

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

Gracz może więc zdobyć maksymalnie 4 punkty w rundzie. 3 Jeśli jest remis, który jest możliwy dla kart, diamentów lub primiera , nikt nie zdobywa punktu.

Ważne jest, aby zdawać sobie sprawę, że ponieważ każda karta musi zostać schwytana przez jednego z dwóch graczy, możesz wywnioskować, jakie karty musiał wziąć drugi gracz, nawet jeśli wiesz tylko, jakie karty wziął jeden gracz. Musisz to zrobić, aby poprawnie zdobyć Primiera .

Zasady wyzwania

Wejście

Twój kod powinien pobierać jako dane wejściowe karty przechwycone przez jednego gracza podczas rundy Scopa.

Dane wejściowe muszą być w postaci łańcucha, w którym jeden znak reprezentuje rangę każdej karty, a jeden znak w jej kolorze. Usuwa to potencjalną lukę w przekazywaniuwyników primiera bezpośrednio jako danych wejściowych. Konwersja rang kart nawyniki Primiera musi odbywać się w programie. Możesz jednak użyć pojedynczego ciągu oddzielonego spacjami lub przecinkami, tablicy ciągów lub dowolnego innego formatu. Na przykład, jeśli zdecydujesz się zakodować rangi jako76A5432QJKi kolory, jakDCHSmożesz użyć danych wejściowych takich jak['7D', '6H', 'QD', 'JS']lub'7D,6H,QD,JS'.

Wynik

Liczba całkowita od 0 do 4 reprezentująca wynik gracza.

Zwycięski

Najkrótsza odpowiedź w bajtach wygrywa!

Przypadki testowe

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

Zdobywa 4 : 1 punkt za> 20 kart, 1 punkt za> 5 diamentów, 1 punkt za 7 diamentów i 1 punkt za zdobycie 78 w primiera (7,7,7,5, gdy przeciwnik ma 7,6,5, K dla 64)

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

Wyniki 0 : <= 20 kart, <= 5 karo, nr 7 karo, i zdobywa tylko 69 w primiera (7,7,4,3, gdy przeciwnik ma 7,7,6, K dla 70)

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

Wyniki 3 : 1 punkt za> 20 kart, 1 punkt za> 5 diamentów, 1 punkt za 7 diamentów. Primiera byłoby 63 (7,7,7), a przeciwnik może zdobyć tylko 51 (7, P, Q, Q), ale ponieważ ta ręka nie ma piki traci punkt domyślnie.

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

Wyniki 3 : <= 20 kart, 1 punkt za> 5 diamentów, 1 punkt za 7 diamentów. Primiera tylko zdobywa 51 (7, P, Q, Q), a przeciwnik może zdobyć 63 (7,7,7), ale od ręki przeciwnika nie ma diamentów ta ręka wygrywa primiera punkt domyślnie.

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

Wyniki 3 : <= 20 kart, 1 punkt za> 5 diamentów, 1 punkt za 7 diamentów. Chociaż ta ręka nie ma pik, nadal wygrywa Primiera wynikiem od 63 do 57 (7,7,7 kontra 7,6,6), ponieważ ręka przeciwnika nie ma diamentów.

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

Wyniki 2 : <= 20 kart, 1 punkt za> 5 diamentów, 1 punkt za 7 diamentów. Ta ręka nie ma pik, a ręka przeciwnika nie ma diamentów. Przeciwnik wygrywa primiera wynikiem 63 do 41 (7,7,7 w porównaniu z 7, Q, Q).

[] (pusta tablica)

Wyniki 0


1: Przynajmniej w naszej rodzinie Jack przewyższa Królową w Scopie, ale nie ma to znaczenia dla punktacji.

2: Gram w tę grę od dzieciństwa i nigdy tego nie widziałem, ale twój kod lepiej poradziłby sobie z tą sprawą!

3: Podczas rundy są punkty bonusowe za „zamiatanie”, które ignoruję na potrzeby tego wyzwania.

qdread
źródło
1
Czy każda ranga musi być reprezentowana przez odrębną postać?
Klamka
@Doorknob Nie, niekoniecznie, ale przynajmniej w rozwiązaniu, nad którym pracuję, konieczne było posiadanie unikalnego charakteru dla każdej rangi, aby wszystkie przypadki testowe działały poprawnie.
qdread
@Grimy dobry połów. dzięki
qdread

Odpowiedzi:

6

Rubin, 156 153 bajtów

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

Wypróbuj online!

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

To używa ;865432000 do reprezentowania 76A5432QJKodpowiednio, a kolory są pisane małymi literami. (Wybór znaków wynika z faktu, że odjęcie 38 od każdego daje wartość primiera, ale tak naprawdę nigdy tego nie robimy, ponieważ liczy się tylko różnica względna).

Nie sprawdzamy, czy któryś z graczy brakuje koloru, ponieważ nie jest to konieczne - ponieważ wszystkie karty są liczone jako 38 plus ich rzeczywista wartość, jeśli komuś brakuje koloru, najwyższy możliwy wynik to (21 + 38) * 3 = 177, czyli mniej niż (10 + 38) * 3 + 21 + 38 = 203, najniższy wynik, jaki może uzyskać inny gracz. Nie możemy pozwolić dwóm graczom pominąć różnej niezerowej liczby kolorów, ponieważ graczowi może brakować tylko 0, 1 lub 2 kolorów, a jeśli komuś brakuje 2 kolorów, mają wszystkie karty z pozostałych 2 kolorów.

Klamka
źródło
4

R, 320 298 265 238 229 224 211 209 179 bajtów

Jest to rozwiązanie głównie ze względu na @digEmAll, w postaci funkcji.

Wypróbuj online!

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)

Poniżej znajduje się najlepsza moja stara mierna próba 209 bajtów.

edycja: gra w golfa poprzez aliasing niektórych funkcji, a następnie przyjęcie pomysłu Doorknob polegającego na dodaniu stałej do wyniku zamiast sprawdzania koloru.

następna edycja: pozbyłem się nadmiaru, a następnie wprowadziłem kilka ulepszeń od Giuseppe

następna edycja: -2 bajty dzięki digEmAll

Jestem w tym okropny, więc jestem pewien, że ktoś może to poprawić, jeśli zechce poświęcić trochę czasu. Czuję się jak sapplyi functionjest bardzo długa i mogę się ich pozbyć, ale nie wiem, jak to zrobić. Dane wejściowe to dwuznakowe ciągi w standardowej notacji.

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)
qdread
źródło
1
Możesz być w stanie uzyskać pomoc na czacie R golfa , digEmAll jest nawet innym Włochem!
Giuseppe
1
Tylko kilka rad, ale jeśli możesz zamienić średnik tylko na nowy wiersz (który wygląda na jeden bajt w R), jest to darmowa zamiana, dzięki której twoja odpowiedź jest bardziej czytelna. Sprawdź także Try It Online, który jest internetowym programem uruchamiającym kody, jeśli jeszcze tego nie zrobiłeś. Nie wymagane, ale znowu, miłe w użyciu. Może nawet generować posty
CGCC
1
253 bajty - nie jestem do końca pewien, czy to zadziała, ponieważ głównie próbowałem zwykłego zestawu golfów, ale nie krępuj się przetestować i daj mi znać.
Giuseppe,
1
209
digEmAll
2

JavaScript (ES6),  171  163 bajtów

Pobiera dane wejściowe jako zestaw kart, używając ich standardowej reprezentacji.

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)

Wypróbuj online!

Skomentował

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
Arnauld
źródło
2

05AB1E , 41 bajtów

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

Wypróbuj online lub sprawdź wszystkie przypadki testowe .

Kolory DCHSsą odpowiednio reprezentowane przez 0123. Rangi 7A65432KJQsą odpowiednio reprezentowane przez 0123456789. Są one brane jako ciągi, a nie liczby całkowite, zgodnie z wymaganiami wyzwania (ale następnie 05AB1E konwertuje je na liczby całkowite, gdy są potrzebne).

Podobnie jak w innych rozwiązaniach, dodajemy dużą stałą (14) do każdego wyniku primiera, aby zbędne było sprawdzanie brakujących kolorów.

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
```
Ponury
źródło
2

MS SQL Server 2017 , 525 bajtów

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

Wypróbuj na skrzypcach db <> .

Andrei Odegov
źródło
1

Retina 0.8.2 , 334 bajty

$
 ¶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

Wypróbuj online! Link zawiera przypadki testowe. Wyjaśnienie:

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

Utwórz listę wszystkich 40 kart.

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

Wyjmij karty, które gracz trzyma.

T`67AJQK`8960

Zamień każdą rangę według kolejności sortowania, która wynosi 9 za 7i 10 mniej niż wartość innych kart.

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

Sortuj karty według koloru i rangi.

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

Policz liczbę kart w każdym kolorze, a także zdobądź kartę o najwyższym rankingu w każdym kolorze, dwukrotnie zdobywając najwyższy diament.

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

Sprawdź, czy najwyższy diament to 7.

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

Usuń wszystkie najwyższe karty, jeśli jeden z kolorów nie ma żadnych kart.

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

Konwertuj najwyższe karty na ich niepowtarzalny wynik i sumuj je razem. Przekształć również całkowitą liczbę kart i długości kolorów na unary.

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

Zdobywaj punkty, jeśli suma, diamenty lub primiera są wyższe.

1

Łączny wynik.

Neil
źródło
1

AWK , 235 bajtów

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

Wypróbuj online!

Odpowiada mapowaniu na 1234 (4 to diamenty), wartości mapowane na 0123456789. Ten program przekształca przypadki testowe w akceptowany format:

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

Moim celem było pokonanie wiodącej implementacji języka Python: D

Daniel LaVine
źródło
1

Python 3 , 249 245 239 238 bajtów

-4 bajty dzięki @ovs

-6 bajtów dzięki @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'

Wypróbuj online!

Czarna sowa Kai
źródło
1
2 bajty mniej z int('0734569c00'[int(x[0])],13)i if x[1]<'E'można je zapisać jakoif'E'>x[1]
ov
all(s in''.join(C)for s in S)można skrócić not S.strip(''.join(C)), oszczędzając 6 bajtów
movatica