Berapa banyak urutan Blackjack dalam daftar itu?

21

Tugas Anda adalah menemukan berapa banyak urutan Blackjack yang berbeda dapat ditemukan dalam daftar 12 kartu yang dipesan.

Urutan Blackjack didefinisikan sebagai urutan kartu berturut-turut yang jumlah poinnya persis 21. Poin dihitung berdasarkan tabel berikut:

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

Memasukkan

String 12 karakter, menggunakan simbol yang dijelaskan di atas. Kami tidak peduli dengan warna kartu, jadi tidak disediakan.

Contoh:

K6K6JA3Q4389

Keluaran

Jumlah urutan Blackjack yang berbeda yang dapat ditemukan dalam string input.

Contoh:

K6K6JA3Q4389 termasuk dua urutan Blackjack yang berbeda:

contoh

  • JA, dengan Ace dihitung sebagai 11 poin (10 + 11 = 21)
  • A3Q43, dengan Ace dihitung sebagai 1 poin (1 + 3 + 10 + 4 + 3 = 21)

Jadi jawabannya 2.

Aturan

  • Dua urutan Blackjack dianggap berbeda jika mengandung kartu yang berbeda atau kartu yang sama dalam urutan yang berbeda. Jika urutan yang sama persis muncul di posisi yang berbeda dalam daftar input, itu harus dihitung hanya sekali.
  • Urutan Blackjack mungkin tumpang tindih satu sama lain.
  • Setiap jenis kartu dapat muncul hingga 12 kali berturut-turut. (Kami berasumsi bahwa kartu diambil dari setidaknya 3 deck yang berbeda.)
  • Jika tidak ada urutan Blackjack dalam string input, Anda harus mengembalikan 0atau nilai falsy lainnya.
  • Ini adalah kode-golf, jadi jawaban tersingkat dalam byte menang. Celah standar dilarang.

Uji kasus

Urutan disediakan untuk tujuan informasi, tetapi Anda hanya diminta untuk menampilkan jumlah mereka.

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
sumber
1
Hmm, bukankah urutannya harus dibatasi untuk yang panjangnya 5 atau kurang?
Jonathan Allan
@ Jonathan Allan Itu poin yang bagus. Saya pikir itu akan menjadi batasan di kasino. Tapi ini bukan game Blackjack sungguhan. Sebagai gantinya, saya memilih untuk membatasi input hingga 12 kartu sehingga banyak Aces tidak memerlukan terlalu banyak waktu komputasi. Apakah itu terdengar oke?
Arnauld
Tantangan berikutnya: Temukan string 12-char dengan urutan Blackjack paling unik: D
ETHproduk
Membatasi input menjadi 10 kartu akan jauh lebih mudah ...
Neil
@Neil Nah, itu akan membuat kasus 'sebelas Aces' tidak mungkin, tetapi apakah benar-benar ada optimasi yang signifikan di balik itu? Saya kira Anda mungkin memikirkan hal lain.
Arnauld

Jawaban:

6

Jelly , 30 29 byte

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

Cobalah secara Online! atau periksa suite tes

Bagaimana?

Perhatikan bahwa, jika kita selalu menilai kartu as sebagai 1 maka jumlah yang valid hanya 21 dan 11 , yang terakhir dapat diterima jika ace muncul dalam urutan.

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

Python 2, 215 byte

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)

Komentar ditambahkan:

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

Python , 134 130 byte

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

Cobalah online!

Bagaimana?

Fungsi yang tidak disebutkan namanya, mengambil string dengan panjang 12 sebagai x.

x[i:j]adalah sepotong string dari i + 1 th ke j th karakter.

Irisan diambil sedemikian rupa sehingga kita memiliki semua sublist dengan melintasi dari i=0ke i=11dengan for i in range(12), untuk masing-masing kita berpindah dari j=0ke j=12dengan for j in range(13).

(Kita hanya perlu j=i+1dan ke atas, tetapi irisan dengan j<=ihanya string kosong, sehingga kita dapat bermain golf 4 byte dari for j in range(i+1,13))

Ini difilter untuk mereka dengan jumlah yang benar ...

Jumlah yang valid adalah 11 dan 21 jika ada kartu as dalam slice, atau hanya 21 jika tidak. 'A'in x[i:j]memberi kami informasi ini dan ~(v)melakukan -1-v, yang kami gunakan untuk mengiris [11,21]- sehingga jika ace berada dalam urutan yang kami dapatkan [11,21][-2:]dan jika tidak kami dapatkan [11,21][-1:], menghasilkan [11,21]dan [21]masing - masing.

