涂每个薄煎饼


35

您的盘子上有一叠煎饼,上面有一团糖浆,厚得不能从侧面流下来。在每个薄煎饼的两面都至少接触到糖浆之前,您不会高兴地进食,但目前只有顶部薄煎饼的一面可以食用。

您知道糖浆甚至不会浸透一个煎饼,但可以通过两个煎饼之间的面对面接触来无限期地转移糖浆。薄煎饼的表面接触糖浆后,将被视为永远涂有糖浆,并且任何未接触糖浆的表面也将被制成糖浆涂层。也可以将糖浆转移到板的顶侧或从板的顶侧转移。

通过将锅铲插入一个或多个煎饼下面,然后将它们全部翻转,您可以像在煎饼分选过程中一样,用糖浆在煎饼的每个表面上涂抹糖浆。(不幸的是,这把锅铲是抗糖浆的,并且不能通过触摸煎饼表面来帮助分配糖浆。)可悲的是,您无法知道哪些煎饼表面已经接触了糖浆,但是您确实记得已经进行了翻转。

考虑到您过去的情况,您可以确定煎饼是否已经全部涂上糖浆了吗?

挑战

编写一个程序,该程序将薄煎饼的数量取为正整数N,并为迄今为止进行的翻转提供一个正整数列表(所有<= N)。列表中的每个数字代表被翻转的煎饼的数量。如果薄煎饼已经涂好,则输出真值,否则输出假值。(真实/虚假定义

输入应来自stdin或命令行,输出应进入stdout(或最接近的替代品)。如果您的输入需要一些额外的格式,那就很好了:例如,[1, 1, 2, 2]而不是1 1 2 2列表。

例子

假设N = 2,那么我们在盘子上有一叠两个薄煎饼,从顶部的糖浆开始。

如果列表为1 1 2 2,则表示我们...

  • 翻转顶部煎饼-覆盖底部煎饼的上表面
  • 再次翻转顶部-在顶部煎饼的原始底面上涂上一层
  • 同时翻转-涂板
  • 再次翻转两者-在底部薄煎饼的原始底面上涂上一层

由于所有四个面都被覆盖,因此输出将类似于True1

如果列表为1 2 2 1,则表示我们...

  • 翻转顶部煎饼-覆盖底部煎饼的上表面
  • 翻转两个-不涂任何东西
  • 再次翻转两者-无涂层
  • 再次翻转顶部-在顶部煎饼的原始底面上涂上一层

由于接触板的表面仍然不含糖浆,因此输出将类似于False0

笔记

  • 翻转列表可以任意大,可以为空,在这种情况下,输出是虚假的。
  • 该板充当糖浆载体,但是是否被包被都无关紧要。(实际上,任何翻转溶液都会覆盖该盘子,因为必须覆盖它碰到的煎饼面,但无论如何。)
  • 该板不能翻转。
  • 您可以假设这些煎饼是单位圆盘,没有面可言,只有两个相对的面。

计分

这是代码高尔夫球。以字节为单位的最短解决方案获胜。


4
这是一个非常非常好的挑战。;)
Soham Chowdhury 2014年

是一个获取列表并返回布尔值的函数可以吗?
骄傲的haskeller 2014年

9
如果有人可以用这种语言实现它,那么应该有一个好处。
grc

3
@grc现在有这么一个赏金!
2014年

2
这是我在Pancake Stack中的解决方案:Put syrup on the pancakes!;)
rodolphito

Answers:


9

CJam,32 30 29字节

q~2@#2b\{)/(W%)1$0=|@]s:~}/:&

在线尝试。

测试用例

$ cjam pancakes.cjam <<< '2 [1 1 2 2]'; echo
1
$ cjam pancakes.cjam <<< '2 [1 2 2 1]'; echo
0

怎么运行的

q~                            " N, L := eval(input())                                     ";
  2@#2b                       " P := base(2 ** N, 2)                                      ";
       \{                }/   " for F in L:                                               ";
         )/                   "   P := split(P, F + 1)                                    ";
           (W%)               "   T, U, V := P[1:], reverse(P[0])[:-1], reverse(P[-1])[0] ";
               1$0=|          "   V |= U[0]                                               ";
                    @]s:~     "   P := map(eval, str([U, V, T]))                          ";
                           :& " print and(P)                                              ";

17
果酱吗 更像CRup。
IngoBürk2014年

12

Haskell,92 90 86 84 114 110 99 98

完整程序的要求太烦人了。我不知道为什么有人会要求这个。

m(n:s)=all(<1)$foldl(\r@(p:s)n->reverse(take n s)++(p*r!!n):drop n s)[0..n]s
main=readLn>>=print.m

