Лучший счет Yahtzee


26

Yahtzee - игра, в которую играют пять шестигранных кубиков и таблица результатов с тринадцатью различными полями для заполнения счета. У каждого окна есть свои правила подсчета очков:

  • 1s, 2s, 3s, 4s, 5s, 6s все очки очков равны сумме соответствующих костей (то есть бросок [3, 2, 3, 1, 5], набранный как 3s, будет награжден 6 очками: 3 за каждые 3).
  • Очки «три в своем роде» и «четыре в своем роде» (как они звучат, три или четыре кубика бросили одинаковые) дают очки, равные сумме всех пяти кубиков.
  • Фулл-хаус (две кости показывают одно значение, остальные три показывают другое) набирает 25 очков
  • Маленькая прямая (четыре последовательных значения) набирает 30 баллов
  • Большая прямая (все последовательные значения) набирает 40 баллов
  • Yahtzee (все кости имеют одинаковое значение) набирает 50 очков

Тринадцатое (шанс) имеет смысл в игре, но не так много для этой задачи; Кроме того, в игре есть бонусы для дополнительных Yahtzees, которые здесь не имеют смысла. Потому что проблема ...

Учитывая пять кубиков в качестве входных данных (пять целых чисел 1-6, однако ввод удобен, вы можете предположить, что ввод всегда действителен), выведите наивысшую возможную оценку для этой «руки». Для целей этого задания действительными являются только методы оценки, приведенные в приведенном выше списке (в частности, шанс не является действительным полем оценки для этого задания ). Счет должен быть выведен как его десятичное числовое значение, будь то целое число или его строковое представление, что угодно. Он должен быть сразу узнаваем как число. Лидирующие / конечные пробелы в порядке, речь идет о получении оценки, а не презентации.

Код гольф, поэтому ответ с наименьшим количеством байтов на данном языке выигрывает. Стандартные лазейки запрещены.

Контрольные примеры

(Обратите внимание, что все они независимы, задача состоит в том, чтобы выиграть одну «руку» игры в кости):

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

3
мы должны закрыть старый вопрос вместо этого? ИМО, это лучший вопрос, чем этот ...
Джузеппе

5
IMO, это совсем не дубликат счета в игре yahtzee. Это прямо говорит о том, что это наивысшая оценка за одну руку, когда другой вопрос запрашивает полный счет из списка бросков кубика. Наконец, и самое главное, я не вижу никаких ответов от возможного дублирования, которое можно было бы использовать здесь в сценарии «копирование-вставка». Пожалуйста, рассмотрите возможность открытия.
DevelopingDeveloper


2
FWIW, я знал о старом вопросе, когда я собрал этот вопрос. Мои мысли повторили то, что сказал @DevelopingDeveloper. Проделав это как упражнение однажды, я нашел несколько интересных возможностей для оптимизации этого процесса. Я также просто думаю, что это более аккуратный вызов.
brhfl

«Тринадцатое (шанс) имеет смысл в игре, но не так много для этого вызова». Так это считается?
Unihedron

Ответы:


6

R , 146 141 байт

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)

Попробуйте онлайн!

Обойден планнапусом

Принимает ввод в виде списка и возвращает счет.

немного разгадал

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


f(c(1,2,3,5,6))терпит неудачу - это должно дать 6 и вместо этого дает 30. Кажется, это потому, что вы подсчитываете, сколько пар (после сортировки) различаются на единицу, что на самом деле четыре для вышеуказанной последовательности, даже если это не является прямой четырех. Я думаю, что столкнулся с этим, когда некоторое время назад выполнил это как упражнение, и я, вероятно, должен добавить это в качестве контрольного примера ...
brhfl

@brhfl это сейчас исправлено.
Джузеппе


4

R 136 134 байта

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

Гольф на 2 байта благодаря @Giuseppe !

отступ,

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

Несколько тестовых случаев:

> 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

1
Да, я задумался factorна горячую секунду, прежде чем отвлекся. Но я думаю, что если я буду использовать ваш подход с z( sв моем ответе), я смогу
Джузеппе