Jumlah itu sendiri perlu memperlakukan Asebagai 1, angka sebagai nilai-nilai mereka, dan T, J, Q, dan Ksebagai 10. pemetaan ini dicapai dengan pengecoran pertama yang ordinals:
" 2 3 4 5 6 7 8 9 T J Q K A"(tanpa spasi) menjadi
[50, 51, 52, 53, 54, 55, 56, 57, 84, 74, 81, 75, 65], mengurangkan 48 untuk mendapatkan
[ 2, 3, 4, 5, 6, 7, 8, 9, 36, 26, 33, 27, 17], mengambil mindengan 26 hasil
[ 2, 3, 4, 5, 6, 7, 8, 9, 26, 26, 26, 26, 17], dan mod ( %) enam belas
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 1], seperti yang dipersyaratkan untuk penjumlahan sum(...),.

Hasil yang disaring ditempatkan ke dalam satu set dengan {...}, jadi hanya hasil unik yang tersisa dan panjangnya, len(...)yang dihitung

Jonathan Allan
sumber
3

05AB1E , 39 38 37 byte

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

Cobalah online!

Penjelasan

'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
sumber
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
sumber
Ide bagus, tapi ini kembali 0untuk AAAAAAAAAAAAbukan 1. ( Asecara bersamaan dapat 1 dan 11)
ETHproduksi
Dengan menggabungkan dua entri kami, Anda bisa mendapatkan 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 byte
ETHproduksi
@ ETHproductions Mulai dari 21 tampaknya masih menyelamatkan saya satu byte.
Neil
@ ETHproductions ... itu membantu jika saya memposting jumlah byte yang benar ...
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

Upaya lama di 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
Produksi ETH
sumber
s.search`A`>-1bisa jadi~s.search`A`
Luke
@ Lukas Tidak, sebenarnya, karena itu mengembalikan nilai-nilai seperti -2, dan1&-2 == 0
ETHproduksi
Benar. Mungkin diatur tke 0dalam .slice(0,-1)panggilan (menghemat 2B)?
Luke
@ Lukas Saya tidak berpikir itu akan berhasil, seperti tvariabel global dan itu akan diatur ulang karena panggilan ke f(s.slice(0,-1)). Tapi saya menemukan jalan sekitar s.search`A`>-1:-)
ETHproduksi
Saya ingin tahu apa yang Anda miliki ketika Anda selesai bermain golf ini. Saya tampaknya terjebak pada 113 untuk saat ini.
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

Logika kode ini sangat mirip dengan yang digunakan dalam jawaban JS yang ada dari ETHproduksi dan Neil . Tapi itu menggunakan array dasar untuk melacak urutan Blackjack yang ditemui daripada a Set.

Diformat dan dikomentari

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

Uji kasus

Arnauld
sumber
Saya mencoba rekursi ganda, bergerak mundur melalui string, secara kumulatif menghitung setiap string yang mungkin karena setiap karakter dikonsumsi ... namun pendekatan terpendek adalah dengan menjalankan melalui setiap irisan. Yang bagus! (Menggunakan Perangkat tampaknya lebih panjang tiga byte, jika saya hitung dengan benar)
ETHproduksi
2

05AB1E , 40 39 38 37 36 byte

-4 Terima kasih kepada Emigna

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

Cobalah 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

Kita perlu melakukan decrement -> substring -> increment thing sehingga face card diwakili oleh satu digit angka.

Riley
sumber
Cara yang bagus untuk berkeliling dua digit! Anda dapat menghapus yang pertama Ssebagai Çmengubah string menjadi daftar kode karakter.
Emigna
Juga, "SIPJ"bisa jadi„èµJu
Emigna
@Emigna Terima kasih. Saya pikir ada cara untuk melakukan itu, tetapi saya tidak dapat menemukan cara menggunakannya dalam dokumentasi.
Riley
Anda dapat menyimpan 2 byte lebih banyak dengan menulis ulang sebagai Ç<çJŒÙ'@0:)vy„èµJuS9:S>D1å2‚T*>sOå}OKemudian Anda 1 byte lebih pendek dari jawaban saya :)
Emigna
@ Emigna Ini adalah jumlah byte yang sama dan lebih seperti aslinya.
Riley
1

Utilitas Bash + Unix, 145 142 141 byte

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

Cobalah online!

Tes berjalan:

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

PHP, 240 byte

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

Tidak Disatukan:

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

Coba di sini!

roberto06
sumber
1
Aneh, aku berani bersumpah itu berhasil pada tes lokal saya, tetapi tampaknya Anda benar. Bagaimanapun; masalahnya berasal dari fakta yang $itidak dinyatakan. Menambahkan 4 byte dan berfungsi dengan baik.
roberto06