Wie viele Blackjack-Sequenzen enthält diese Liste?

21

Ihre Aufgabe ist es, herauszufinden, wie viele verschiedene Blackjack-Sequenzen in einer geordneten Liste von 12 Karten enthalten sind.

Eine Blackjack-Sequenz ist definiert als eine Sequenz aufeinanderfolgender Karten, deren Punktesumme genau 21 beträgt. Die Punkte werden gemäß der folgenden Tabelle gezählt:

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

Eingang

Eine 12-stellige Zeichenfolge mit den oben beschriebenen Symbolen. Die Farben der Karten sind uns egal, daher werden sie nicht mitgeliefert.

Beispiel:

K6K6JA3Q4389

Ausgabe

Die Anzahl der verschiedenen Blackjack-Sequenzen, die in der Eingabezeichenfolge enthalten sind.

Beispiel:

K6K6JA3Q4389 beinhaltet zwei verschiedene Blackjack-Sequenzen:

Beispiel

  • JA, wobei das Ass als 11 Punkte gezählt wird (10 + 11 = 21)
  • A3Q43, wobei das Ass als 1 Punkt gezählt wird (1 + 3 + 10 + 4 + 3 = 21)

Die Antwort wäre also 2.

Regeln

  • Zwei Blackjack-Sequenzen werden als unterschiedlich betrachtet, wenn sie unterschiedliche Karten oder die gleichen Karten in unterschiedlicher Reihenfolge enthalten. Erscheint die exakt gleiche Sequenz an unterschiedlichen Stellen in der Eingabeliste, muss sie nur einmal gezählt werden.
  • Die Blackjack-Sequenzen können sich überlappen.
  • Jede Art von Karte kann bis zu 12 Mal in der Sequenz vorkommen. (Wir gehen davon aus, dass die Karten aus mindestens 3 verschiedenen Decks stammen.)
  • Wenn die Eingabezeichenfolge keine Blackjack-Sequenz enthält, müssen Sie 0einen Wert oder einen anderen falschen Wert zurückgeben.
  • Das ist Code-Golf, also gewinnt die kürzeste Antwort in Bytes. Standardlücken sind verboten.

Testfälle

Die Sequenzen werden zu Informationszwecken bereitgestellt, aber Sie müssen nur die Anzahl der Sequenzen ausgeben.

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
quelle
1
Hmm, sollten die Sequenzen nicht auf Sequenzen mit einer Länge von 5 oder weniger beschränkt sein?
Jonathan Allan
@ JonathanAllan Das ist ein guter Punkt. Ich denke das wäre in der Tat das Limit in einem Casino. Dies ist jedoch kein richtiges Blackjack-Spiel. Stattdessen habe ich beschlossen, die Eingabe auf 12 Karten zu beschränken, damit viele Asse nicht zu viel Rechenzeit benötigen. Klingt das ok
Arnauld
Nächste Herausforderung: Finden Sie die 12-
Zeichen
Es wäre viel einfacher gewesen, die Eingabe auf 10 Karten zu beschränken ...
Neil
@Neil Nun, das hätte den "Elf-Asse" -Fall unmöglich gemacht, aber steckt wirklich eine signifikante Optimierung dahinter? Ich nehme an, Sie haben vielleicht noch etwas anderes im Sinn.
Arnauld

Antworten:

6

Gelee , 30 29 Bytes

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

Probieren Sie es online! oder schauen Sie sich die Testsuite an

Wie?

Beachten Sie, dass, wenn wir ein Ass immer als 1 bewerten, die einzigen gültigen Summen 21 und 11 sind , wobei letztere akzeptabel sind, wenn ein Ass in der Sequenz erscheint.

ẆÇÐ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
quelle
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)

Kommentare hinzugefügt:

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

Probieren Sie es online!

Wie?

Eine unbenannte Funktion, die die Zeichenfolge der Länge 12 als annimmt x.

x[i:j]ist ein Teil der Zeichenfolge vom i + 1- ten bis zum j- ten Zeichen.

Slices werden so genommen, dass wir alle Unterlisten durchlaufen, indem wir von i=0nach i=11mit gehen for i in range(12), für jede von denen wir von j=0nach j=12mit gehen for j in range(13).

(Wir brauchen nur j=i+1und bis, aber Slices mit j<=isind nur leere Zeichenfolgen, so dass wir 4 Bytes ab Golf spielen können. for j in range(i+1,13))

Diese werden nach denen mit der richtigen Summe gefiltert ...

Gültige Summen sind 11 und 21, wenn ein Slice ein Ass enthält, oder nur 21, wenn nicht. 'A'in x[i:j]gibt uns diese Informationen und ~(v)führt -1-v, die wir Scheibe verwenden [11,21]- also wenn ein Ass in der Folge ist , dass wir bekommen , [11,21][-2:]und wenn wir nicht bekommen [11,21][-1:]in, was [11,21]und [21]jeweils.

