그 목록에 얼마나 많은 블랙 잭 시퀀스가 ​​있습니까?


21

당신의 임무는 12 개의 카드 목록에서 몇 개의 별개의 블랙 잭 시퀀스를 찾을 수 있는지 찾는 것입니다.

블랙 잭 시퀀스는 포인트 합계가 정확히 21 인 연속 된 카드 시퀀스로 정의됩니다. 포인트는 다음 표에 따라 계산됩니다.

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

입력

위에서 설명한 기호를 사용하는 12 자 문자열 우리는 카드의 색상에 신경 쓰지 않으므로 제공되지 않습니다.

예:

K6K6JA3Q4389

산출

입력 문자열에서 찾을 수있는 별개의 블랙 잭 시퀀스 수입니다.

예:

K6K6JA3Q4389 두 개의 별개의 블랙 잭 시퀀스를 포함합니다.

예

  • JA에이스는 11 포인트로 계산됩니다 (10 + 11 = 21)
  • A3Q43Ace가 1 포인트로 계산됩니다 (1 + 3 + 10 + 4 + 3 = 21).

대답은입니다 2.

규칙

  • 두 개의 블랙 잭 시퀀스는 다른 카드 또는 동일한 카드를 다른 순서로 포함하는 경우 별개의 것으로 간주됩니다. 입력 목록의 다른 위치에 정확히 동일한 시퀀스가 ​​표시되면 한 번만 계산해야합니다.
  • 블랙 잭 시퀀스는 서로 겹칠 수 있습니다.
  • 각 종류의 카드는 순서대로 최대 12 번 나타날 수 있습니다. (우리는 카드가 적어도 3 개의 다른 덱에서 선택되었다고 가정합니다.)
  • 입력 문자열에서 블랙 잭 시퀀스를 찾을 수 없으면 0또는 다른 잘못된 값을 반환해야합니다 .
  • 이것은 코드 골프이므로 바이트 단위의 최단 답변이 이깁니다. 표준 허점은 금지되어 있습니다.

테스트 사례

시퀀스는 정보 제공을 위해 제공되지만 그 수만 출력하면됩니다.

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

1
흠, 시퀀스는 길이가 5 이하인 것으로 제한되어서는 안됩니까?
Jonathan Allan

@JonathanAllan 좋은 지적입니다. 나는 그것이 카지노의 한계라고 생각합니다. 그러나 이것은 실제 블랙 잭 게임이 아닙니다. 대신, 많은 에이스가 너무 많은 계산 시간을 필요로하지 않도록 입력을 12 카드로 제한하기로 선택했습니다. 괜찮습니까?
Arnauld

다음 도전 과제 : 가장 독특한 블랙 잭 시퀀스가있는 12 자리 문자열 찾기 : D
ETHproductions

입력을 10 장의 카드로 제한하는 것이 훨씬 쉬웠을 것입니다 ...
Neil

@Neil 음, 그것은 '11 개의 Aces '사례를 불가능하게 만들었을 것입니다. 그러나 실제로 그 뒤에 중요한 최적화가 있습니까? 나는 당신이 다른 것을 염두에두고 있다고 생각합니다.
Arnauld 2012

답변:


6

젤리 , 30 29 바이트

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

온라인으로 사용해보십시오! 또는 테스트 스위트를 확인하십시오

방법?

우리가 항상 에이스를 1 로 평가하면 유효한 합은 2111 뿐이며 , 후자는 에이스가 시퀀스에 나타날 때 허용됩니다.

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

7

파이썬 2, 215 바이트

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)

댓글 추가 :

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

3

파이썬 , 134130 바이트

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

온라인으로 사용해보십시오!

방법?

이름없는 함수와 같은 길이 12의 문자열을 복용 x.

x[i:j]i + 1 번째 의 문자열 조각입니다. 부터 j 번째 .

조각은 우리가에서 이송 모든 하위 목록을 갖도록 촬영 i=0i=11for i in range(12)있는 우리가에서 통과 각각에 대하여,j=0j=12for j in range(13).

(우리는 단지 필요 j=i+1 이상이지만, 슬라이스가 j<=i비어있는 문자열이므로에서 4 바이트를 골프 오프 할 수 있습니다 for j in range(i+1,13))

올바른 합계를 가진 사람들을 위해 필터링됩니다 ...

슬라이스에 에이스가 있으면 유효한 합계는 11과 21이며 그렇지 않으면 21입니다. 'A'in x[i:j]우리에게이 정보를 제공하고 ~(v)수행합니다 -1-v. 우리가 슬라이스를하는 데 사용합니다. [11,21]따라서 에이스가 우리가 얻는 순서에 [11,21][-2:]있고 그렇지 않으면 얻 [11,21][-1:]습니다.[11,21][21]각각입니다.

