Skor Yahtzee terbaik

26

Yahtzee adalah permainan yang dimainkan dengan lima dadu enam sisi dan lembar skor dengan tiga belas kotak berbeda untuk mengisi skor. Setiap kotak memiliki aturan penilaian sendiri:

  • 1s, 2s, 3s, 4s, 5s, 6s semua skor poin sama dengan jumlah dadu masing-masing (yaitu, gulungan [3, 2, 3, 1, 5] skor sebagai 3s akan diberikan 6 poin: 3 untuk masing-masing 3).
  • 3-of-a-kind dan 4-of-kind (seperti yang terdengar, tiga atau empat dadu digulung sama) skor poin sama dengan jumlah semua lima dadu.
  • Rumah penuh (dua dadu menunjukkan satu nilai, tiga lainnya menunjukkan lain) skor 25 poin
  • Kecil lurus (empat nilai berturut-turut) skor 30 poin
  • Besar lurus (semua nilai berturut-turut) skor 40 poin
  • Yahtzee (semua dadu menunjukkan nilai yang sama) mencetak 50 poin

Ketigabelas (kesempatan) masuk akal dalam game, tetapi tidak terlalu banyak untuk tantangan ini; selain itu permainan memiliki bonus untuk Yahtze tambahan yang tidak masuk akal di sini. Karena tantangannya adalah ...

Diberikan lima dadu sebagai input (lima bilangan bulat 1-6, input bagaimanapun nyaman, Anda dapat menganggap input selalu valid), menghasilkan skor tertinggi yang mungkin untuk 'tangan' itu. Untuk tujuan tantangan ini, hanya metode penilaian dalam daftar di atas yang valid (khususnya, peluang bukan kotak skor yang valid untuk tantangan ini). Skor tersebut harus berupa output sebagai nilai numerik desimalnya, apakah itu bilangan bulat atau representasi stringnya, apa pun. Itu harus segera dikenali sebagai angka. Leading / trailing whitespace baik-baik saja, ini tentang mendapatkan skor dan bukan presentasi.

Kode golf, jadi jawabannya dengan byte paling sedikit dalam bahasa tertentu menang. Celah standar dilarang.

Uji kasus

(Perhatikan bahwa ini semua independen, tantangannya adalah mencetak satu 'dadu' tangan):

in: 1 5 4 3 2
out: 40
in: 1 1 4 3 1
out: 10
in: 2 2 6 5 3
out: 6
in: 2 4 2 4 6
out: 8
in: 1 1 1 1 1
out: 50
in: 5 2 5 3 6
out: 10
in: 1 6 3 4 2
out: 30
in: 1 3 1 1 3
out: 25
in: 6 5 5 6 6
out: 28
in: 1 2 3 5 6
out: 6
brhfl
sumber
3
haruskah kita menutup pertanyaan yang lebih tua? IMO ini adalah pertanyaan yang lebih baik dari itu ...
Giuseppe
5
IMO ini sama sekali bukan duplikat dari skor permainan yahtzee. Ini secara eksplisit menyatakan itu adalah skor tertinggi untuk satu sisi, di mana pertanyaan lain meminta seluruh skor dari daftar gulungan kertas. Terakhir, dan yang paling penting, saya tidak melihat jawaban dari kemungkinan dupe yang bisa digunakan di sini dalam skenario "copy-paste". Silakan pertimbangkan untuk membuka kembali.
DevelopingDeveloper
2
FWIW, saya menyadari pertanyaan lama ketika saya menyatukan ini. Pikiranku menggemakan apa yang dikatakan @DevelopingDeveloper. Setelah melakukan ini sebagai latihan sekali sebelumnya, saya menemukan beberapa peluang menarik untuk mengoptimalkan proses ini. Saya juga hanya berpikir ini adalah tantangan yang lebih rapi.
brhfl
"Kesempatan ketiga belas itu masuk akal dalam pertandingan, tetapi tidak terlalu banyak untuk tantangan ini." Jadi, apakah itu dihitung?
Unihedron

Jawaban:

6

R , 146 141 byte

function(d)max(unique(d<-sort(d))*(g=table(d)),any(g>2)*sum(d),all(2:3%in%g)*25,(s=sum((R=diff(d))==1))<4&all(R<2)*30,(s>3)*40,(0==sd(d))*50)

Cobalah online!

Dikalahkan oleh plannapus

Mengambil input sebagai daftar, dan mengembalikan skor.

ungolfed sedikit:

