Bir Cribbage Hand'i puanla


28

Bu zorluk, bir Cribbage eli elde etmektir. Cribbage oynamıyorsan, yapmayı öğrendiğin bazı şeyler var. Standart bir poker destesiyle oynarız ve bir el dört kart ve "yukarı kart" dan oluşur. İki tür el vardır: normal ve bir beşik eli.

Kartlar biçiminde gelir : biri (On için T) ve bir tanesidir . Bir el şeklinde verilecek (örneğin)vsvA23456789TJQKsSCDH

AS 2D 3H JS | 4S

4Syukarı kart nerede . Bir beşik elin biçimi olacak

JD 3C 4H 5H | 5S !

Yüz kartlarının değeri 10'dur ve as değeri 1'dir. Puanlama aşağıdaki gibi yapılır.

  • Onbeşler: toplamı 15 olan beş kartın her alt kümesi için iki nokta ekleyin.
  • Çiftler: Aynı değere sahip her kart çifti için (değer değil) iki puan ekleyin.
  • Koşular: 2'den uzun arka arkaya kartların her maksimum koşusu için, koşunun uzunluğunu nokta cinsinden ekleyin.
  • Flush: Beş kartın tümü aynı renkse, beş puan ekleyin. Aksi takdirde, üstteki kart dışındakilerin hepsi aynı ise, dört nokta ekleyin. Bu bir beşik eli ise, dört noktalı değişken sayılmaz.
  • Notlar: Eğer yukarı kartın aynı takımını elinde tutan bir kriko varsa, bir nokta ekleyin.

Notlar:

  • Üçlü ve dörtlü bir tür özel değildir - üçlü olarak üç çift vardır, bu yüzden üçlü 6 puan değerindedir.

  • Çalışmalar üst üste gelebilir. Örneğin, AS AH 2D 3C | 2C(bir çift ikili koşu) dört uzunluk 3 ve iki çift koşuya sahiptir, bu nedenle 3 + 3 + 3 + 3 + 2 + 2 = 16 puan değerindedir.

  • Yalnızca maksimal sayımlar sayılır, KS QD JD TC | 9S5 puan olduğundan 5 puan değerindedir. Alt sayımlar sayılmaz.

Ev Kuralı:

Bir elinde 19 puan almak mümkün değil. Sıfır yerine, 19 puan verin.

Örnekler:

5S 5H 5D JS | KS
21

AS 2D 3H JS | 4S !
9

JD 3C 4H 5H | 5S
12

9S 8S 7S 6S | 5H !
9

9S 8S 7S 6S | 5H
13

8D 7D 6D 5D | 4D !
14

8D 7D 6D 5D | 4D
14

AD KD 3C QD | 6D
19

Bu kod golfü. En kısa çözüm kazanır.


4
"on beş iki, on beş dört, ..." Evet, yai, yai, ama uzun zaman oldu.
dmckee

2
@dmckee, evet, puanlama şartlarımda çok iyiydim. Ben ... patter tam bir açıklama koyarak düşündüm "on beş iki, 1504 ve altı için bir çift; onları yapışır peg" . Ancak, sorun açıklaması 30 sayfa uzunluğunda olur.
Boothby

1
3 + 3 + 3 + 3 + 2 = 16 mı? Sanırım bir tane daha + 2 kaçırıyorsun.
grc

1
Ve ikinci ve son örneklerin 9 ve 1 olması mı gerekiyor? Son kuralın kendileri için geçerli olması gerektiğini düşünüyorum ama emin değilim (daha önce hiç cribbage oynamamıştım).
grc

1
@ grc yup, bunlardaki isimleri özledim. Bu, hangi skorlamanın en zor kısım olduğunu bildiğim tek oyundur.
boothby

Yanıtlar:


2

GolfScript, 187 178 174 karakter

:c"J"c{"SCDH"?)},1/:s-1=+/,([s)-!5*s);)-!4*c"!"?)!*]$-1=+0.14,{c{"A23456789TJQK"?)}%{},:v\{=}+,,.{@*\)}{;.2>**+1 0}if}/;;5-v{{=+}+v\/}/[0]v{.9>{;10}*{1$+}+%}/{15=},,2*+.!19*+

