Combien de séquences de Blackjack dans cette liste?

21

Votre tâche consiste à trouver combien de séquences de Blackjack distinctes peuvent être trouvées dans une liste ordonnée de 12 cartes.

Une séquence de Blackjack est définie comme une séquence de cartes consécutives dont la somme des points est exactement 21. Les points sont comptés selon le tableau suivant:

Symbol | Name  | Points     Symbol | Name  | Points
-------+-------+--------    -------+-------+--------
   2   | Two   | 2             9   | Nine  | 9
   3   | Three | 3             T   | Ten   | 10
   4   | Four  | 4             J   | Jack  | 10
   5   | Five  | 5             Q   | Queen | 10
   6   | Six   | 6             K   | King  | 10
   7   | Seven | 7             A   | Ace   | 1 or 11
   8   | Eight | 8

Contribution

Une chaîne de 12 caractères, utilisant les symboles décrits ci-dessus. Nous ne nous soucions pas des couleurs des cartes, elles ne sont donc pas fournies.

Exemple:

K6K6JA3Q4389

Production

Le nombre de séquences de Blackjack distinctes qui peuvent être trouvées dans la chaîne d'entrée.

Exemple:

K6K6JA3Q4389 comprend deux séquences distinctes de Blackjack:

exemple

  • JA, l'As étant compté comme 11 points (10 + 11 = 21)
  • A3Q43, l'As étant compté comme 1 point (1 + 3 + 10 + 4 + 3 = 21)

La réponse serait donc 2.

Règles

  • Deux séquences de Blackjack sont considérées comme distinctes si elles contiennent des cartes différentes ou les mêmes cartes dans des ordres différents. Si la même séquence exacte apparaît à différentes positions dans la liste de saisie, elle ne doit être comptée qu'une seule fois.
  • Les séquences de Blackjack peuvent se chevaucher.
  • Chaque type de carte peut apparaître jusqu'à 12 fois dans la séquence. (Nous supposons que les cartes sont choisies dans au moins 3 jeux différents.)
  • Si aucune séquence de Blackjack ne peut être trouvée dans la chaîne d'entrée, vous devez renvoyer 0ou toute autre valeur falsifiée.
  • Il s'agit de code-golf, donc la réponse la plus courte en octets l'emporte. Les failles standard sont interdites.

Cas de test

Les séquences sont fournies à titre informatif, mais vous ne devez en afficher que le nombre.

Input        | Output | Distinct sequences
-------------+--------+--------------------------------------------------------
3282486Q3362 | 0      | (none)
58A24JJ6TK67 | 1      | 8A2
Q745Q745Q745 | 1      | Q74
AAAAAAAAAAAA | 1      | AAAAAAAAAAA
T5AQ26T39QK6 | 2      | AQ, 26T3
JQ4A4427464K | 3      | A442, 44274, 7464
Q74Q74Q74Q74 | 3      | Q74, 74Q, 4Q7
37AQKA3A4758 | 7      | 37A, 37AQ, AQ, AQK, QKA, KA, A3A475
TAQA2JA7AJQA | 10     | TA, TAQ, AQ, QA, A2JA7, 2JA7A, JA, AJ, AJQ, JQA
TAJAQAKAT777 | 13     | TA, TAJ, AJ, JA, JAQ, AQ, QA, QAK, AK, KA, KAT, AT, 777
Arnauld
la source
1
Hmm, les séquences ne devraient-elles pas être limitées à celles de longueur 5 ou moins?
Jonathan Allan
@JonathanAllan C'est un bon point. Je pense que ce serait effectivement la limite dans un casino. Mais ce n'est pas un vrai jeu de Blackjack. Au lieu de cela, j'ai choisi de limiter l'entrée à 12 cartes afin que de nombreux As ne nécessitent pas trop de temps de calcul. Cela vous semble-t-il correct?
Arnauld
Prochain défi: trouvez la chaîne de 12 caractères avec les séquences de Blackjack les plus uniques: D
ETHproductions
Limiter l'entrée à 10 cartes aurait été tellement plus facile ...
Neil
@Neil Eh bien, cela aurait rendu impossible le cas des «onze as», mais y a-t-il vraiment une optimisation significative derrière cela? Je suppose que vous avez peut-être autre chose en tête.
Arnauld

Réponses:

6

Gelée , 30 29 octets

1e×5,⁵Ḥ‘
O_48«26%⁴µSeÇ
ẆÇÐfQL

Essayez-le en ligne! ou consultez la suite de tests

Comment?

Notez que, si nous évaluons toujours un as comme 1, les seules sommes valides sont 21 et 11 , cette dernière étant acceptable si un as apparaît dans la séquence.

ẆÇÐfQL - Main link: string
Ẇ      - all non-empty contiguous sublists
  Ðf   - filter keep if...
 Ç     -     last link (2) as a monad ...is truthy
    Q  - unique results
     L - length

