Winnable纸牌Mancala板


10

曼卡拉(Mancala)是一系列棋盘游戏的名称,通常涉及一系列杯子,杯子中装有玩家操纵的珠子。该挑战将为游戏的单人纸牌变体使用特定的规则集。

该板的一端是一个“篮子”,然后是无数个杯子(从1开始编号)。某些杯子中会有一些珠子。如果n杯子中恰好有n珠子,则可以从中“撒出”珠子。播种是指将所有n珠子从杯子中取出,然后一次将它们在每个杯子中​​朝篮子放置。最后的珠子将进入篮子。当棋盘上的所有珠子都在篮子中时,玩家获胜。

显然,有许多棋盘无法胜出,例如,第二个杯子中恰好有一个珠子。没有合法玩法,因为不能播种所有带有0个珠子的杯子,并且第二个杯子没有要播种的珠子。显然这没什么好玩的,所以您的任务是创建可赢得的棋盘。

任务

给定表示多个珠子的正整数,将输出一个非负整数的列表,该非负整数表示应放入每个杯子中​​以制成如上所述的可取下的棋子的珠子的数量。此列表不应包含任何尾随零。

对于任何给定数量的珠子,始终只有一种可胜任的棋盘配置。

示范

这是演示如何玩可赢局并输入4的示例[0, 1, 3]。可赢局是。我们从唯一可用的举动开始,从第三个杯子中播出珠子,得到[1, 2, 0]。现在我们实际上有一个选择,但是唯一正确的选择是播下第一个杯子,得到:[0, 2, 0]。然后,我们播种第二个杯子[1, 0, 0],最后我们再次播种第一个杯子,以得到所有空杯子。

测试用例:

1 => [1]
2 => [0, 2]
3 => [1, 2]
4 => [0, 1, 3]
5 => [1, 1, 3]
6 => [0, 0, 2, 4]
7 => [1, 0, 2, 4]
8 => [0, 2, 2, 4]
9 => [1, 2, 2, 4]
10 => [0, 1, 1, 3, 5]
11 => [1, 1, 1, 3, 5]
12 => [0, 0, 0, 2, 4, 6]
13 => [1, 0, 0, 2, 4, 6]
14 => [0, 2, 0, 2, 4, 6]
15 => [1, 2, 0, 2, 4, 6]
16 => [0, 1, 3, 2, 4, 6]
17 => [1, 1, 3, 2, 4, 6]
18 => [0, 0, 2, 1, 3, 5, 7]
19 => [1, 0, 2, 1, 3, 5, 7]
20 => [0, 2, 2, 1, 3, 5, 7]

非常感谢PeterTaylor提出了生成测试用例的程序!


Answers:


5

CJam(21字节)

M{_0+0#_Wa*\)+.+}ri*`

在线演示

说明

我独立地得出了本文中提到的“播放”技术。通过归纳证明,对于给定数量的珠子,只有一个获胜板。

基本情况:有0个珠子,唯一的胜局是空的。

归纳步骤:如果我们从杯子播种,k则在下一步移动时杯子k将是空的,靠近篮子的每个杯子将至少包含一个珠子。因此nn-1通过查找编号最小的空杯子,从篮子中取出一个珠子,从该空杯子下面的每个杯子中​​取出一个珠子,然后将它们全部放入空杯子中,我们可以从带珠子的中奖板上找到独特的带珠子的中奖板。

解剖

M           e# Start with an empty board
{           e# Loop
  _0+0#     e#   Find position of first 0 (appending to ensure that there is one)
  _Wa*      e#   Make array of that many [-1]s
  \)+       e#   Append the index plus 1 (since board is 1-indexed)
  .+        e#   Pointwise addition
}
ri*         e# Read integer from stdin and execute loop that many times
`           e# Format for display

9

Python,42 41字节

m=lambda n,i=2:n*[1]and[n%i]+m(n-n%i,i+1)

4

JavaScript(ES6),63 37字节

f=(n,d=2)=>n?[n%d,...f(n-n%d,d+1)]:[]

@orlp的Python答案的端口。说明:考虑i第th杯和更高杯中珠子的总数。这些杯子之一的每次打法都会i从总数中除去珠子。(例如,如果i为3,而您从第五个杯子开始比赛,则将那个杯子中的磁珠数量减少5个,但同时在第四个和第三个杯子中都加一个。)因此,总数必须为倍数的i。现在,该i-1杯子不能容纳i更多的珠子,因此,要使杯子离开i整数倍,必须以模数包含其余的珠子i

先前的解释(来自@xnor的链接):天真的方法是“反向播放”技术。这样做是为了使比赛清空杯子,因此反向比赛会从每个杯子中​​收集一个珠子,然后将它们放入第一个空杯子中,就像这样(63个字节):

f=n=>n?[...a=f(n-1),0].some((m,i)=>(m?a[i]--:a[i]=i+1)>m)&&a:[]

现在,只考虑第一个i杯子。如果其中之一是空的,则反向游戏将增加1这些杯子中的珠子总数,而如果其中一个都不是空的,则反向游戏将从i总数中减去,但这等同于加1i+1n反向播放后,第一个i杯子中的珠子总数将等于ni+1,或者换句话说,i第一个杯子中的珠子数将等于n减去前面杯子中的珠子总数,以模为模i+1。现在i要使第一个杯子可玩,珠子的数量不能超过i,所以实际上它将等于模数的剩余珠子数量i+1。(请注意,d=i+1因为它使用的字节数更少,所以我使用它。)


您忘记使用@orlp的解决方案在版本中分配功能,从而阻止了递归工作。同样关于该解决方案,数组连接+在ES6中不是问题吗?
价值墨水

@KevinLau糟糕,在麻烦将其也包括在字节数之后!但是,否,+是字符串连接,除非两个参数都是数字或布尔值,在这种情况下,它是加法。幸运的是,数组理解使任意串联变得更容易。
尼尔,

2

Ruby,36个字节

@orlp的答案的端口,因为它太天才了,让我无法想到更好的方法。

m=->n,i=2{n>0?[n%i]+m[n-n%i,i+1]:[]}
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.