Hiçbir zaman cribbage oynamamıştım, hiçbir fantezi skoru bilmiyorum. Bu yüzden rekabet etmenin tek yolunun (en azından biraz) bir golf dili kullanmak olduğunu düşündüm. Kod oldukça sade bir GolfScript, test senaryoları burada bulunabilir . .

Daha okunaklı bir şekilde kod ( biraz biçimlendirilmiş ve çözülmüş ):

# Save cards to <c>
:c;

# Is it a non-crib hand? <r>
c"!"?)!:r;

# Values go to <v>
c{"A23456789TJQK"?)}%{},:v;

# Suits go to <s>
c{"SCDH"?)},1/:s;

# Print score for Fifteens
[0]v{.9>{;10}*{1$+}+%}/{15=},,2* .p

# Print score for Pairs
-5v{{=+}+v\/}/ .p

# Print score for Runs
0..14,{v\{=}+,,.{*\)\}{;\.2>**+0 1}if}/;; .p

# Print score for Flush
[s)-!5*s);)-!4*r*]$-1= .p

# And finally print the score for Nobs
c"J"s-1=+/,( .p

# Sum up the sub-scores and if score is zero set to 19
++++
.!19*+

Düzenleme: Onbeş ve sifon için değiştirilmiş mantık.


1
Olmadı! Bu gördüğüm en uzun GS senaryosu! Bravo!
stand

7

C, 364 388 karakter

Büyük ve çirkin (bir zamanlar olduğu kadar büyük olmasa da):

char*L="CA23456789TJQKDHS",b[20],p[15],r[5],s[5],v,i=4,t,m,q;
g(j){++p[r[i]=strchr(L,b[j])-L];s[i]=strchr(L,b[j+1])-L;}
f(j,u){u==15?v+=2:++j<5&&f(j,u,f(j,u+(r[j]>9?10:r[j])));}
main(){gets(b);for(g(14);i--;r[i]^11|s[i]^s[4]||++v)g(i*3);
for(f(i,0);++i<15;v+=q?q*q-q:t>2?t*m:0,t=q?t+1:0,m=q?m*q:1)q=p[i];
while(++t<5&&s[t]==*s);v+=t>4-!b[16]?t:0;printf("%d\n",v?v:19);}

(Okumayı kolaylaştırmak için satır sonları eklendi; bunlar yukarıdaki bölüme dahil edilmedi.)

Sorun açıklaması, kodun geçersiz girdi olup olmadığını denetlemesi gerekip gerekmediğini belirtmedi, bu nedenle, doğal olarak, programın, girişin fazladan boşluk içeriyorsa, istediği gibi programın hatalı davranmakta serbest olduğunu varsaydım.

İşte ungolfed versiyonu:

#include <stdio.h>
#include <string.h>

/* A-K correspond to values 1-13. Suit values are arbitrary.
 */
static char const *symbols="CA23456789TJQKDHS";

/* Used as both an input buffer and to bucket cards by rank.
 */
static char buf[20];

/* The cards.
 */
static int rank[5], suit[5];

/* The cards broken down by rank.
 */
static int buckets[15];

static int score;
static int touching, matching, i;

/* Read card number i from buf at position j.
 */
static void getcard(int j)
{
    rank[i] = strchr(symbols, buf[j]) - symbols;
    suit[i] = strchr(symbols, buf[j+1]) - symbols;
    ++buckets[rank[i];
}

/* Recursively find all combinations that add up to fifteen.
 */
static void fifteens(int j, int total)
{
    for ( ; j < 5 ; ++j) {
        int subtotal = total + (rank[j] > 9 ? 10 : rank[j]);
        if (subtotal == 15)
            score += 2;
        else if (subtotal < 15)
            fifteens(j + 1, subtotal);
    }
}

int main(void)
{
    fgets(buf, sizeof buf, stdin);
    score = 0;

    /* Read cards from buf */
    for (i = 0 ; i < 4 ; ++i)
        getcard(i * 3);
    getcard(14);

    /* Score fifteens */
    fifteens(0, 0);

    /* Score any runs and/or pairs */
    touching = 0;
    matching = 1;
    for (i = 1 ; i < 15 ; ++i) {
        if (buckets[i]) {
            score += buckets[i] * (buckets[i] - 1);
            ++touching;
            matching *= buckets[i];
        } else {
            if (touching > 2)
                score += touching * matching;
            touching = 0;
            matching = 1;
        }
    }

    /* Check for flush */
    for (i = 1 ; i < 5 && suit[i] == suit[0] ; ++i) ;
    if (i >= (buf[17] == '!' ? 5 : 4))
        score += i;

    /* Check for hisnob */
    for (i = 0 ; i < 4 ; ++i)
        if (rank[i] == 11 && suit[i] == suit[4])
            ++score;

    printf("%d\n", score ? score : 19);
    return 0;
}

Belirtmediğim için şu 20 karakterden tıraş olmaktan çekinmeyin!
12'de

Bu gerçekten etkileyici - soru da büyük ve çirkin! Bu kod golf olmak, bok girişinde segfaulting a-ok.
12'de stant

5

Ruby 1.9, 359 356

Çok uzun - neredeyse C çözümü kadar.

R='A23456789TJQK'
y=gets
f=y.scan /\w+/
o=f.map(&:chr).sort_by{|k|R.index k}
s=0
2.upto(5){|i|o.combination(i){|j|t=0
j.map{|k|t+=k==?A?1:k<?:?k.hex: 10}
(t==15||i<3&&j.uniq!)&&s+=2}}
m=n=l=1
(o+[z=?_]).map{|k|k[z]?n+=1:R[z+k]?(m*=n
l+=n=1):(l>2&&s+=l*m*n
l=n=m=1)
z=k}
x=f.take_while{|k|k[y[1]]}.size
x>(y[?!]?4:3)&&s+=x
y[?J+f[4][1]+' ']&&s+=1
p s>0?s:19

5

Başlamak için bir şey .. Ruby, 422 365 355 352

c=gets
a,b=c.scan(/(\w)(\w)/).transpose
f=->x{x.uniq.size<2}
s=f[b]?5:!c[/!/]&f[b[0,4]]?4:0
c[/J(.).*\1 ?!?$/]&&s+=1
s+=[5,4,3].map{|i|a.permutation(i).map{|x|'A23456789TJQK'[x*'']?i:0}.inject :+}.find{|x|x>0}||0
a.map{|x|s+=a.count(x)-1}
2.upto(5){|i|s+=2*a.map{|x|x.tr(?A,?1).sub(/\D/,'10').to_i}.combination(i).count{|x|x.inject(:+)==15}}
p s<1?19:s

Biraz ungolfed:

def t(c)
  s=0

  if c.scan(/[SDHC]/).uniq.size<2 # Flush
    s+=5 
  elsif c[0..9].scan(/[SDHC]/).uniq.size<2 && c[-1]!=?! # Flush
    s+=4
  end
  s+=1 if c =~ /J(.).*(\1$|\1\s.$)/ # Nobs

  c=c.scan(/[^ \|]+/).map{|x|x[0]}[0..4]
  d = (3..5).map{|i|c.permutation(i).map{|x| 'A23456789TJQK'.include?(x*'') ? i : 0}.inject(:+)}.reverse.find{|x|x>0} || 0# Runs
  s+=d
  c.map{|x|s+=c.count(x)-1} # Pairs
  c.map!{|x|x.tr('A','1').gsub(/[JQK]/,'10').to_i}
  (2..5).map{|i|s+=2*c.combination(i).count{|x|15==x.inject(:+)}} # 15s
  s<1 ? 19 : s
end

Golf sürümü için birim testleri:

require "test/unit"

def t(c)
c=gets
a,b=c.scan(/(\w)(\w)/).transpose
f=->x{x.uniq.size<2}
s=f[b]?5:!c[/!/]&f[b[0,4]]?4:0
c[/J(.).*\1 ?!?$/]&&s+=1
s+=[5,4,3].map{|i|a.permutation(i).map{|x|'A23456789TJQK'[x*'']?i:0}.inject :+}.find{|x|x>0}||0
a.map{|x|s+=a.count(x)-1}
2.upto(5){|i|s+=2*a.map{|x|x.tr(?A,?1).sub(/\D/,'10').to_i}.combination(i).count{|x|x.inject(:+)==15}}
p s<1?19:s
end

class Test1 < Test::Unit::TestCase
  def test_simple
    assert_equal 21, t("5S 5H 5D JS | KS")
    assert_equal 21, t("JS 5H 5D 5S | KS")
    assert_equal 12, t("JD 3C 4H 5H | 5S")
    assert_equal 13, t("9S 8S 7S 6S | 5H")
    assert_equal 14, t("8D 7D 6D 5D | 4D")
    assert_equal 19, t("AD KD 3C QD | 6D")
    assert_equal 9, t("AS 2D 3H JS | 4S !")
    assert_equal 9, t("JS 2D 3H AS | 4S !")
    assert_equal 14, t("8D 7D 6D 5D | 4D !")
    assert_equal 9, t("9S 8S 7S 6S | 5H !")
  end
end

Sonuçlar:

% ruby ./crib.rb
   Run options: 

# Running tests:

21
21
12
13
14
19
9
9
14
9
.

Finished tests in 0.014529s, 68.8281 tests/s, 688.2813 assertions/s.

1 tests, 10 assertions, 0 failures, 0 errors, 0 skips

4

Python, 629 karakter

Sadece benimkimi gönderiyorum çünkü başka hiç kimse yok. Oldukça uzun :(

g=range
i=raw_input().split()
r,u=zip(*[tuple(x)for x in i if x not in'!|'])
v=map(int,[((x,10)[x in'TJQK'],1)[x=='A']for x in r])
z=list(set(map(int,[(x,dict(zip('ATJQK',[1,10,11,12,13])).get(x))[x in'ATJQK']for x in r])))
z.sort()
z=[-1]*(5-len(z))+z
s=p=l=0
for a in g(5):
 for b in g(a+1,5):
    s+=2*(v[a]+v[b]==15)
    p+=2*(r[a]==r[b])
    if z[a:b+1]==g(z[a],z[b]+1)and b-a>1:l=max(l,b+1-a)
    for c in g(b+1,5):s+=2*(v[a]+v[b]+v[c]==15)
for d in g(5):s+=2*(sum(v)-v[d]==15)
n=len(set(u))
s+=4*(n==2 and u[-1] not in u[:4] and i[-1]!='!')+5*(n<2)+('J'+u[4]in i[:4])+2*(sum(v)==15)+p+((l*3,l*p)[p<5]or l)
print(s,19)[s<1]

Vay, bu çok uzun! Yine de güzel bitti. Btw, tırnak ve parantez önce / sonra boşluklara ihtiyacınız yok.
boothby

1
Oh teşekkürler, bunu unuttum. Şimdi biraz daha kısa;)
grc

Ne dersiniz print s or 19? Ben de 3 daha fazla karakter kapatma (Python 3.x ve tıraş kullanabilirsiniz düşünmek raw_inputiçin inputdaha sonra, print s or 19karşı print(s or 19)).
Ry

2

Python 2, 606 584 bayt

Jo King 'in golfü nedeniyle 22 bayt kurtarıldı .

from itertools import*
s,S,C,E=sum,sorted,combinations,enumerate
def f(a):a=a.split();a.pop(4);e=a.pop(5)if a[-1]<"$"else 0;b=S("A23456789TJQK".index(i)for i,j in a);d=S(set(b));h=[j for i,j in a];z=len([s(k)for r in range(6)for k in C([[10,k+1][k<10]for k in b],r)if s(k)==15])*2+s(2for i,j in C(b,2)if i==j)+[4*(e<1),5][len(set(h))<2]*(len(set(h[:4]))<2)+(a[4][1]in[j for i,j in a[:4]if i=="J"])+s(reduce(lambda x,y:x*y,[b.count(k)for k in m])*len(m)for m in[d[s(x[:i]):s(x[:i])+j]for x in[[len(list(e))for i,e in groupby(j-i for i,j in E(d))]]for i,j in E(x)if j>2]);return z or 19

Çevrimiçi deneyin!

Grc'den biraz daha kısa cevabından ve oraya farklı bir rota .

Açıklama:

    # import everything from "itertools" library. We only need "combinations" and "groupby".
from itertools import*
# alias functions to shorter names
s,S,C,E=sum,sorted,combinations,enumerate

# function f which takes the hand+up card+crib string as its argument
def f(a):
    # convert space-separated string into list of items.
    a=a.split()

    # remove the 4th index, which is always "|".
    a.pop(4)

    # change golfed by Jo King
    # if the final item in the list is a "!" (if it is <"$"), remove it from the list and assign it to variable "e".
    # otherwise, assign 0 to variable "e".
    # a non-empty string will evaluate to True and 0 will evaluate to False in IF checks later.
    e=a.pop(5)if a[-1]<"$"else 0

    # for each card in the list, split the identifiers into the value(i) and the suit(j).
    # return the value's index in the string "A23456789TJQK".
    # so, ["5S", "5H", "5D", "JS", "KS"] will return [4, 4, 4, 10, 12].
    # using the aliased built-in function sorted(), sort the list numerically ascending.
    b=S("A23456789TJQK".index(i)for i,j in a)

    # get the unique items in b, then sort the result numerically ascending.
    d=S(set(b))

    # for each card in the list, split the identifiers into the value(i) and the suit(j).
    # return the suits.
    h=[j for i,j in a]

        # fifteens
        # changes golfed by Jo King
        # generate pairs of (10, value + 1) for all cards (since they are zero-indexed)
        # since True and False evaluate to 1 and 0 in python, return 10 if k>=10
        # and reduce all values >10 to 10
        # get all unique combinations of cards for 5 cards, 4 cards, 3 cards, 2 cards, and 1 card
        # add the values of all unique combinations, and return any that equal 15
        # multiply the number of returned 15s by 2 for score
    z=len([s(k)for r in range(6)for k in C([[10,k+1][k<10]for k in b],r)if s(k)==15])*2
        +
        # pairs
        # using itertools.combinations, get all unique combinations of cards into groups of 2.
        # then, add 2 for each pair where both cards have an identical value.
        s(2for i,j in C(b,2)if i==j)
        +
        # flush
        # changes golfed by Jo King
        # using list indexing
        # [4 * (0 if crib else 1), 5], get item at index [0 if more than one suit in hand+up card else 1]
        #    -> 4 if not crib and not all suits same
        #    -> 5 if all cards same
        #    -> 0 otherwise
        # * (0 if more than one suit in hand else 1)
        #    -> 4 * 0 if not crib and not all suits same
        #    -> 4 * 1 if not crib and all suits same
        #    -> 5 * 1 if all cards same
        #    -> 0 otherwise
        [4*(e<1),5][len(set(h))<2]*(len(set(h[:4]))<2)
        +
        # nobs
        # check if the suit of the 5th card (4, zero-indexed) matches the suit of any of the other 4 cards, and if it does is that card a Jack
        (a[4][1]in[j for i,j in a[:4]if i=="J"])
        +
        # runs
        s(reduce(lambda x,y:x*y,[b.count(k)for k in m])*len(m)for m in[d[s(x[:i]):s(x[:i])+j]for x in[[len(list(e))for i,e in groupby(j-i for i,j in E(d))]]for i,j in E(x)if j>2])

    # since only 0 evaluates to false, iff z==0 return 19, else return z.
    print z or 19

Özellikle çalıştırma mantığı için açıklama:

# for each index and value in the list, add the value minus the index
# since the list is sorted and reduced to unique values, this means adjacent values will all be the same value after offset
# ex: "JD 3C 4H 5H | 5S" -> [2, 3, 4, 10] - > [2, 2, 2, 7]
z = []
for i,j in enumerate(d):
    z.append(j-i)

# group the values by unique value
# then add the length of the groups to the list
# ex: [2, 2, 2, 7] -> [2:[2,2,2], 7:[7]]
#     [2:[2,2,2], 7:[7]] -> [[3], [1]]
w = []
for i,e in groupby(z):
    w.append([len(list(e))])

# list is double-nested so that the combined list comprehension leaves "x" available in both places it is needed
z = []
for x in w:
    for i,j in enumerate(x):
        if j>2:
            # if the group length is larger than 2
            # slice the list of unique card values to obtain only run values
            # since the run can be anywhere in the list, sum the preceding lengths to find the start and end index
            a = d[ sum(x[:i]) : sum(x[:i])+j ]
            z.append(a)

w = []
for m in z:
    # get the number of times the value is in the entire hand
    # ex: "JD 3C 4H 5H | 5S" -> [2,3,4,4,10] and (2,3,4) -> [1, 1, 2]
    a = [b.count(k)for k in m]
    # multiply all values together
    # [1, 1, 2] = 1*1*2 = 2
    a = reduce(lambda x,y:x*y, a)
    # length of the run * number of duplicate values
    a *= len(m)
    w.append(a)

# sum the results of the runs
return sum(w)

1
584 byteif ulaşmak için bazı hızlı golf
Jo King

1

Stax , 106 bayt

Çí╬Δ╓↔╥.L§º♦½┌§└─»◄G≤n▒HJ♀p$¼♥,Q¢▲»Δ÷♠º≈r↑Vo\b■┌4Üé∟]e:┬A½f║J4σ↔└ΓW6O?╧φ¡╫╠├√├ùß5₧k%5ê╜ò/Φ/7w╠█91I◘┬n≥ìk♂╪

Çevrimiçi çalıştırın ve hata ayıklayın!

CP437 için bonus: Paketlenmiş Stax'taki takım elbisesi sembolüne bakın? Kulüplerin ortaya çıkmaması çok kötü ...

ASCII eşdeğeri

jc%7<~6(4|@Y{h"A23456789TJQK"I^mXS{{A|mm|+15=_%2=_:u*+f%HxS{{o:-u1]=f{%mc3+|Msn#*+y{H"SHCD"ImY:uc5*s!yNd:u;**HH++yN|Ixs@11#+c19?

açıklama

jc%7<~6(4|@Y...X...Y...c19?
j                              Split on space
 c%7<~                         Is it a crib hand? Put it on input stack for later use
      6(                       Remove "!" if it exists
        4|@                    Remove "|"
           Y                   Store list of cards in y
            ...X               Store ranks in x
                ...            Perform scoring for ranks
                   Y           Store suits in y
                    ...        Perform scoring for suits
                       c19?    If the score is 0, change it to 19

{h"..."I^mX
{        m     Map each two character string to
 h             The first character
  "..."I^      1-based index of the character in the string

S{{A|mm|+15=_%2=_:u*+f%H
S                          Powerset
 {                   f%H   Twice the number of elements that satisfy the predicate
  {A|mm                        Value of card. Take the minimum of the rank and 10
       |+15=                   Sum of values equal 15 (*)
            _%2=               Length is 2 (**)
                _:u            All elements are the same (***)
                   *+          ( (***) and (**) ) or (*)

xS{{o:-u1]=f{%mc3+|Msn#*+
xS                                Powerset of ranks
  {        f                      Filter with predicate
   {o                                 Sort
     :-u                              Unique differences between elements
        1]=                           Is [1]
            {%mc                  Length of all runs
                3+|M              Maximum of all the lengths and 3
                    sn#           Number of runs with maximal length
                       *          Multiplied by its length
                        +         Add to score

y{H"SHCD"ImY
y{        mY    For each two character string
  H"SHCD"I      0-based index of the second character in the string "SHCD"

:uc5*s!yNd:u;**HH++
:uc5*                 5 points if all cards have same suit
     s!               Not all cards have same suit (#)
       yNd:u          First four cards have same suit (##)
            ;         Not a crib hand (###)
             **HH++   4 points if (#) and (##) and (###), add to score

yN|Ixs@11#+
yN|I           Index of cards with the same suit of last card (not including itself)
    xs@        The rank at these indices
       11#     Number of Jacks with the same suit of last card
          +    Add to score
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.