Quel est le score de ma main Scopa?


14

J'aime les défis des jeux de cartes, j'ai donc fait celui-ci pour le jeu de cartes italien Scopa. Ma famille joue à ce jeu depuis des temps immémoriaux. Il a un système de notation très intéressant qui devrait être amusant pour le golf. Je vais poster une réponse en R pour commencer le plaisir, que je suis sûr que les gens vont améliorer.

Le défi: déterminer le nombre de points marqués lors d'une manche de Scopa, compte tenu des cartes saisies par le joueur lors de la manche.

Il y a 40 cartes dans un paquet Scopa. Si vous utilisez un deck international, vous supprimez les 8, 9 et 10, laissant A, 2,3,4,5,6,7, Q, J, K dans chaque combinaison. 1 Il y a deux joueurs ou partenariats, et après chaque tour, toutes les cartes sont capturées par l'un ou l'autre des deux joueurs. Le score est compté comme suit (plus d'informations ici ):

  • Le joueur avec le plus de cartes marque 1 point.
  • Le joueur avec le plus de diamants (ou de pièces s'il utilise le deck italien) marque 1 point.
  • Le joueur avec le 7 de diamants (ou pièces), connu sous le nom de sette bello ou beautiful seven, marque 1 point.
  • Le joueur avec la primiera la plus élevée marque 1 point. Le score primiera d' un joueur est la somme des scores de la carte de la plus haute valeur que le joueur a capturée dans chaque couleur (voir tableau ci-dessous). Si vous n'avez pas au moins une carte dans chaque couleur, vous perdez par défaut même si votre score dépasse le score de votre adversaire. Dans le cas extrêmement rare où aucun joueur n'a au moins une carte dans chaque couleur , le joueur avec le total de primiera le plus élevé marque le point. 2

Tableau des scores primiera

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

Ainsi, un joueur peut marquer au plus 4 points dans un tour. 3 S'il y a une cravate, ce qui est possible pour les cartes, les diamants ou les primiera , personne ne marque le point.

Il est important de réaliser que puisque chaque carte doit être capturée par l'un des deux joueurs, vous pouvez déduire quelles cartes l'autre joueur doit avoir prises même si vous ne savez que quelles cartes un joueur a prises. Vous devrez le faire pour marquer correctement primiera .

Règles du challenge

Contribution

Votre code doit prendre en entrée les cartes capturées par un seul joueur lors d'une manche de Scopa.

L'entrée doit être au format chaîne, dans laquelle un caractère représente le rang de chaque carte et un caractère sa couleur. Cela supprime la faille potentielle de passer lesscores primiera directement en entrée. La conversion des classements de cartes en scores primiera doit être effectuée dans le programme. Cependant, vous pouvez choisir d'utiliser une seule chaîne séparée par des espaces ou des virgules, un tableau de chaînes ou tout autre format. Par exemple, si vous choisissez de coder les rangs comme76A5432QJKet convient,DCHSvous pouvez utiliser des entrées telles que['7D', '6H', 'QD', 'JS']ou'7D,6H,QD,JS' .

Production

Un entier de 0 à 4 représentant le score du joueur.

Gagnant

La réponse la plus courte en octets gagne!

Cas de test

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

Scores 4 : 1 point pour> 20 cartes, 1 point pour> 5 diamants, 1 point pour les 7 diamants et 1 point pour avoir marqué 78 en primiera (7,7,7,5 où l'adversaire a 7,6,5, K pour 64)

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

Scores 0 : <= 20 cartes, <= 5 diamants, pas 7 de diamants, et ne marque que 69 en primiera (7,7,4,3 où l'adversaire a 7,7,6, K pour 70)

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

Scores 3 : 1 point pour> 20 cartes, 1 point pour> 5 diamants, 1 point pour 7 diamants. La primiera serait de 63 (7,7,7) et l'adversaire ne peut marquer que 51 (7, Q, Q, Q) mais comme cette main n'a pas de pique, elle perd le point par défaut.

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

Scores 3 : <= 20 cartes, 1 point pour> 5 diamants, 1 point pour 7 diamants. La primiera ne marque que 51 (7, Q, Q, Q) et l'adversaire peut marquer 63 (7,7,7) mais comme la main de l'adversaire n'a pas de diamants, cette main gagne le point primiera par défaut.

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

Scores 3 : <= 20 cartes, 1 point pour> 5 diamants, 1 point pour 7 diamants. Même si cette main n'a pas de pique, elle gagne toujours primiera par un score de 63 à 57 (7,7,7 contre 7,6,6) car la main de l'adversaire n'a pas de diamant.

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

Scores 2 : <= 20 cartes, 1 point pour> 5 diamants, 1 point pour 7 diamants. Cette main n'a pas de pique et la main de l'adversaire n'a pas de diamant. L'adversaire remporte la primiera par un score de 63 à 41 (7,7,7 contre 7, Q, Q).

[] (tableau vide)

Scores 0


1: Au moins dans notre famille, Jack devance Queen dans Scopa, mais cela n'est pas pertinent pour les buts.

2: Je joue à ce jeu depuis mon enfance et je n'ai jamais vu cela se produire, mais votre code devrait mieux gérer cette affaire!

3: Il y a des points bonus pour les "balayages" marqués pendant le tour que j'ignore dans le cadre de ce défi.


1
Chaque rang doit-il être représenté par un caractère distinct?
Poignée de porte

@ Doorknob Non pas nécessairement, mais au moins dans la solution sur laquelle je travaille, j'ai trouvé nécessaire d'avoir un caractère unique pour chaque rang pour obtenir tous les cas de test.
qdread

@Grimy bonne capture. merci
qdread

Réponses:


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}

Essayez-le en ligne!

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

Cela utilise ;865432000pour représenter76A5432QJK respectivement, et les combinaisons sont en minuscules. (Le choix des caractères est dû au fait que la soustraction de 38 à chacun donne leur valeur primiera, mais nous ne le faisons jamais réellement parce que seule la différence relative compte.)

Nous ne vérifions pas s'il manque un costume à l'un ou l'autre des joueurs car cela n'est pas nécessaire - puisque toutes les cartes sont comptées comme 38 plus leur valeur réelle, si quelqu'un manque un costume, le score le plus élevé qu'il peut obtenir est (21 + 38) * 3 = 177, ce qui est inférieur à (10 + 38) * 3 + 21 + 38 = 203, le score le plus bas que l'autre joueur puisse obtenir. Nous ne pouvons pas laisser les deux joueurs manquer un nombre de combinaisons différent de zéro, car un joueur ne peut manquer que 0, 1 ou 2 combinaisons, et si quelqu'un manque 2 combinaisons, il a toutes les cartes des 2 autres combinaisons.


4

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

C'est une solution principalement due à @digEmAll, sous la forme d'une fonction.

Essayez-le en ligne!

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)

Ci-dessous est le meilleur de mes anciennes tentatives médiocres pour 209 octets.

edit: joué au golf en aliasant certaines fonctions, puis en prenant l'idée de Doorknob d'ajouter une constante au score au lieu de vérifier les combinaisons.

prochaine édition: débarrassé de certaines redondances, puis incorporé quelques améliorations de Giuseppe

prochaine édition: -2 octets grâce à digEmAll

Je suis horrible à ce sujet, donc je suis sûr que quelqu'un peut améliorer cela s'il veut prendre le temps. Je me sens comme sapplyet je suis functionsuper longue et je pourrais m'en débarrasser mais je ne sais pas comment. Les entrées sont des chaînes de deux caractères dans la notation standard.

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
Vous pourrez peut-être obtenir de l'aide dans le salon de golf R , digEmAll est même un collègue italien!
Giuseppe

1
Juste quelques conseils mais si vous pouvez échanger un point-virgule juste une nouvelle ligne (qui semble être un octet dans R), c'est un échange gratuit qui rend votre réponse plus lisible. En outre, consultez Try It Online, qui est un exécuteur de code en ligne si vous ne l'avez pas fait. Pas nécessaire, mais encore une fois, agréable à utiliser. Il peut même générer des messages CGCC
Veskah

1
253 octets - Je ne suis pas totalement sûr que cela fonctionnera, car j'essayais principalement l'ensemble de golf habituel, mais n'hésitez pas à tester et à me le faire savoir.
Giuseppe



2

JavaScript (ES6),  171  163 octets

Prend l'entrée comme un ensemble de cartes, en utilisant leur représentation standard.

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)

Essayez-le en ligne!

Commenté

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 octets

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

Essayez-le en ligne ou vérifiez tous les cas de test .

Les costumes DCHSsont respectivement représentés par0123 . Les rangs 7A65432KJQsont respectivement représentés par0123456789 . Celles-ci sont prises comme des chaînes, pas des entiers, comme requis par le défi (mais ensuite 05AB1E les convertit en entiers quand c'est nécessaire).

Comme dans les autres solutions, nous ajoutons une grande constante (14) à chaque score primiera afin de rendre inutile la vérification des combinaisons manquantes.

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 octets

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

Essayez-le sur db <> violon .


1

Retina 0.8.2 , 334 octets

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

Essayez-le en ligne! Le lien inclut des cas de test. Explication:

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

Créez une liste des 40 cartes.

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

Retirez les cartes que le joueur détient.

T`67AJQK`8960

Remplacez chaque rang par son ordre de tri, qui est de 9 pour 7et 10 de moins que sa valeur pour les autres cartes.

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

Triez les cartes par couleur et rang.

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

Comptez le nombre de cartes dans chaque couleur et capturez également la carte la mieux classée dans chaque couleur, capturant le diamant le plus élevé deux fois.

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

Vérifiez si le diamant le plus élevé était le 7.

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

Supprimez toutes les cartes les plus élevées si l'une des combinaisons n'a pas de cartes.

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

Convertissez les cartes les plus élevées en leur score unaire et additionnez-les. Convertissez également le nombre total de cartes et de longueurs de costume en unaire.

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

Marquez des points si le total, diamants ou primiera, est plus élevé.

1

Faites le total du score.



1

AWK , 235 octets

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

Essayez-le en ligne!

La carte convient à 1234 (4 correspond aux diamants), la valeur correspond à 0123456789. Ce programme transforme les cas de test au format accepté:

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

Mon objectif était juste de battre l'implémentation Python leader: D


1

Python 3 , 249 245 239 238 octets

-4 octets grâce à @ovs

-6 octets grâce à @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'

Essayez-le en ligne!


1
2 octets de moins avec int('0734569c00'[int(x[0])],13)et if x[1]<'E'peut être écrit commeif'E'>x[1]
ovs

all(s in''.join(C)for s in S)peut être raccourci en not S.strip(''.join(C))économisant 6 octets
movatica
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.