O_48«26%⁴µSeÇ - Link 2, isBlackjackSubtring: char array  e.g. ['A','2','8','Q']
O             - cast to ordinal values                        [ 65, 50, 56, 81]
 _48          - subtract 48                                   [ 17,  2,  8, 33]
     26       - 26
    «         - minimum (vectorises)                          [ 17,  2,  8, 26]
        ⁴     - 16
       %      - modulo                                        [  1,  2,  8, 10]
         µ    - monadic chain separation (call the result v)
          S   - sum(v)                                        21
            Ç - last link (1) as a monad link_1(v)            [11,21]
           e  - exists in?                                    1

1e×5,⁵Ḥ‘ - Link 1 validSums: value list (where A is 1, and {T,J,Q,K} are 10)
1e       - 1 exists in? (are there any aces? Yields 1 or 0)
  ×5     - multiply by 5 (5 or 0)
     ⁵   - 10
    ,    - pair ([5,10] or [0,10])
      Ḥ  - double ([10,20] or [0,20])
       ‘ - increment ([11,21] or [1,21])
         -                        ^
         -     note: if no ace is in the sequence it's sum can't be 1 anyway
Jonathan Allan
la source
7

Python 2, 215 octets

def b(s,a=[],r=range):
 S=map(lambda x:":">x>"1"and int(x)or 10-(x=="A")*9,s)
 for i in r(12):
  for j in r(13):
   if 21in[x*10+sum(S[i:j])for x in r(S[i:j].count(1)+1)]and s[i:j]not in a:a+=s[i:j],
 return len(a)

Commentaires ajoutés:

def b(s,a=[],r=range):                                      # Define the function b and a list, a, which holds all the blackjack sequences
 S=map(lambda x:":">x>"1"and int(x)or 10-(x=="A")*9,s)      # Set S to the score of each card in b
 for i in r(12):                                            # Loop with i from 0 to 11
  for j in r(13):                                           # Loop with j from 0 to 12
   if 21in[x*10+sum(S[i:j])for x in r(S[i:j].count(1)+1)]\  # If 21 is included in all the possible sums that the scores between i and j in S can be
           and s[i:j]not in a:                              # And that sequence is not already included,
               a+=s[i:j],                                   # Append that sequence to a
 return len(a)                                              # Return the amount of elements in a
Loovjo
la source
3

Python , 134 130 octets

lambda x:len({x[i:j]for i in range(12)for j in range(13)if sum(min(26,ord(c)-48)%16for c in x[i:j])in([11,21][~('A'in x[i:j]):])})

Essayez-le en ligne!

Comment?

Une fonction sans nom, prenant la chaîne de longueur 12 comme x.

x[i:j]est une tranche de la chaîne du i + 1 ème au j ème caractère.

Les tranches sont prises de telle sorte que nous ayons toutes des sous-listes en traversant de i=0à i=11avec for i in range(12), pour chacune desquelles nous traversons de j=0à j=12avec for j in range(13).

(Nous n'avons besoin j=i+1que de plus, mais les tranches avec ne j<=isont que des chaînes vides, nous pouvons donc jouer au golf à 4 octets for j in range(i+1,13))

Ceux-ci sont filtrés pour ceux qui ont la bonne somme ...

Les sommes valides sont 11 et 21 s'il y a un as dans une tranche, ou juste 21 sinon. 'A'in x[i:j]nous donne ces informations et ~(v)effectue -1-v, que nous utilisons pour couper [11,21]- donc si un as est dans la séquence que nous obtenons [11,21][-2:]et sinon nous obtenons [11,21][-1:], résultant en [11,21]et [21]respectivement.

La somme lui - même doit traiter Acomme 1, des chiffres que leurs valeurs, et T, J, Qet Kque 10. Cette cartographie est réalisée par coulée à la première ordinaux:
" 2 3 4 5 6 7 8 9 T J Q K A"(sans les espaces) devient
[50, 51, 52, 53, 54, 55, 56, 57, 84, 74, 81, 75, 65], en soustrayant 48 pour obtenir
[ 2, 3, 4, 5, 6, 7, 8, 9, 36, 26, 33, 27, 17], en prenant la minavec 26 rendements
[ 2, 3, 4, 5, 6, 7, 8, 9, 26, 26, 26, 26, 17], et mod ( %) seize sont ceux
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 1], au besoin pour la somme, sum(...).

Les résultats filtrés sont placés dans un ensemble avec {...}, de sorte que seuls les résultats uniques restent et la longueur, len(...)est le nombre

Jonathan Allan
la source
3

05AB1E , 39 38 37 octets

'A1:vTy‚ydè})ŒvyO¸y1åiDT+ì}21å})¹ŒÏÙg

