Qual é a pontuação da minha mão Scopa?


14

Eu gosto de desafios de jogos de cartas, então fiz este para o jogo de cartas italiano Scopa. Minha família joga esse jogo desde tempos imemoriais. Tem um sistema de pontuação muito interessante que deve ser divertido para o golfe. Vou postar uma resposta em R para começar a diversão, que tenho certeza de que as pessoas vão melhorar.

O desafio: descobrir o número de pontos marcados em uma rodada de Scopa, considerando as cartas que o jogador capturou durante a rodada como entrada.

Existem 40 cartas no baralho Scopa. Se você estiver usando um baralho internacional, remova os 8s, 9s e 10s, deixando A, 2,3,4,5,6,7, Q, J, K em cada naipe. 1 Existem dois jogadores ou parcerias e, após cada rodada, todas as cartas acabam sendo capturadas por um ou outro dos dois jogadores. A pontuação é contada da seguinte forma (mais informações aqui ):

  • O jogador com mais cartas ganha 1 ponto.
  • O jogador com mais diamantes (ou moedas, se estiver usando o baralho italiano) recebe 1 ponto.
  • O jogador com o 7 de diamantes (ou moedas), conhecido como sette bello ou belo sete, marca 1 ponto.
  • O jogador com a primiera mais alta marca 1 ponto. A pontuação inicial de um jogador é a soma das pontuações da carta de maior valor que o jogador capturou em cada naipe (veja a tabela abaixo). Se você não tiver pelo menos uma carta em cada naipe, você perde por padrão, mesmo que sua pontuação exceda a pontuação do seu oponente. No caso extremamente raro de nenhum dos dois jogadores ter pelo menos uma carta em cada naipe, o jogador com a pontuação mais alta total pontua o ponto. 2

Tabela de pontuações primiera

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

Assim, um jogador pode marcar no máximo 4 pontos em uma rodada. 3 Se houver um empate, possível para cartas, diamantes ou primiera , ninguém marca o ponto.

É importante perceber que, como cada carta deve ser capturada por um dos dois jogadores, é possível inferir quais cartas o outro jogador deve ter pegado, mesmo se você souber apenas quais cartas um jogador pegou. Você precisará fazer isso para marcar corretamente a primiera .

Regras do desafio

Entrada

Seu código deve ter como entrada as cartas capturadas por um único jogador durante uma rodada de Scopa.

A entrada deve estar no formato de sequência, em que um caractere representa a classificação de cada cartão e um caractere seu naipe. Isso remove a brecha potencial de passar aspontuaçõesdo primiera diretamente como entrada. A conversão de classificações de cartões em pontuações primárias deve ser feita no programa. No entanto, você pode optar por usar uma única cadeia de caracteres separada por espaços ou vírgulas, uma matriz de cadeias de caracteres ou qualquer outro formato. Por exemplo, se você optar por codificar classificações como76A5432QJKe naipes,DCHSpoderá usar entradas como['7D', '6H', 'QD', 'JS']ou'7D,6H,QD,JS'.

Resultado

Um número inteiro de 0 a 4 representando a pontuação do jogador.

Ganhando

Menor resposta em bytes ganha!

Casos de teste

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

Pontuação 4 : 1 ponto para> 20 cartas, 1 ponto para> 5 diamantes, 1 ponto para o 7 de diamantes e 1 ponto para marcar 78 na primiera (7,7,7,5 onde o oponente tem 7,6,5, K para 64)

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

Pontuações 0 : <= 20 cartas, <= 5 diamantes, nº 7 de diamantes e apenas 69 pontos em primiera (7,7,4,3 onde o oponente tem 7,7,6, K por 70)

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

Pontuações 3 : 1 ponto para> 20 cartas, 1 ponto para> 5 diamantes, 1 ponto para 7 de diamantes. A primiera seria 63 (7,7,7) e o oponente só pode marcar 51 (7, Q, Q, Q), mas como essa mão não tem espadas, perde o ponto por padrão.

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

Pontuações 3 : <= 20 cartões, 1 ponto para> 5 diamantes, 1 ponto para 7 de diamantes. A primiera marca apenas 51 (7, Q, Q, Q) e o oponente pode marcar 63 (7,7,7), mas como a mão do oponente não tem diamantes, esta mão ganha o ponto de primiera por padrão.

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

Pontuações 3 : <= 20 cartões, 1 ponto para> 5 diamantes, 1 ponto para 7 de diamantes. Mesmo que essa mão não tenha espadas, ela ainda vence primiera com uma pontuação de 63 a 57 (7,7,7 contra 7,6,6) porque a mão do oponente não tem diamantes.

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

Pontuações 2 : <= 20 cartões, 1 ponto para> 5 diamantes, 1 ponto para 7 de diamantes. Esta mão não tem espadas e a mão do oponente não tem diamantes. O oponente vence a primiera com uma pontuação de 63 a 41 (7,7,7 contra 7, Q, Q).

[] (matriz vazia)

Pontuações 0


1: Pelo menos em nossa família, Jack supera o Queen em Scopa, mas isso é irrelevante para fins de pontuação.

2: Eu jogo esse jogo desde a infância e nunca vi isso acontecer, mas é melhor o seu código lidar com esse caso!

