Ile sekwencji blackjacka na tej liście?

21

Twoim zadaniem jest ustalenie, ile różnych sekwencji blackjacka można znaleźć na uporządkowanej liście 12 kart.

Sekwencję blackjacka definiuje się jako sekwencję następujących po sobie kart, których suma punktów wynosi dokładnie 21. Punkty są liczone zgodnie z poniższą tabelą:

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

Wkład

Ciąg 12 znaków, używając symboli opisanych powyżej. Nie dbamy o kolory kart, więc nie są one dostarczane.

Przykład:

K6K6JA3Q4389

Wydajność

Liczba różnych sekwencji blackjacka, które można znaleźć w ciągu wejściowym.

Przykład:

K6K6JA3Q4389 zawiera dwie różne sekwencje blackjacka:

przykład

  • JA, przy czym as liczony jest jako 11 punktów (10 + 11 = 21)
  • A3Q43, z asem liczonym jako 1 punkt (1 + 3 + 10 + 4 + 3 = 21)

Tak więc odpowiedź brzmiałaby 2.

Zasady

  • Dwie sekwencje blackjacka są uważane za odrębne, jeśli zawierają różne karty lub te same karty w różnych porządkach. Jeśli dokładnie ta sama sekwencja pojawia się w różnych pozycjach na liście danych wejściowych, należy ją policzyć tylko raz.
  • Sekwencje blackjacka mogą się nakładać.
  • Każdy rodzaj karty może pojawić się 12 razy w sekwencji. (Zakładamy, że karty są wybierane z co najmniej 3 różnych talii.)
  • Jeśli w ciągu wejściowym nie można znaleźć sekwencji Blackjacka, musisz zwrócić 0lub dowolną inną wartość fałszowania.
  • To jest golf golfowy, więc wygrywa najkrótsza odpowiedź w bajtach. Standardowe luki są zabronione.

Przypadki testowe

Sekwencje są dostarczane w celach informacyjnych, ale musisz podać tylko ich liczbę.

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
źródło
1
Hmm, czy sekwencje nie powinny być ograniczone do sekwencji o długości 5 lub mniejszej?
Jonathan Allan
@JonathanAllan To dobra uwaga. Myślę, że to rzeczywiście byłby limit w kasynie. Ale to nie jest prawdziwa gra w blackjacka. Zamiast tego zdecydowałem się ograniczyć dane wejściowe do 12 kart, aby wiele Asów nie wymagało zbyt dużo czasu obliczeń. Czy to brzmi OK?
Arnauld
Następne wyzwanie: znajdź 12-znakowy ciąg z najbardziej unikalnymi sekwencjami blackjacka: D
ETHproductions
Ograniczenie wejścia do 10 kart byłoby o wiele łatwiejsze ...
Neil
@Neil Cóż, to uniemożliwiłoby przypadek „jedenaście asów”, ale czy naprawdę kryje się za tym znacząca optymalizacja? Podejrzewam, że możesz mieć na myśli coś innego.
Arnauld

Odpowiedzi:

6

Galaretka , 30 29 bajtów

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

Wypróbuj online! lub sprawdź pakiet testowy

W jaki sposób?

Zauważ, że jeśli zawsze oceniamy asa na 1, wówczas jedynymi poprawnymi sumami są 21 i 11 , przy czym te ostatnie są dopuszczalne, jeśli as pojawia się w sekwencji.

ẆÇÐ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
źródło
7

Python 2, 215 bajtów

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)

Dodane komentarze:

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

Python , 134 130 bajtów

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

Wypróbuj online!

W jaki sposób?

Funkcja bez nazwy, przyjmująca ciąg długości 12 jako x.

x[i:j]to plasterek ciągu od i + 1- szego do j- tego znaku.

Plasterki są pobierane w taki sposób, że wszyscy mamy listy podrzędne, przemierzając od i=0do i=11z for i in range(12), z których każdy przemierzamy od j=0do j=12z for j in range(13).

(Potrzebujemy tylko j=i+1i wyżej, ale plastry z j<=isą tylko pustymi ciągami, więc możemy grać w golfa z 4 bajtów od for j in range(i+1,13))

Są filtrowane według tych z prawidłową sumą ...

Prawidłowe sumy to 11 i 21, jeśli na asie jest as, lub tylko 21, jeśli nie. 'A'in x[i:j]daje nam tę informację i ~(v)preform -1-v, których używamy do plasterka [11,21]- więc jeśli asem w sekwencji otrzymujemy [11,21][-2:]a jeśli nie mamy [11,21][-1:], co skutkuje [11,21]i [21]odpowiednio.