function(d){
 d <- sort(d)
 u <- unique(d)                  # unique dice
 g <- table(d)                   # table of counts
 Ns <- u*g                       # scores as 1s, 2s, ... etc.
 NKind <- any(g>2)*sum(d)        # 3 or 4 of a kind if any counts are at least 3
 FHouse <- all(2:3%in%g)*25      # full house is 25 if 2 & 3 are in counts
 R <- diff(d)                    # consecutive differences
 s <- sum(R==1)                  # sum of differences equal to 1
 sStraight <- s<4 &              # if the number of 1s is 3 and
               all(R<2)*30       # no consecutive numbers are 2 apart
 bStraight <- (s>3)*40           # all 1s means big straight
 Yahtzee <- sd(d)==0             # sd = 0 means all are equal
 max(Ns,NKind,FHouse,sStraight,bStraight,Yahtzee)
}

Giuseppe
sumber
f(c(1,2,3,5,6))gagal - itu harus menghasilkan 6 dan bukannya menghasilkan 30. Tampaknya ini karena Anda menghitung berapa banyak pasangan (post-sorting) berbeda satu, yang sebenarnya empat untuk urutan di atas, meskipun itu bukan lurus dari empat. Saya pikir saya mengalami ini ketika saya melakukan ini sebagai latihan beberapa waktu lalu, dan saya mungkin harus menambahkan itu sebagai ujian ...
brhfl
@ brhfl ini sudah diperbaiki sekarang.
Giuseppe
5

Python 2 , 187 184 167 165 byte

-17 byte terima kasih kepada @mypetlion
-2 byte terima kasih kepada @chrstphrchvz

def f(d):r=range(1,7);c=d.count;m=map(c,r);s=`m`[1::3];return max([i*c(i)for i in r]+[sum(d)*(max(m)>2),25*(set(m)>{2,3}),30*(4*'1'in s),40*(5*'1'in s),50*(5 in m)])

Cobalah online!

ovs
sumber
4

R, 136 134 byte

function(n,y=table(factor(n,1:6)),z=sum(!diff(diff(sort(n)))))max(1:6*y,c(25,sum(n),10*3:5)[c(all(y<4&y-1),any(y>2),z>1,z>2,any(y>4))])

Golf turun 2 byte berkat @Giuseppe !

Bertakuk,

function(n, #vector of die scores
         y=table(factor(n,1:6)), #Contingency table
         z=sum(!diff(diff(sort(n))))) #Diff of diff of ordered scores
    max(1:6*y,
        c(25,sum(n),10*3:5)*c(all(y<4&y-1), #Full house
                            any(y>2), #3 and 4 of a kind
                            z>1, #Small straight
                            z>2, #Long straight
                            any(y>4))] #Yahtzee

Beberapa kasus uji:

> f=function(n,y=table(factor(n,1:6)),z=sum(!diff(diff(sort(n)))))max(1:6*y,c(25,sum(n),10*3:5)*c(all(y<4&y-1),any(y>2),z>1,z>2,any(y>4)))
> f(c(2,4,2,4,6))
[1] 8
> f(c(1,2,3,5,6))
[1] 6
> f(c(6,5,5,6,6))
[1] 28
> f(c(6,5,3,1,4))
[1] 30
> f(c(6,5,3,2,4))
[1] 40
plannapus
sumber
1
Huh, aku berpikir factorsebentar sebelum teralihkan perhatiannya. Tapi saya pikir jika saya menggunakan pendekatan Anda dengan z( sdalam jawaban saya), saya dapat menambang hingga 134 ...
Giuseppe
Selain itu, Anda dapat menyimpan tiga byte dengan menggunakan all(y<4&y-1)dan menggunakan *alih-alih [, dan mengatur yinline alih-alih sebagai argumen fungsi, dan masih melewati semua kasus uji: Coba online!
Giuseppe
juga, saya merestrukturisasi maxdan saya pikir itu menyelamatkan byte dari pengaturan yinline.
Giuseppe
3

Batch, 359 byte

@echo off
set/at=s=m=r1=r2=r3=r4=r5=r6=0
for %%r in (%*)do set/a"m+=!(m-r%%r),r%%r+=1,t+=%%r,p=s-r%%r*%%r,p&=p>>9,s-=p
goto %m%
:1
if %r1% neq %r6% set s=40&goto g
:2
set/at=r3*r4*(r2*(r1+r5)+r5*r6)
if %t% gtr 0 set s=30
goto g
:3
set/a"s=r1^r2^r3^r4^r5^r6"
if %s%==1 if %t% lss 25 set s=25&goto g
:4
set/as=t
goto g
:5
set s=50
:g
echo %s%

Penjelasan:

@echo off
set/at=s=m=r1=r2=r3=r4=r5=r6=0
for %%r in (%*)do set/a"m+=!(m-r%%r),r%%r+=1,t+=%%r,p=s-r%%r*%%r,p&=p>>9,s-=p
goto %m%

Hitung jumlah dadu untuk setiap angka, plus maksimum, ditambah total semua dadu, ditambah total dadu tertinggi dari nomor yang sama.

:1
if %r1% neq %r6% set s=40&goto g

Jika semua dadu berbeda, ini mungkin lurus panjang, tetapi itu perlu ada tidak 1atau tidak 6.

:2
set/at=r3*r4*(r2*(r1+r5)+r5*r6)
if %t% gtr 0 set s=30
goto g

Jika tidak, atau jika paling banyak dua dadu sama, maka ini bisa menjadi lurus pendek. Setidaknya harus ada a 3dan a 4dan juga kombinasi dari empat angka lainnya.

:3
set/a"s=r1^r2^r3^r4^r5^r6"
if %s%==1 set s=25&goto g

Jika ada tiga dadu yang sama, periksa rumah penuh, karena 3^2==1. Namun, beberapa rumah penuh, seperti 6s dan 5, skor lebih tinggi sebagai 3-of-a-kind.

:4
set/as=t
goto g

Jika tidak, atau jika ada empat yang sama, maka nilai totalnya.

:5
set s=50

Dan jika ada lima yang sama, maka Yahtzee!

:g
echo %s%

Keluarkan skor terbaik.

Neil
sumber
1
Terima kasih telah mengingatkan saya pada potensi perangkap [5,5,6,6,6] -cored-as-full-house - Saya telah menambahkan ini sebagai kasus uji. Saya tahu ada beberapa kasus aneh yang saya lupakan.
brhfl
3

Jelly , 58 byte

ċЀ`Ṁ>2ȧS
ṢI=1Ạµ-ƤẸ,E;ṢI$E$;⁸Lƙ`Ṣ⁼2,3¤a3,5,4,2.Ṁ×⁵»Ç»Sƙ`Ṁ$

Cobalah online!

Erik the Outgolfer
sumber
Ini benar-benar valid, tapi saya penasaran dan tidak tahu Jelly cukup baik untuk suss keluar sendiri ... mengapa rumah penuh kembali 25.0sementara tidak ada kasus lain yang tertinggal .0?
brhfl
@ brhfl Yah, karena disimpulkan sebagai 2.5 × 10 = 25.0(float arithmetic), sedangkan yang lain seperti 30disimpulkan sebagai 3 × 10 = 30(aritmatika integer).
Erik the Outgolfer
2
Terima kasih! Saya tidak benar-benar menjawab pertanyaan saya dengan baik; Saya lebih ingin tahu metode apa yang Anda gunakan untuk mendeteksi rumah penuh yang menghasilkan matematika secara berbeda - tetapi sekarang saya berpikir tentang hal itu, saya kira itu hanya pemain golf untuk melakukan 2,5, 3, 4, 5 * 10 vs 25, 30, 40, 50. Rasanya saya menjawab pertanyaan saya sendiri.
brhfl
@ brhfl Persis, karena × 102 byte, 2.5sama dengan 2 byte 25, dan 3,5,4menyimpan 3 byte lebih 30,50,40, sehingga 3 + 0 - 2 = 1 byte disimpan.
Erik the Outgolfer
2

Perl 6 , 159 byte

->\b{max map {$_(b)},|(1..6).map({*{$_}*$_}),{.kxxv.sum*?.values.grep(*>2)},{25*(6==[*]
.values)},30*?*{3&4&(1&2|2&5|5&6)},40*?*{2&3&4&5&(1|6)},50*(*.keys==1)}

Cobalah online!

Karena input dapat diterima "namun nyaman," fungsi saya menganggapnya sebagai turunan dari Bagkelas, yang merupakan wadah dengan banyak. A Bagjuga merupakan wadah asosiatif; $bag{$key}mengembalikan berapa kali $keyterjadi dalam tas.

Sebagian besar fungsi hanyalah daftar fungsi yang mengevaluasi setiap tangan Yahtzee yang mungkin, mengembalikan skor untuk tangan itu atau nol jika kondisi untuk tangan tersebut tidak terpenuhi.

  • |(1..6).map({ *{$_} * $_ })adalah daftar enam fungsi yang mengevaluasi tangan berdasarkan angka berulang 1-6. Yang terkemuka |meratakan daftar ini ke daftar di sekitarnya.
  • {.kxxv.sum * ?.values.grep(* > 2) }mengevaluasi tangan 3 dan 4 dari jenisnya. .kxxvpada Bagmengembalikan kunci diulang dengan multiplisitas masing-masing, memulihkan daftar asli gulungan mati, dan .sumtentu saja menjumlahkan dadu. Jumlah itu dikalikan dengan nilai boolean ( ?) yang benar jika tas .values(yaitu, multiplisitas) mengandung nilai yang lebih besar dari 2.
  • { 25 * (6 == [*] .values) }mengevaluasi tangan rumah penuh. 25 dikalikan dengan nilai boolean yang benar jika produk dari multiplisitas adalah 6, yang untuk lima dadu hanya dapat terjadi jika satu adalah 3 dan yang lainnya adalah 2.
  • 30 * ?*{ 3 & 4 & (1 & 2 | 2 & 5 | 5 & 6) }mengevaluasi tangan lurus kecil. Itu sebuah WhateverCodefungsi; bintang kedua *adalah Bag. Ekspresi antara kawat gigi adalah persimpangan nilai 3 dan 4, dan baik 1 dan 2, atau 2 dan 5, atau 5 dan 6. Mencari persimpangan ini dalam Baghasil di persimpangan dari multiplisitas yang sesuai. Jika mulitplicities 3 dan 4, dan setidaknya satu dari 1 dan 2, atau 2 dan 5, atau 5 dan 6, bukan nol, persimpangan benar ketika dipaksa ke boolean (dengan ?), dan boolean ini dikalikan dengan 30 untuk mendapatkan skor.
  • 40 * ?*{ 2 & 3 & 4 & 5 & (1 | 6) }sama mengevaluasi tangan lurus besar. Ini lebih sederhana karena dadu harus memasukkan masing-masing angka 2-5, dan 1 atau 6.
  • 50 * (*.keys == 1)mengevaluasi tangan Yahtzee. Ini hanya 50 kali nilai boolean yang benar jika jumlah dadu yang berbeda adalah satu.
Sean
sumber
2

Pip , 65 63 byte

n:_NgM\,6MXn*\,6AL[2<MXn23=JSNn3<Y#MX Jn^0MXn=5]*[$+g25--y*t50]

Mengambil dadu sebagai lima argumen baris perintah. Cobalah online!

Penjelasan + tidak dikelompokkan

(Ini adalah versi aslinya.)

                    g is list of cmdline args; t is 10 (implicit)

Y                   Yank into y:
  _Ng                function that counts occurrences of its argument in g
 M                   mapped to
  \,6                inclusive range from 1 to 6
                    This gives us how many dice are showing each number 1-6

s:                  Assign to s:
  # MX               length of max of
      Jy ^ 0         join y into string and split on zeros
                    This gives us the length of the longest straight

MX                  Max of
   y * \,6           each die frequency in y, times its value
 AL                  to which list append
   [                 this list:
                      3- and 4-of-a-kind:
    MXy > 2 & $+g      If max frequency is 3 or more, sum of g (else 0)
                      Full house:
    23 = J SNy & 25    Sort y and join into string; if it's 000023, 25 (else 0)
                      Straights:
    s > 3 & --s*t      If s is 4 or more, (s-1)*10 (else 0)
                      Yahtzee:
    MXy = 5 & 50       If max frequency is 5, 50 (else 0)
   ]
                    The result of the last expression is autoprinted
DLosc
sumber
1

Ruby , 184 byte

Program lengkap. Untuk membuatnya lebih mudah untuk menguji input, tambahkan $/=' 'di atas untuk membaca dalam format "digit dipisahkan oleh spasi". (191 karakter)

a=$<.map &:to_i
b=a.|c=[]
d=(1..6).map{|x|e=a.count x
c<<x*e
e}
e=a.sum
p !b[1]?50:b[4]&&!(a&[1,6])[1]?40:(1..3).any?{|x|(a&[*x..x+3])[3]}?30:(d-[0,2,3])[0]?d.max>2?e:c.max: [25,e].max

Saya menetapkan penghalang pembatas 200 byte dan saya berhasil menghancurkannya dengan selusin byte tersisa, dengan mudah!

Cobalah online!

Penjelasan

Bukan yang sangat bagus. Semoga Anda memiliki pengetahuan Ruby ~

a=$<.map &:to_i # a: input as [number]*5
b=a.|c=[]       # c: [], b: a.uniq
d=(1..6).map{|x|
    e=a.count x # e: occurrence count in a 
    c<<x*e      # add (number * occurrence count) to c
    e           # return value in d
}
e=a.sum         # e: sum of input
p !b[1] ? 50 :  #   condition to print 50 <= if a.uniq has length 0 (el 1 is nil)
  b[4] &&       #   condition to print 40 <= if a.uniq has length 5 (el 4 exists)
  !(a&[1,6])[1] ? 40 : # <- arr & [mask]  # and a does not have both 1 and 6
  (1..3).any?{|x| # condition to print 30 <= if any of 1..4, 2..5, 3..6
  (a&[*x..x+3])[3]} ? 30 : # [3] to assert entire mask is found in a
  (d-[0,2,3])[0] ? # if, after removing 0 (not found) 2 (a pair) 3 (a triple)
                   # and something is found, this is not full house
  d.max > 2 ?   # is triple / quadruple ?
     e :        # weakly dominating alternatives
     c.max      # choose best by-suit
  : [25,e].max  # choose best by-score
Unihedron
sumber