让我们玩Mölkky!


33

莫尔基

莫尔基(Mölkky)是芬兰的投掷游戏。玩家使用木销(也称为“mölkky”)尝试敲打尺寸几乎与投掷销类似的木销,标有从1到12的数字。销的初始位置如下:

   (07)(09)(08)
 (05)(11)(12)(06)
   (03)(10)(04)
     (01)(02)

本说明和以下规则基于Wikipedia

简化的Mölkky规则

  1. 敲击一个图钉会得分该图钉上标记的点数。

  2. 2个或更多的针可计分被打倒的针数(例如,敲3个针可计3分)。

  3. 游戏的目的是精确达到50分。将得分重新设置为25分,得分超过50 分。

  4. 出于这一挑战的目的,我们将假设引脚始终处于上述确切顺序。(在真实的游戏中,每次掷球后,将其重新放置在降落位置上。)

所有其他Mölkky规则都将被忽略,仅考虑一个玩家。

输入项

包含12个布尔值的列表的非空列表。每个布尔值列表都描述了抛出的结果:如果销被撞倒则为1,否则为0。的布尔值在销的确切顺序给出,从左上到右下:798511126310412

输出量

后,所有的分数由抛出应用规则在输入所描述的,计算出的123

详细的例子

让我们考虑以下输入:

// 07 09 08 05 11 12 06 03 10 04 01 02
[ [ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ],  // scores 5 (rule #1)
  [ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ],  // scores 2 (rule #2), total: 7
  [ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 ],  // scores 7, total: 14
  [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ],  // scores 12, total: 26
  [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ],  // scores 12, total: 38
  [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ],  // scores 11, total: 49
  [ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],  // scores 7, total: 56 -> 25 (rule #3)
  [ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ] // scores 2, total: 27

预期输出为27

挑战规则

  • 您可以采用任何合理的格式输入。除了布尔值列表,您还可以使用整数,其中最高有效位是引脚#7,最低有效位是引脚#2。以这种格式,上面的示例将作为传递[ 256, 2304, 127, 64, 64, 128, 2048, 3072 ]
  • 输入列表中可能包含没有任何引脚被打倒的抛出,在这种情况下,分数保持不变。
  • 当分数刚好达到50分时,您无需执行任何特殊操作。但是您可以假设发生这种情况时不会再发生其他抛出。
  • 这是,因此最短的答案以字节为单位。

测试用例

使用整数列表作为输入:

[ 0 ] --> 0
[ 528 ] --> 2
[ 4095 ] --> 12
[ 64, 0, 3208 ] --> 16
[ 16, 1907, 2048 ] --> 18
[ 2023, 2010, 1, 8 ] --> 29
[ 1726, 128, 35, 3136, 1024 ] --> 34
[ 32, 32, 2924, 2, 256, 16 ] --> 28
[ 64, 64, 2434, 1904, 3251, 32, 256 ] --> 25
[ 3659, 2777, 2211, 3957, 64, 2208, 492, 2815 ] --> 25
[ 2047, 1402, 2, 2599, 4, 1024, 2048, 3266 ] --> 50
[ 256, 2304, 127, 64, 64, 128, 2048, 3072 ] --> 27
[ 16, 8, 128, 1, 2048, 1, 2048, 513, 8, 3206 ] --> 30

您可以单击此链接以布尔格式获取这些测试用例。


5
非常酷的挑战,并且对于那些尚未尝试过的人来说,夏天还会是一个很棒的游戏-与烤架一起使用时效果很好。
尼特

2
@Nit谢谢。:)我不得不承认,直到今天我才知道这个游戏。我看到人们今天下午在公园散步时玩它。现在,我想尝试一下。
阿诺尔德

Answers:


7

Python 2中126个111 108 104字节

-3个字节,感谢Jonathan Allan

-4个字节感谢Kaya!

f=lambda A,t=0:t>50and f(A,25)or A and f(A[1:],t-~(sum(A[0])-1or 762447093078/12**A[0].index(1)%12))or t

在线尝试!

定义一个采用1和0的2D数组并返回整数值的递归函数。没什么特别的,我敢肯定有一个简单的解决方案。

说明:

f=lambda A,t=0:    #Define the function, initialising t to 0 on the first iteration
               t>50and f(A,25)      #If t>50 then iterate again with t=25
                              or    #Else
               A and                #If A exists
                     f(A[1:],       #Iterate again without the first list of A
                        t-~         #And add to t, either
                           (sum(A[0])-1   #The sum of all elements if that's not 1
                                         or
                           762447093078/12**A[0].index(1)%12   #Else the appropriate pin value (black magic!)
               or t       #Finally, if A is finished, just return t

(0x103925BA4786>>4*A[0].index(1))%16保存1个角色,对ord('GIHEKLFCJDAB'[A[0].index(1)])-65
卡亚

1
更好一些:762447093078/12**A[0].index(1)%12
卡亚

那东西对我来说就像是黑魔法!谢谢@Kaya!
乔·金

1
那只是以12为底进行编码
恩迪尔

6

果冻,25 个字节

“ñ€bḷ’œ?TLḢṖ?µ€+25¹>?50ɗ/

接受一和零(长度为12)列表的列表的单子链接,该列表返回一个整数。

在线尝试!或查看测试套件(使用OP中提供的整数值)

怎么样?

此解决方案利用œ?给定数字n的,并且列表找到列表的第n 字典排列,其中列表定义了排序顺序。首先,我们需要解决这个问题n

 index:  1  2  3  4  5  6  7  8  9 10 11 12
 value:  7  9  8  5 11 12  6  3 10  4  1  2   (as defined by the question)
     P: 11 12  8 10  4  7  1  3  2  9  5  6   (our permutation lookup array)

...即Pat index i设置为value的原始索引i
P具有的逐一指数438337469(也就是说,如果你把所有12!数字的排列112和它们排序字典顺序,在438337469 P)。
这可以用果冻的Œ¿原子来发现。
这两个步骤都可以使用Jelly程序一次完成ĠŒ¿

“ñ€bḷ’œ?TLḢṖ?µ€+25¹>?50ɗ/ - Link: list of lists of zeros and ones
             µ€           - perform the monadic chain to the left for €ach list:
“ñ€bḷ’                    -   base 250 number = 438337469
      œ?                  -   nth permutation (reorder the 1s and 0s to their pin values)
        T                 -   truthy indices (get the pin values of the 1s)
            ?             -   if...
           Ṗ              -   ...condition: pop (length greater than 1 ?)
         L                -   ...then: length (the number of pins)
          Ḣ               -   ...else: head (the first (& only) pin value)
                        / - reduce the resulting list of integers with:
                       ɗ  -   last three links as a dyad:
               +          -     addition (add the two values together)
                     50   -     literal fifty
                    ?     -     if...
                   >      -     ...condition: greater than (sum greater than 50 ?)
                25        -     ...then: literal twenty-five
                  ¹       -     ...else: identity (do nothing - just yield the sum)

我认为您关于在所有排列中找到合适的词典索引的解释值得一提,是果冻技巧。(上次我必须这样做,我进行了手动二分搜索,对于短序列来说搜索时间并不长,但是有点乏味。^^)
Arnauld

大声笑; 我有完全相同的解决方案,除了两个不同的字节:-> µ-> Ʋ。Jelly确实可以通过将一个niladic链接作为¡s <link>(第一个参数)而受益,除了在程序的开始时,保持特殊的装箱行为。
暴民埃里克(Erik the Outgolfer)'18年

...而且我几乎都用了!
乔纳森·艾伦


4

Pyth,51 48 38字节

VQI>=+Z?qJsN1@.PC"îO&"S12xN1J50=Z25;Z

感谢Jonathan Allan节省了10个字节将输入作为布尔列表的列表。
在这里尝试

说明

VQI>=+Z?qJsN1@.PC"îO&"S12xN1J50=Z25;Z
VQ                                  ;     For each input...
    =+Z                                   ... add to the total...
       ?q sN1                             ... if one pin is down...
             @.PC"îO&"S12xN1              ... the score of that pin.
         J                    J           ... otherwise, the count.
  I>                           50         If we pass 50...
                                 =Z25     ... reset to 25.
                                     Z    Output the total.

不知道如何准确地将其放入程序中,但是如果可以的话,它应该节省6或7个字节...- 7tT8h4hT12h5h2T4h02> .PC"îO&"S12-使用像我的Jelly答案一样的字典排列索引。(该代码在字符串的开头具有不可打印的字节0x0F。)
Jonathan Allan '18年

))可以;
乔纳森·艾伦