Essayez-le en ligne!

Explication

'A1:                  # replace A with 1 in input

v      }              # for each card
 Ty‚                  # pair 10 and the card
    yd                # check if the card is a digit
      è               # use this to index into the pair, giving 10 for JQK
        )             # wrap in list
                      # we now have a list of cards as numbers in range [1 ... 10]

Œv               }    # for each sublist
  yO¸                 # create a list with the sum of the sublist
     y1åi    }        # if the sublist contain 1
         DT+ì         # add sum+10 to the list
              21å     # check if 21 is in that list
                  )   # wrap in list
                      # we now have a list with 1 where the sublist sums to 21 and
                      # 0 otherwise

¹Œ                    # get sublists of the input
  Ï                   # keep only those which sum to 21
   Ù                  # remove duplicates
    g                 # count the number of lists
Emigna
la source
3

JavaScript (ES6), 123 octets

f=
t=>eval("for(s=new Set,i=0;t[i];i++)for(a=0,b=21,j=i;c=t[j++];b&&b-a*10||s.add(t.slice(i,j)))b-=+c||(c>'A'?10:a=1);s.size")
<input oninput=o.textContent=/[^2-9TJQKA]/.test(this.value)?'':f(this.value)><pre id=o>

Neil
la source
Excellente idée, mais cela revient 0pour AAAAAAAAAAAAplutôt que 1. ( Apeut être simultanément 1 et 11)
ETHproductions
En combinant nos deux entrées, vous pouvez obtenir s=>eval("q=new Set;for(i=0;s[i];i++)for(t=A=0,j=i;c=s[j++];t==21|t==11&A&&q.add(s.slice(i,j)))t+=+c||(c<'B'?A=1:10);q.size")pour 124 octets
ETHproductions
@ETHproductions À partir de 21 semble encore me faire gagner un octet.
Neil
@ETHproductions ... ça aide si je poste le bon nombre d'octets ...
Neil
3

JavaScript (ES6), 144 138 129 128 126 124 octets

g=([c,...s],a=[],q=new Set)=>c?g(s,[...a,[,21]].map(([x,y,A])=>[x+=c,y-=+c||(c<'B'?A=1:10),A,y&&y^10*A||q.add(x)]),q):q.size

Ancienne tentative à 128:

s=>(q=new Set,f=s=>s?f(s.slice(1))&f(s.slice(0,-1))&[...s].map(c=>t+=-c||~(c<'B'?A=0:9),t=A=21)|t&&t-10*!A?q:q.add(s):q)(s).size
ETHproductions
la source
s.search`A`>-1pourrait être~s.search`A`
Luke
@Luke Non, en fait, car cela renvoie des valeurs telles que -2, et1&-2 == 0
ETHproductions
Vrai. Peut-être réglé tsur 0dans l' .slice(0,-1)appel (enregistre 2B)?
Luke
@Luke Je ne pense pas que cela fonctionnerait, tout comme tune variable globale et elle serait réinitialisée à cause de l'appel à f(s.slice(0,-1)). Mais j'ai trouvé un moyen de contourner s.search`A`>-1:-)
ETHproductions
Je suis curieux de voir ce que vous avez quand vous avez fini de jouer au golf. J'ai l'impression d'être bloqué à 113 pour l'instant.
Arnauld
3

JavaScript (ES6), 112 octets

f=(s,x=[k=0])=>s?f(s.slice(1),x,[...s].map(c=>x[t+=+c||10^(c<'B'?a=11:0),b+=c]||t-21&&t-a?0:x[b]=++k,a=b=t=0)):k

Cette logique de code est assez similaire à celle utilisée dans les réponses JS existantes d' ETHproductions et Neil . Mais il utilise un tableau de base pour garder une trace des séquences de Blackjack rencontrées plutôt qu'un Set.

Formaté et commenté

f = (                     // given:
  s,                      //  - s = list of cards
  x = [k = 0]             //  - x = array of Blackjack sequences
) =>                      //  - k = number of distinct Blackjack sequences 
  s ?                     // if s is not empty:
    f(                    //   do a recursive call:
      s.slice(1),         //     starting at the next card in the list
      x,                  //     without re-initializing x[]
      [...s].map(         //   for each card 'c' in the list:
        c => x[           //
          t+ =            //   update the total number of points:
            +c ||         //     using the number of the card (for 2 ... 9)
            10 ^ (        //     or using 10 for all other cards
              c < 'B' ?   //     except the Ace which is
                a = 11    //     counted as 1 point and sets 'a' to 11
              :           //     (which means that a total number of points
                0         //     of 11 will be considered valid from now on)
            ),            //
          b += c          //   update the current sequence 'b'
        ] ||              //   if x[b] was previously stored as a Blackjack sequence
        t - 21 &&         //   or the total number of points is not equal to 21
        t - a ?           //   and not equal to 'a':
          0               //     do nothing
        :                 //   else:
          x[b] = ++k,     //     store the current sequence in x[] and increment k
        a = b = t = 0     //   initialization of all variables used in map()
      )                   //
    )                     //
  :                       // else:
    k                     //   return k