자체를 취급 할 필요가 합계 A1과는, 그 값으로 자리수, T, J, Q, 및 K10로 맵핑하는 서수 먼저 주조에 의해 달성된다 :
" 2 3 4 5 6 7 8 9 T J Q K A"(공백없이)하게
[50, 51, 52, 53, 54, 55, 56, 57, 84, 74, 81, 75, 65]얻을 48을 빼서
[ 2, 3, 4, 5, 6, 7, 8, 9, 36, 26, 33, 27, 17]상기에게 복용 min26 개 수율
[ 2, 3, 4, 5, 6, 7, 8, 9, 26, 26, 26, 26, 17], 그리고 mod ( %) 16 개
[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 1]는 합계에 필요한대로sum(...) .

필터링 된 결과는로 세트에 배치 {...}되므로 고유 한 결과 만 남고 길이 len(...)는 개수입니다.


3

05AB1E , 39 38 37 바이트

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

온라인으로 사용해보십시오!

설명

'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

3

자바 스크립트 (ES6), 123 바이트

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>


좋은 생각이지만 이것은 대신에 반환 0됩니다 . ( 동시에 1과 11이 될 수 있습니다)AAAAAAAAAAAA1A
ETHproductions

두 항목을 결합하면 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 바이트를 얻을 수 있습니다.
ETHproductions

@ETHproductions 21부터 시작해도 여전히 바이트를 절약하는 것 같습니다.
Neil

@ETHproductions ... 올바른 바이트 수를 게시하면 도움이됩니다 ...
Neil

3

자바 스크립트 (ES6) 144 138 129 128 126 124 바이트

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

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

s.search`A`>-1가능~s.search`A`
Luke

@Luke 아니, 사실은, 그 반환 값 때문에 같은 -2, 그리고1&-2 == 0
ETHproductions

참된. 아마 설정 t0에서 .slice(0,-1)호출 (저장 2B)?
Luke

@Luke t전역 변수와 마찬가지로 작동하지 않으며 에 대한 호출로 인해 재설정 될 것이라고 생각합니다 f(s.slice(0,-1)). 그러나 나는 길을 찾았습니다 s.search`A`>-1:-)
ETHproductions

나는 당신이 골프를 다했을 때 무엇을 가지고 있는지 궁금합니다. 나는 지금 113에 붙어있는 것 같습니다.
Arnauld 2012

3

자바 스크립트 (ES6), 112 바이트

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

이 코드 로직은 ETHproductionsNeil의 기존 JS 답변에 사용 된 것과 매우 유사합니다 . 그러나 기본 배열을 사용하여 a 대신 발생하는 블랙 잭 시퀀스를 추적합니다 Set.

형식화 및 의견

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

테스트 사례


문자열을 통해 뒤로 이동하여 각 문자가 소비 될 때 가능한 각 문자열을 누적 적으로 계산하는 이중 재귀를 시도했지만 가장 짧은 방법은 각 조각을 실행하는 것입니다. 좋은 것! (정확하게 계산하면 세트 사용이 3 바이트 더 길어
보입니다

2

05AB1E , 40 39 38 37 36 바이트

-4 감사합니다 Emigna

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

온라인으로 사용해보십시오!

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

페이스 카드가 한 자리 숫자로 표시되도록 감소-> 부분 문자열-> 증가 작업을 수행해야합니다.


두 자리 숫자를 얻는 좋은 방법! 문자열을 문자 코드 목록 S으로 Ç바꾸면서 첫 번째 를 제거 할 수 있습니다 .
Emigna

또한, "SIPJ"„èµJu
Emigna

@Emigna 감사합니다. 그 방법이 있다고 생각했지만 문서에서 사용법을 찾을 수 없었습니다 .
라일리

다시 쓰면 2 바이트를 더 절약 할 수 있습니다. Ç<çJŒÙ'@0:)vy„èµJuS9:S>D1å2‚T*>sOå}O그러면 내 대답보다 1 바이트 짧습니다 :)
Emigna

@Emigna 이것은 동일한 바이트 수이며 내 원본과 비슷합니다.
라일리

1

배시 + 유닉스 유틸리티 145 142 141 바이트

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

온라인으로 사용해보십시오!

시운전 :

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

1

PHP, 240 바이트

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

언 골프 :

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

여기 사용해보십시오!


1
이상하게도, 나는 그것이 내 로컬 테스트에서 작동한다고 맹세 할 수 있었지만, 당신이 옳은 것 같습니다. 어쨌든; 문제는 $i선언되지 않은 사실에서 비롯된 것 입니다. 4 바이트가 추가되었으며 완벽하게 작동합니다.
roberto06
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.