Die Summe selbst zu behandeln , muss Aals 1, Zahlen als Werte, und T, J, Q, und Kals 10. Diese Zuordnung von ersten Gußstück ordinals erreicht:
" 2 3 4 5 6 7 8 9 T J Q K A"(ohne Leerzeichen) wird
[50, 51, 52, 53, 54, 55, 56, 57, 84, 74, 81, 75, 65], 48 subtrahieren zu erhalten
[ 2, 3, 4, 5, 6, 7, 8, 9, 36, 26, 33, 27, 17], die Einnahme minmit 26 Ausbeute
[ 2, 3, 4, 5, 6, 7, 8, 9, 26, 26, 26, 26, 17], und mod ( %) sechzehn diejenigen sind
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 1], als für die Summe erforderlich sum(...).

Die gefilterten Ergebnisse werden mit in eine Menge eingefügt {...}, sodass nur die eindeutigen Ergebnisse übrig bleiben und die Länge len(...)die Zählung ist

Jonathan Allan
quelle
3

05AB1E , 39 38 37 Bytes

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

Probieren Sie es online!

Erläuterung

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

JavaScript (ES6), 123 Byte

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
quelle
Tolle Idee, aber diese Erträge 0für AAAAAAAAAAAAstatt 1. ( Akann gleichzeitig 1 und 11 sein)
ETHproductions
Wenn Sie unsere beiden Einträge kombinieren, erhalten Sie 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 Ab 21 scheint mir noch ein Byte zu sparen.
Neil
@ETHproductions ... es hilft, wenn ich die richtige Byteanzahl poste ...
Neil
3

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

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

Alter Versuch bei 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
quelle
s.search`A`>-1könnte sein~s.search`A`
Luke
@Luke Nein, eigentlich, denn das gibt Werte wie -2und1&-2 == 0
ETHproductions
Wahr. Vielleicht tauf 0im .slice(0,-1)Anruf setzen (spart 2B)?
Luke
@Luke Ich glaube nicht, dass das funktionieren würde, da tes sich um eine globale Variable handelt und sie wegen des Aufrufs von zurückgesetzt würde f(s.slice(0,-1)). Aber ich habe einen Ausweg gefunden s.search`A`>-1:-)
ETHproductions
Ich bin gespannt, was du hast, wenn du damit fertig bist. Ich scheine vorerst bei 113 zu stecken.
Arnauld
3

JavaScript (ES6), 112 Byte

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

Diese Codelogik ähnelt derjenigen, die in vorhandenen JS-Antworten von ETHproductions und Neil verwendet wird . Es wird jedoch ein einfaches Array verwendet, um die aufgetretenen Blackjack-Sequenzen zu verfolgen, anstatt eines Set.

Formatiert und kommentiert

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

Testfälle

Arnauld
quelle
Ich habe versucht, eine doppelte Rekursion durchzuführen, indem ich mich rückwärts durch die Zeichenfolge bewegte und jede mögliche Zeichenfolge kumulativ berechnet habe, während jedes Zeichen verbraucht wurde ... und doch besteht der kürzeste Ansatz darin, einfach durch jede Schicht zu laufen. Schön! (Using a Set scheint drei Bytes länger zu sein, wenn ich richtig gerechnet habe)
ETHproductions
2

05AB1E , 40 39 38 37 36 Bytes

-4 Danke an Emigna

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

Probieren Sie es 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

Wir müssen das Dekrementieren -> Teilzeichenfolge -> Inkrementieren ausführen, damit Bildkarten durch eine einstellige Zahl dargestellt werden.

Riley
quelle
Gute Möglichkeit, zweistellige Zahlen zu umgehen! Sie können den ersten entfernen, Swährend Çdie Zeichenfolge in eine Liste von Zeichencodes umgewandelt wird.
Emigna
Auch "SIPJ"könnte„èµJu
Emigna
@Emigna Danke. Ich dachte, es gäbe eine Möglichkeit, das zu tun, aber ich konnte nicht herausfinden, wie ich es in der Dokumentation verwenden soll.
Riley
Sie können 2 weitere Bytes speichern, indem Ç<çJŒÙ'@0:)vy„èµJuS9:S>D1å2‚T*>sOå}OSie es umschreiben als Dann sind Sie 1 Byte kürzer als meine Antwort :)
Emigna
@Emigna Dies ist die gleiche Anzahl von Bytes und ähnelt eher meinem Original.
Riley
1

Bash + Unix-Dienstprogramme, 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\>'

Probieren Sie es online!

Testläufe:

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

Ungolfed:

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

Probieren Sie es hier aus!

roberto06
quelle
1
Komisch, ich hätte schwören können, dass es bei meinen lokalen Tests funktioniert hat, aber es scheint, dass Sie Recht haben. Sowieso; Das Problem kam von der Tatsache, dass $inicht deklariert wurde. 4 Bytes hinzugefügt und es funktioniert einwandfrei.
roberto06