Кроме того, вы можете сохранить три байта, используя all(y<4&y-1)и используя *вместо [, и устанавливая yinline, а не как аргумент функции, и он по-прежнему проходит все тестовые случаи: попробуйте онлайн!
Джузеппе

Кроме того, я реструктурировал, maxи я думаю, что это спасло байт от установки yinline.
Джузеппе

3

Пакетный, 359 байт

@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%

Объяснение:

@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

Если все кости разные, это может быть длинная прямая, но это должно быть либо нет, 1либо нет 6.

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

В противном случае, или если не более двух кубиков одинаковы, это может быть короткая стрита. Должно быть как минимум a 3и a, 4а также комбинация других четырех чисел.

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

Если есть три кубика то же самое, проверить полный дом, так как 3^2==1. Тем не менее, некоторые фулл-хаусы, такие как 6s и 5s, получают более высокие оценки как 3 в своем роде.

:4
set/as=t
goto g

В противном случае, или если есть четыре одинаковых, то наберите общий результат.

:5
set s=50

А если есть пять одинаковых, то Яхтзе!

:g
echo %s%

Выведите лучший результат.


1
Спасибо, что напомнили мне о потенциальной ловушке [5,5,6,6,6] с оценкой как фулл-хаус - я добавил это в качестве контрольного примера. Я знал, что было несколько странных случаев, которые я забыл.
brhfl

3

Желе , 58 байт

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

Попробуйте онлайн!


Это совершенно верно, но мне любопытно, и я не знаю достаточно хорошо Желе, чтобы разобраться в этом самостоятельно ... почему фулл-хаус возвращается, в 25.0то время как ни в одном другом случае нет следов .0?
brhfl

@brhfl Ну, потому что он выводится как 2.5 × 10 = 25.0(арифметика с плавающей точкой), а другие, такие как 30выводятся как 3 × 10 = 30(целочисленная арифметика).
Эрик Outgolfer

2
Благодарность! Я не очень хорошо сформулировал свой вопрос; Мне было более любопытно, какой метод вы используете, чтобы обнаружить фулл-хаус, который приводит к другому математике, но теперь, когда я думаю об этом, я предполагаю, что это просто гольф, чтобы сделать 2,5, 3, 4, 5 * 10 против 25, 30, 40, 50. Думаю, я ответил на свой вопрос.
brhfl

@brhfl Точно, так × 10как 2 байта, 2.52 байта, как и 25, и 3,5,4сохраняет 3 байта больше 30,50,40, так что 3 + 0 - 2 = 1 байт сохранен.
Эрик Outgolfer

2

Perl 6 , 159 байт

->\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)}

Попробуйте онлайн!

Поскольку входные данные могут быть приняты «как бы это ни было удобно», моя функция воспринимает их как экземпляр Bagкласса, который является контейнером с множественностью. А Bagтакже является ассоциативным контейнером; $bag{$key}возвращает, сколько раз $keyвстречается в сумке.

Большая часть функции - это просто список функций, которые оценивают каждую возможную руку Яхтзе, возвращая счет для этой руки или ноль, если условия для руки не выполнены.

  • |(1..6).map({ *{$_} * $_ })это список из шести функций, которые оценивают руки на основе повторяющихся серий чисел 1-6. Ведущий |сводит этот список в окружающий список.
  • {.kxxv.sum * ?.values.grep(* > 2) }оценивает 3-х и 4-х в своем роде руки. .kxxvпри Bagвозврате возвращает ключи, повторенные с кратностью каждого, восстанавливая исходный список бросков кубика и, .sumконечно, суммируя кубик. Эта сумма умножается на логическое значение ( ?), которое истинно, если в сумке .values(то есть, кратности) содержится значение больше 2.
  • { 25 * (6 == [*] .values) }оценивает фулл-хаус. 25 умножается на логическое значение, которое истинно, если произведение кратностей равно 6, что для пяти кубиков может произойти, только если один равен 3, а другой равен 2.
  • 30 * ?*{ 3 & 4 & (1 & 2 | 2 & 5 | 5 & 6) }оценивает маленькую прямую руку. Это WhateverCodeфункция; вторая звезда *это Bag. Выражение между фигурными скобками - это соединение значений 3 и 4 и либо 1 и 2, либо 2 и 5, либо 5 и 6. Поиск этого соединения в Bagрезультатах приводит к соединению соответствующих кратностей. Если кратности 3 и 4 и, по крайней мере, одно из 1 и 2, или 2 и 5, или 5 и 6, отличны от нуля, соединение является истинным, когда приведено к логическому (с ?), и этот логический коэффициент умножается на 30 чтобы получить счет.
  • 40 * ?*{ 2 & 3 & 4 & 5 & (1 | 6) }Аналогично оценивает большую прямую руку. Это проще, потому что кости должны включать каждое из чисел 2-5, а также 1 или 6.
  • 50 * (*.keys == 1)оценивает руку Яхтзе. Это просто 50-кратное логическое значение, которое истинно, если число различных кубиков равно единице.

2

Пип , 65 63 байта

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

Принимает кости как пять аргументов командной строки. Попробуйте онлайн!

Ungolfed + объяснение

(Это оригинальная версия.)

                    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

1

Рубин , 184 байта

Полная программа. Чтобы упростить тестирование ввода, добавьте $/=' 'сверху, чтобы читать в формате «цифры, разделенные пробелами». (191 символ)

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

Я поставил перед собой барьер в 200 байт, и мне удалось с легкостью его уничтожить, оставив дюжину байтов!

Попробуйте онлайн!

объяснение

Не очень хороший, хотя. Надеюсь, у тебя есть знания по 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.