4

05AB1E29 28字节

v•CÞŸαLć•13вyOΘmyÏOO25‚¬50›è

在线尝试!

说明

v                              # for each boolean list in input
 •CÞŸαLć•                      # push 13875514324986
         13в                   # convert to a list of base-13 numbers
            yO                 # push the sum of y
              Θm               # truthify and raise the pin-list to this number (0 or 1)
                yÏ             # keep those which are true in the current list
                  OO           # sum the list and the stack
                    25‚        # pair with 25
                       ¬50›    # check if the first number is larger than 50
                           è   # index into the pair with this result

4

Perl 5中74 70个字节

$\+=y/1//-1||/1/g&&(0,6,8,7,4,10,11,5,2,9,3,0,1)[pos];$\=25if++$\>50}{

在线尝试!

将输入作为一系列由换行符分隔的位串。


3

Haskell,96个字节

foldl(\s a->([s..50]++e)!!sum(last$zipWith(*)[7,9,8,5,11,12,6,3,10,4,1,2]a:[a|sum a>1]))0
e=25:e

在线尝试!

包装是聪明的:我本质上索引s+sum(…)到list的位置([0..50]++cycle[25])。但是,一种较短的写方法是在位置处索引并在处sum(…)开始列表s


3

Java的10,131个 130 129字节

m->{int r=0,i,s,t;for(var a:m){for(i=s=t=0;i<12;s+=a[i++])t=a[i]>0?"    \n".charAt(i):t;r+=s<2?t:s;r=r>50?25:r;}return r;}

包含10个不可打印的内容。
输入为零和一的整数矩阵。

通过@JonathanFrech,将-1个字节更改\t为一个实际选项卡(在TIO中有效,在我的本地IDE中不起作用)。

在线尝试。

说明:

m->{                // Method with integer-matrix parameter and integer return-type
  int r=0,          //  Result-integer, starting at 0
      i,s,t;        //  Temp integers
  for(var a:m){     //  Loop over the integer-arrays of the input
    for(i=s=t=0;    //   Reset `i`, `s` and `t` to 0
        i<12;       //   Loop `i` in the range [0,12)
        s+=a[i++])  //    Increase `s` by the current value (0 or 1)
      t=a[i]>0?     //    If the current value is 1:
         "  \n".charAt(i)
                    //     Set `t` to the score at this position
        :t;         //    Else: Leave `t` the same
    r+=s<2?         //   If only a single pin was hit:
        t           //    Add its score `t` to the result
       :            //   Else:
        s;          //    Add the amount of pins `s` to the result
    r=r>50?         //   If the result is now above 50
       25           //    Penalize it back to 25
      :r;}          //   If not, it stays the same
  return r;}        //  Return the result

我认为您可以在中使用实际的制表符来节省一个字节"\t\n"
乔纳森·弗雷希

@JonathanFrech嗯,确实似乎在TIO中工作。在我的IDE中无法在本地工作,但是我猜谁在乎呢?;)
Kevin Cruijssen

如果某处有可行的实现,则允许它。:@
乔纳森·弗雷奇

2

木炭,43字节

≔⁰ηFθ«≧⁺⎇⊖ΣιΣι⌕᧔$|#z⁸Ug⊗”⌕ι¹η¿›η⁵⁰≔²⁵η»Iη

在线尝试!链接是详细版本的代码。将输入作为布尔数组。说明:

≔⁰η

将分数设置为0。

Fθ«

循环抛出。

⎇⊖Σι

引脚数是1吗?

Σι

如果不是,则取针数。

⌕᧔$|#z⁸Ug⊗”⌕ι¹

否则,将引脚的位置转换为一个值。

≧⁺...η

将其添加到乐谱中。

¿›η⁵⁰≔²⁵η

如果分数超过50,则将其设置回25。

»Iη

在所有抛出之后打印最终结果。


2

Haskell,110字节

m s|sum s==1=sum$zipWith(*)[7,9,8,5,11,12,6,3,10,4,1,2]s|1>0=sum s
f l=foldl(\b->c.(b+).m)0l
c a|a>50=25|1>0=a

相同长度:f l=foldl(\b a->last$b+m a:[25|b+m a>50])0l代替fc

在线尝试!