Suma sam musi traktować Ajako 1, cyfr, ich wartości i T, J, Qi Kjako 10. Odwzorowanie to osiągnąć przez pierwszy odlewania porządkowych:
" 2 3 4 5 6 7 8 9 T J Q K A"(bez przestrzeni) staje się
[50, 51, 52, 53, 54, 55, 56, 57, 84, 74, 81, 75, 65], odejmując 48, aby
[ 2, 3, 4, 5, 6, 7, 8, 9, 36, 26, 33, 27, 17], przyjmując minz 26 wydajnością
[ 2, 3, 4, 5, 6, 7, 8, 9, 26, 26, 26, 26, 17], i mod ( %) na szesnaście te są
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 1], zgodnie z wymaganiami dla sumy, sum(...).

Przefiltrowane wyniki są umieszczane w zestawie z {...}, więc pozostają tylko unikalne wyniki, a długość len(...)jest liczbą

Jonathan Allan
źródło
3

05AB1E , 39 38 37 bajtów

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

Wypróbuj online!

Wyjaśnienie

'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
źródło
3

JavaScript (ES6), 123 bajty

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
źródło
Świetny pomysł, ale to wraca 0do AAAAAAAAAAAAzamiast 1. ( Amoże być jednocześnie 1 i 11)
ETHprodukcje
Łącząc nasze dwa wpisy, możesz uzyskać 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 bajty
ETHproductions
@ETHproductions Począwszy od 21 nadal wydaje mi się, że oszczędzam bajt.
Neil
@ETHproductions ... to pomaga, jeśli opublikuję poprawną liczbę bajtów ...
Neil
3

JavaScript (ES6), 144 138 129 128 126 124 bajtów

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

Stara próba 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
ETHprodukcje
źródło
s.search`A`>-1może być~s.search`A`
Łukasz
@Luke Nie, w rzeczywistości, ponieważ zwraca wartości takie jak -2i1&-2 == 0
ETHproductions
Prawdziwe. Może ustawić taby 0w .slice(0,-1)zaproszeniu (oszczędność 2B)?
Łukasz
@Luke Nie sądzę, aby to działało, podobnie jak tzmienna globalna i zostałaby zresetowana z powodu wywołania f(s.slice(0,-1)). Ale znalazłem sposób na obejście s.search`A`>-1:-)
ETHprodukcje
Jestem ciekawy, co masz, kiedy skończysz grać w golfa. Wydaje mi się, że na razie utknąłem na poziomie 113.
Arnauld
3

JavaScript (ES6), 112 bajtów

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

Ta logika kodu jest dość podobna do tej używanej w istniejących odpowiedziach JS z ETHproductions i Neila . Ale używa podstawowej tablicy do śledzenia napotkanych sekwencji Blackjacka, a nie a Set.

Sformatowane i skomentowane

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

Przypadki testowe

Arnauld
źródło
Próbowałem podwójnej rekurencji, przechodząc wstecz przez łańcuch, obliczając łącznie każdy możliwy łańcuch, gdy każdy znak jest konsumowany ... a jednak najkrótszym podejściem jest po prostu przejście przez każdy plasterek. Niezłe! (Korzystanie z zestawu wydaje się być o trzy bajty dłuższe, jeśli poprawnie wyliczyłem)
ETHprodukcje
2

05AB1E , 40 39 38 37 36 bajtów

-4 Dzięki Emignie

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

Wypróbuj online!

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

Musimy wykonać dekrementację -> podciąg -> inkrementację, aby karty twarzy były reprezentowane przez jedną cyfrę.

Riley
źródło
Miły sposób na obejście podwójnych cyfr! Możesz usunąć pierwszy, Sponieważ Çzmienia ciąg w listę kodów znaków.
Emigna
Ponadto "SIPJ"może być„èµJu
Emigna
@Emigna Thanks. Myślałem, że jest na to sposób, ale nie mogłem znaleźć w dokumentacji tego sposobu.
Riley
Możesz zapisać jeszcze 2 bajty przepisując go, ponieważ Ç<çJŒÙ'@0:)vy„èµJuS9:S>D1å2‚T*>sOå}Ojesteś o 1 bajt krótszy od mojej odpowiedzi :)
Emigna
@Emigna Jest to ta sama liczba bajtów i bardziej przypomina mój oryginał.
Riley,
1

Narzędzia Bash + Unix, 145 142 141 bajtów

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

Wypróbuj online!

Przebiegi testowe:

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

PHP, 240 bajtów

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

Nie golfowany:

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

Wypróbuj tutaj!

roberto06
źródło
1
Dziwne, mogłem przysiąc, że działało to na moich lokalnych testach, ale wygląda na to, że masz rację. Tak czy inaczej; problem wynikał z faktu, że $inie został zadeklarowany. Dodano 4 bajty i działa idealnie.
roberto06