¿Cuántas secuencias de Blackjack en esa lista?

21

Su tarea es encontrar cuántas secuencias distintas de Blackjack se pueden encontrar en una lista ordenada de 12 cartas.

Una secuencia de Blackjack se define como una secuencia de cartas consecutivas cuya suma de puntos es exactamente 21. Los puntos se cuentan de acuerdo con la siguiente tabla:

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

Entrada

Una cadena de 12 caracteres, utilizando los símbolos descritos anteriormente. No nos importan los colores de las tarjetas, por lo que no se proporcionan.

Ejemplo:

K6K6JA3Q4389

Salida

El número de secuencias distintas de Blackjack que se pueden encontrar en la cadena de entrada.

Ejemplo:

K6K6JA3Q4389 incluye dos secuencias distintas de Blackjack:

ejemplo

  • JA, con el As contado como 11 puntos (10 + 11 = 21)
  • A3Q43, con el As contado como 1 punto (1 + 3 + 10 + 4 + 3 = 21)

Entonces la respuesta sería 2.

Reglas

  • Dos secuencias de Blackjack se consideran distintas si contienen cartas diferentes o las mismas cartas en diferentes órdenes. Si la misma secuencia exacta aparece en diferentes posiciones en la lista de entrada, debe contarse solo una vez.
  • Las secuencias de Blackjack pueden superponerse entre sí.
  • Cada tipo de tarjeta puede aparecer hasta 12 veces en la secuencia. (Suponemos que las cartas se seleccionan de al menos 3 mazos diferentes).
  • Si no se puede encontrar una secuencia de Blackjack en la cadena de entrada, debe devolver 0o cualquier otro valor falso.
  • Este es el código de golf, por lo que gana la respuesta más corta en bytes. Las lagunas estándar están prohibidas.

Casos de prueba

Las secuencias se proporcionan con fines informativos, pero solo se requiere que envíe el número de ellas.

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
fuente
1
Hmm, ¿no deberían limitarse las secuencias a las de longitud 5 o menos?
Jonathan Allan
@ JonathanAllan Ese es un buen punto. Creo que ese sería el límite en un casino. Pero este no es un juego de Blackjack real. En cambio, elegí limitar la entrada a 12 cartas para que muchos Ases no requieran demasiado tiempo de cálculo. ¿Suena eso bien?
Arnauld
Próximo desafío: encontrar la secuencia de 12 caracteres con las secuencias de blackjack más exclusivas: D
ETHproductions
Limitar la entrada a 10 tarjetas hubiera sido mucho más fácil ...
Neil
@Neil Bueno, eso habría hecho imposible el caso de los 'once Ases', pero ¿hay realmente una optimización significativa detrás de eso? Supongo que puede tener algo más en mente.
Arnauld

Respuestas:

6

Jalea , 30 29 bytes

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

¡Pruébelo en línea! o echa un vistazo a la suite de prueba

¿Cómo?

Tenga en cuenta que, si siempre valoramos un as como 1, entonces las únicas sumas válidas son 21 y 11 , siendo este último aceptable si aparece un as en la secuencia.

ẆÇÐ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
fuente
7

Python 2, 215 bytes

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)

Comentarios agregados:

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

Python , 134 130 bytes

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

Pruébalo en línea!

¿Cómo?

Una función sin nombre, que toma la cadena de longitud 12 como x.

x[i:j]es un pedazo de la cadena de la i + 1 ª a la j- ésimo carácter.

Los cortes se toman de tal manera que tenemos todas las sublistas al pasar de i=0a i=11con for i in range(12), para cada una de las cuales atravesamos de j=0a j=12con for j in range(13).

(Solo necesitamos j=i+1y hacia arriba, pero las rebanadas con j<=ison solo cadenas vacías, por lo que podemos jugar desde 4 bytes for j in range(i+1,13))

Estos se filtran para aquellos con la suma correcta ...

Las sumas válidas son 11 y 21 si hay un as en una rebanada, o solo 21 si no. 'A'in x[i:j]nos da esta información y ~(v)lleva a cabo -1-v, que utilizamos para la rebanada [11,21]- tanto si es un as en la secuencia que obtenemos [11,21][-2:]y si no tenemos [11,21][-1:], lo que resulta en [11,21]y [21]respectivamente.