当相邻的煎饼共享同一面时,此解决方案的工作原理是通过一系列面表示煎饼堆。每面都是一个数字,如果面为零,则该面会被覆盖。

运行为:

*Main> main
[2,1,1,2,2]
True

1
+1表示不使用Python 2;)
卡尔文的爱好2014年

@ Calvin'sHobbies哈哈
自豪的haskeller 2014年

恐怕需要完整的程序……
John Dvorak

1
@JanDvorak我没看到……我只是问问题注释中的函数是否还可以。如果不是,我会更改它
骄傲的haskeller 2014年

@proudhaskeller现在OP已明确告知您...我希望很快会有所变化。
John Dvorak 2014年

10

Python,92个字节

我认为这可行:

s=[1]+[0,0]*input()
for f in input():x=f*2;s[0]=s[x]=s[0]|s[x];s[:x]=s[x-1::-1]
print all(s)

它使用一份煎饼面(包括盘子)来记住哪些糖浆涂层。通过反转部分列表来翻转薄煎饼,但是首先将糖浆在顶面和新露出的面之间转移。

用法:

$ python pancakes.py
2
1, 1, 2, 2
True

这是一种非常非常聪明的逆转方法。+1
Soham Chowdhury 2014年

看来您要从“是否一切都是糖浆”检查中排除盘子。需要吗 当所有煎饼面都涂上涂料时,盘子将接触糖浆状的煎饼面,因此盘子也将浆化。
user2357112支持Monica 2014年

@ user2357112是的,您是对的。谢谢!
grc

8

的Python 2:75

grc和feersum解决方案的简化。

n,b=input()
s=[1]+[0]*n
for x in b:s[:x+1]=s[x::-1];s[x]|=s[0]
print all(s)

存储2*n+1煎饼边缘的糖浆状态是多余的,因为接触的边缘总是相同的。而是记住每个n+1煎饼结的状态。这样,糖浆转移便会自动解决。

唯一需要的更新是在x翻转时将糖浆保留在接合处。这是通过将翻转后的糖浆0加入或来完成的x

两次输入不会影响字符数。

s=[1]+[0]*input()
for x in input():s[:x+1]=s[x::-1];s[x]|=s[0]
print all(s)

5

Python 2,93字节

起初我要发布答案,但是后来grc已经在一分钟前发布了一个非常相似的答案。因此,我试图提出一些改进。我唯一能找到的是使用字典表比较而不是all()

编辑:修正了因尝试不同的输入方法而导致的错误,该错误不会改变字符数。

n,F=input()
L=[1]+2*n*[0]
for f in F:f*=2;L[0]=L[f]=L[0]|L[f];L[:f]=L[~-f::-1]
print[1]*2*n<L

样本输入/输出:

2, [1, 1, 2]

 

False

3

APL,77

∧/⊃{x[1]+←⍺⌷x←⍵⋄(⌽⍺↑x),⍺↓x}/(⌽1+⎕),⊂1,⎕⍴0


2

哈斯克尔,129 125

t(m:l)=all(any(<1).(\i->foldr(\n->foldr($)[].map(n%))[i]l))[0..m]
n%i|i>n=(i:)|i<n=(n-i:)|1>0=(n:).(0:)
main=readLn>>=print.t

可能还没有完全打高尔夫球,但它无需操纵一系列涂层面即可工作。取而代之的是,它向后退,以找出给定煎饼的给定面是否曾经接触过开始时顶部的任何东西。 foldr有效地遍历了向后翻转的列表,因此没有reverse

因此,这里是算法:我们在所有相关的边([0..m])上进行映射,并从背面开始,在每一步中生成我们边从其继承糖浆的边的列表:最初,该列表是just [i],但是n每层都有薄煎饼成为[n-i]if i<n[n,0]if i==n[i]if i>n。当且仅当所有翻转后的结果列表包含0any (<1))时,所讨论的面才被覆盖。 all其余的工作,然后main将所有这些转换为可运行的程序。

该程序以stdin形式接受输入[n_pancakes, flip1, flip2, flip3, ...],并以换行符终止。


有趣的方法。
骄傲的haskeller 2014年

怎么样,而不是使用功能代码的继承列表中使用列表,即n%i|i>n=[i]|i<n=[n-i]|0<1=[n,0]和,而不是foldr($)[].map(n%)(=<<).(%),将映射所有继承和加入他们的行列。
自豪的haskeller 2014年

您使我意识到,我可以从一叠开始[0..]并将涂层的煎饼表示为0,而不是将非零的煎饼制成涂层。谢谢!
骄傲的haskeller 2014年
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.