3: Existem pontos de bônus por "varreduras" marcadas durante a rodada que eu estou ignorando para o objetivo deste desafio.


1
Cada classificação deve ser representada por um caractere distinto?
Maçaneta

@ Doorknob Não, não necessariamente, mas pelo menos na solução em que estou trabalhando, achei necessário ter um caractere único para cada classificação para acertar todos os casos de teste.
Qdread 25/09/19

@ Boa captura imunda. graças
qdread

Respostas:


6

Ruby, 156 153 bytes

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

Experimente 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

Isso costuma ;865432000representar 76A5432QJKrespectivamente, e os naipes estão em minúsculas. (A escolha dos caracteres ocorre porque a subtração de 38 de cada um dá o seu valor primiera, mas nunca o fazemos porque apenas a diferença relativa é importante.)

Não verificamos se um dos jogadores está com falta de um naipe porque é desnecessário - como todas as cartas são contadas como 38 mais o seu valor real, se alguém está com falta de um naipe, a pontuação mais alta que eles podem obter é (21 + 38) * 3 = 177, que é menor que (10 + 38) * 3 + 21 + 38 = 203, a pontuação mais baixa que o outro jogador pode obter. Não podemos fazer com que os dois jogadores não tenham um número diferente de zero de naipes, porque um jogador só pode ter 0, 1 ou 2 naipes, e se alguém estiver faltando 2 naipes, terá todas as cartas dos outros 2 naipes.


4

R, 320 298 265 238 229 224 211 209 179 bytes

Esta é uma solução principalmente devido a @digEmAll, na forma de uma função.

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

Abaixo está a melhor das minhas antigas tentativas medíocres de 209 bytes.

edit: reduziu o apelido de algumas funções e depois tomou a idéia de Maçaneta de adicionar uma constante à pontuação, em vez de verificar os naipes.

próxima edição: se livrou de alguma redundância e depois incorporou algumas melhorias do Giuseppe

próxima edição: -2 bytes graças a digEmAll

Sou péssimo nisso, por isso tenho certeza de que alguém pode melhorar isso se quiser tomar um tempo. Sinto-me como sapplye functionsou super longa e poderia me livrar deles, mas não consigo descobrir como. As entradas são cadeias de dois caracteres na notação padrão.

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
Você pode conseguir ajuda na sala de bate-papo de golfe R , digEmAll é até um colega italiano!
Giuseppe

1
Apenas alguns conselhos, mas se você puder trocar um ponto e vírgula apenas uma nova linha (que parece ser um byte em R), é uma troca gratuita que torna sua resposta mais legível. Além disso, confira o Try It Online, que é um corredor de código on-line, se você não tiver. Não é necessário, mas, novamente, agradável de usar. Pode até gerar posts
CGCC

1
253 bytes - Não tenho certeza absoluta de que isso funcionará, pois eu estava tentando o jogo de golfe habitual, mas sinta-se à vontade para testar e me informar.
Giuseppe



2

JavaScript (ES6),  171  163 bytes

Recebe a entrada como um conjunto de cartões, usando sua representação padrão.

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)

Experimente online!

Comentado

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 bytes

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

Experimente online ou verifique todos os casos de teste .

Os naipes DCHSsão representados respectivamente por 0123. As classificações 7A65432KJQsão representadas respectivamente por 0123456789. Esses são tomados como cadeias, não números inteiros, conforme exigido pelo desafio (mas 05AB1E os converte em números inteiros quando necessário, de qualquer maneira).

Como em outras soluções, adicionamos uma constante grande (14) a cada pontuação de primiera para tornar desnecessária a verificação de fatos perdidos.

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 bytes

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

Experimente no db <> fiddle .


1

Retina 0.8.2 , 334 bytes

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

Experimente online! O link inclui casos de teste. Explicação:

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

Crie uma lista de todos os 40 cartões.

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

Retire as cartas que o jogador segura.

T`67AJQK`8960

Substitua cada classificação por sua ordem de classificação, que é 9 para 7e 10 menor que seu valor para outras cartas.

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

Classifique as cartas por naipe e classificação.

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

Conte o número de cartas em cada naipe e também capture a carta mais alta de cada naipe, capturando o diamante mais alto duas vezes.

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

Verifique se o diamante mais alto foi o 7.

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

Exclua todas as cartas mais altas se um dos naipes não tiver cartas.

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

Converta as cartas mais altas em pontos unários e some-as. Também converta o número total de cartas e comprimentos de naipes para unário.

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

Marque pontos se o total, diamantes ou primiera, for maior.

1

Total da pontuação.



1

AWK , 235 bytes

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

Experimente online!

Serve para mapear 1234 (4 são diamantes), valores mapear para 0123456789. Este programa transforma os casos de teste no formato aceito:

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

Meu objetivo era apenas vencer a principal implementação do Python: D


1

Python 3 , 249 245 239 238 bytes

-4 bytes graças a @ovs

-6 bytes graças a @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'

Experimente online!


1
2 bytes a menos com int('0734569c00'[int(x[0])],13)e if x[1]<'E'pode ser gravado comoif'E'>x[1]
ovs 26/09

all(s in''.join(C)for s in S)pode ser reduzido not S.strip(''.join(C)), economizando 6 bytes
movatica
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.