将l参数放到f中3个字节。f=foldl(\b->c.(b+).m)0
aoemica '18年

2

稻壳47 35字节

借助H.PWiz(生成列表编码点的更好方法)可以得到 -12个字节!

F₅0
S?25>50+?←Lε`f`+Nm+3d4652893071

在线尝试!

说明

F₅0  -- input is a list of boolean lists
F    -- left fold by
 ₅   -- | the function flipped (overflowing label) on line 1
  0  -- | with initial value 0

S?25>50+?←Lε`f`+Nm+3d4652893071  -- example inputs: [0,0,0,1,0,0,0,0,0,0,0,0] 0
                     4652893071  -- integer literal: 4652893071
                    d            -- digits: [4,6,5,2,8,9,3,0,7,1]
                 m+3             -- map (+3): [7,9,8,5,11,12,6,3,10,4]
              `+N                -- append natural numbers: [7,9,8,5,11,12,6,3,10,4,1,2,3,...
            `f                   -- filter this list by argument: [5]
        ?  ε                     -- if it's of length 1
         ←                       -- | take first
          L                      -- | else the length
                                 -- : 5
       +                         -- add to argument: 5
 ?  >50                          -- if the value is > 50
  25                             -- | then 25
S                                -- | else the value
                                 -- : 5

怎么m+3d4652893071
H.PWiz

1

红色189172字节

func[b][s: 0 foreach c b[d: 0 foreach e c[if e = 1[d: d + 1]]i: find c 1
n: either i[pick[7 9 8 5 11 12 6 3 10 4 1 2]index? i][0]if 50 < s: s + either 1 < d[d][n][s: 25]]s]

在线尝试!

取消编码的说明:

f: func[b][                                            ; a block of blocks of booleans
    s: 0                                               ; sets sum to 0
    foreach c b[                                       ; for each row of booleans 
        d: 0 foreach e c[if e = 1[d: d + 1]            ; count the number of 1s         
        i: find c 1                                    ; the index of the first 1
        n: either i[pick [7 9 8 5 11 12 6 3 10 4 1 2]  ; if there is 1, pick the number
                    index? i][0]                       ; at the index of 1
                                                       ; otherwise 0  
        if 50 < s: s + either 1 < d[d][n][s: 25]       ; if there is only one 1, add 
                                                       ; the number to the sum, otherwise
                                                       ; the number of 1s 
                                                       ; if the sum > 50, reset it to 25 
    ]
    s                                                  ; return the sum 
]

1

JavaScript(ES6),98个字节

a=>a.map(b=>b.map((m,i)=>(c+=m,d+=m*('0x'+'7985bc63a412'[i])),c=d=0)|(t+=c>1?c:d)>50?t=25:0,t=0)|t

测试用例:


与我的参考实现大小相同(并且非常相似)。:)
Arnauld

啊,酷。只要我能匹配您的代码大小,我都会很高兴。我只有一次可以击败它:)
瑞克·希区柯克

0

Stax,37 个字节

├T<↓"♥←~;▌6»≥øF←î5░U╚_π○Q▒<│∟└ù║pε♀▀æ

运行并调试

在线试用!

说明

F:1"=EA5MQ9-I1%)"!s@c%1={h+}{%+}?c50>{d25}{}?    # Full program, unpacked

F                                                # Loop through every element
 :1                                              # Get indices of truthy elements
   "=EA5MQ9-I1%)"!                               # Push encoded [7,9,8,5,11,12,6,3,10,4,1,2]
                 s@                              # Swap the top 2 elements of stack and get elements at indexes
                   c%1=                          # Copy the top element, get length of array, compare to length of 1
                       {h+}{%+}?                 # If it has length of 1, add the element, otherwise add the length of the array to total
                                 c50>            # Compare total to 50, 
                                     {d25}{}?    # If it is greater, pop it off and push 25 to reset counter, otherwise do nothing

不是我最好的工作,但是它有效。我敢肯定,我想把它缩短一点。


0

Python 2中109个 105 103字节

c=0
for l in input():a=sum(l);c+=int('7985bc63a412'[l.index(1)],16)if a==1else a;c=(25,c)[c<51]
print c

在线尝试!

没有递归函数的替代方法。

-2感谢@Jo King


您可以删除括号字符串文字
乔金
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.