Cas de test

Arnauld
la source
J'ai essayé la double récursivité, en reculant dans la chaîne, en calculant cumulativement chaque chaîne possible à mesure que chaque caractère est consommé ... et pourtant l'approche la plus courte consiste simplement à parcourir chaque tranche. Joli! (L'utilisation d'un ensemble semble être de trois octets de plus, si j'ai calculé correctement)
ETHproductions
2

05AB1E , 40 39 38 37 36 octets

-4 Merci à Emigna

Ç<çJŒÙ'@0:[Ž„èµJuS9:S>D1å2‚T*>sOå½]¾

Essayez-le en ligne!

Ç<ç                                  # decrement characters by 1
   JŒÙ                               # get all unique substrings
      '@0:                           # replace @ (was A) with 0
          [Ž                      ]  # for everything on the stack
            „èµJuS9:                 # replace what was T,J,Q,K with 9
                    S>D              # increment all values
                       1å2‚T*>       # push [11,21] if there was an A, [1,21] otherwise
                              sO     # sum the values of the cards
                                å½   # increment the counter_variable if the sum 
                                     # is in the array
                                   ¾ # end loop and push (print) the counter_variable

Nous devons faire la chose décrémentation -> sous-chaîne -> incrémentation afin que les cartes de visage soient représentées par un nombre à un seul chiffre.

Riley
la source
Belle façon de se déplacer à deux chiffres! Vous pouvez supprimer le premier Scar Çtransforme la chaîne en une liste de codes de caractères.
Emigna
En outre, "SIPJ"pourrait être„èµJu
Emigna
@Emigna Merci. Je pensais qu'il y avait un moyen de le faire, mais je n'ai pas trouvé comment l'utiliser dans la documentation.
Riley
Vous pouvez enregistrer 2 octets de plus en le réécrivant comme Ç<çJŒÙ'@0:)vy„èµJuS9:S>D1å2‚T*>sOå}Oalors vous êtes 1 octet de moins que ma réponse :)
Emigna
@Emigna C'est le même nombre d'octets et ressemble plus à mon original.
Riley
1

Utilitaires Bash + Unix, 145 142 141 141 octets

for n in {9..155}
{ echo ${1:n%12:n/12};}|sort -u|sed 's/\(.\)/+\1/g;s/A/{1,11}/g;s/[J-T]/10/g;s/^/eval echo $[0/;s/$/]/'|sh|grep -c '\<21\>'

Essayez-le en ligne!

Essais:

for x in 3282486Q3362 58A24JJ6TK67 Q745Q745Q745 AAAAAAAAAAAA T5AQ26T39QK6 JQ4A4427464K Q74Q74Q74Q74 37AQKA3A4758 TAQA2JA7AJQA TAJAQAKAT777
  do
    echo -n "$x "
    ./21 "$x"
  done

3282486Q3362 0
58A24JJ6TK67 1
Q745Q745Q745 1
AAAAAAAAAAAA 1
T5AQ26T39QK6 2
JQ4A4427464K 3
Q74Q74Q74Q74 3
37AQKA3A4758 7
TAQA2JA7AJQA 10
TAJAQAKAT777 13
Mitchell Spector
la source
1

PHP, 240 octets

$a=str_split($argv[1]);foreach($a as$k=>$v)$n[$k]=$v=='A'?1:($v==0?10:$v);for($i=0;$i<=$k;$i++){$s=$a[$i];$r=$n[$i];for($j=$i+1;$j<=$k;$j++){$s.=$a[$j];$r+=$n[$j];if ($r==21||($r==11&&stristr($s,'A')))$f[]=$s;}}echo count(array_unique($f));

Non golfé:

$a = str_split($argv[1]);
foreach ($a as $k=>$v)
    $n[$k] = $v == 'A' ? 1 : ($v == 0 ? 10 : $v);
for ($i=0; $i<=$k; $i++) {
    $s = $a[$i];
    $r = $n[$i];
    for ($j=$i+1; $j<=$k; $j++) {
        $s .= $a[$j];
        $r += $n[$j];
        if ($r == 21 || ($r == 11 && stristr($s,'A')) )
            $f[] = $s;
    }
}
echo count(array_unique($f));

Essayez-le ici!

roberto06
la source
1
Bizarre, j'aurais pu jurer que cela avait fonctionné sur mes tests locaux, mais il semble que vous ayez raison. En tous cas; le problème vient du fait que cela $in'a pas été déclaré. Ajout de 4 octets et cela fonctionne parfaitement.
roberto06