La suma en sí necesita tratar Acomo 1, dígitos como sus valores, y T, J, Q, y Kcomo 10. Este mapeo se logra por primera fundición a ordinales:
" 2 3 4 5 6 7 8 9 T J Q K A"(sin los espacios) se convierte
[50, 51, 52, 53, 54, 55, 56, 57, 84, 74, 81, 75, 65], restar 48 para obtener
[ 2, 3, 4, 5, 6, 7, 8, 9, 36, 26, 33, 27, 17], tomando el mincon 26 rendimientos
[ 2, 3, 4, 5, 6, 7, 8, 9, 26, 26, 26, 26, 17], y mOD ( %) dieciséis son los que
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 1], como se requiere para la suma, sum(...).

Los resultados filtrados se colocan en un conjunto con {...}, por lo que solo quedan los resultados únicos y la longitud, len(...)es el recuento

Jonathan Allan
fuente
3

05AB1E , 39 38 37 bytes

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

Pruébalo en línea!

Explicación

'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
fuente
3

JavaScript (ES6), 123 bytes

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
fuente
Gran idea, pero esto vuelve 0por AAAAAAAAAAAAmás que 1. ( Apuede ser simultáneamente 1 y 11)
ETHproductions
Al combinar nuestras dos entradas, puede obtener 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")124 bytes
ETHproductions
@ETHproductions A partir de 21 todavía parece ahorrarme un byte.
Neil
@ETHproductions ... ayuda si publico el recuento de bytes correcto ...
Neil
3

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

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

Viejo intento en 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
ETHproducciones
fuente
s.search`A`>-1podría ser~s.search`A`
Lucas
@Luke No, en realidad, porque eso devuelve valores como -2, y1&-2 == 0
ETHproductions
Cierto. Tal vez fijado ta 0la .slice(0,-1)llamada (ahorra 2B)?
Lucas
@Luke No creo que funcione, ya que tes una variable global y se restablecería debido a la llamada a f(s.slice(0,-1)). Pero encontré una forma de s.search`A`>-1
evitarlo
Tengo curiosidad por ver lo que tienes cuando termines de jugar golf. Parece que estoy atrapado en 113 por ahora.
Arnauld
3

JavaScript (ES6), 112 bytes

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

Esta lógica de código es bastante similar a la utilizada en las respuestas JS existentes de ETHproductions y Neil . Pero está utilizando una matriz básica para realizar un seguimiento de las secuencias de Blackjack encontradas en lugar de a Set.

Formateado y comentado

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

Casos de prueba

Arnauld
fuente
Intenté la doble recursión, retrocediendo a través de la cadena, calculando acumulativamente cada cadena posible a medida que se consume cada carácter ... y, sin embargo, el enfoque más corto es simplemente ejecutar cada rebanada. ¡Buena esa! (El uso de un conjunto parece ser tres bytes más largo, si
calculé
2

05AB1E , 40 39 38 37 36 bytes

-4 Gracias a Emigna

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

Pruébalo en línea!

Ç<ç                                  # 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

Necesitamos hacer el decremento -> subcadena -> cosa de incremento para que las tarjetas faciales estén representadas por un número de un solo dígito.

Riley
fuente
¡Buena manera de moverse por los dos dígitos! Puede eliminar el primero Smientras Çconvierte la cadena en una lista de códigos de caracteres.
Emigna
Además, "SIPJ"podría ser„èµJu
Emigna
@ Emmigna Gracias. Pensé que había una manera de hacerlo, pero no pude encontrar cómo usarlo en la documentación.
Riley
Puedes guardar 2 bytes más reescribiéndolo como Ç<çJŒÙ'@0:)vy„èµJuS9:S>D1å2‚T*>sOå}OEntonces eres 1 byte más corto que mi respuesta :)
Emigna
@Emigna Este es el mismo número de bytes y se parece más a mi original.
Riley
1

Utilidades Bash + Unix, 145 142 141 bytes

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

Pruébalo en línea!

Pruebas de funcionamiento:

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

PHP, 240 bytes

$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));

Sin 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));

Pruébalo aquí!

roberto06
fuente
1
Extraño, podría haber jurado que funcionó en mis pruebas locales, pero parece que tienes razón. De todas formas; El problema vino del hecho de que $ino fue declarado. Se agregaron 4 bytes y funciona perfectamente.
roberto06