Coating Every Pancake

35

5

You have a stack of pancakes on a plate with a glob of syrup on top so thick it can't run down the sides. You won't be happy to eat until both faces of each pancake have at least touched the syrup, but right now only one face of the top pancake has.

You know that the syrup will never soak through even one pancake, but it can be transferred indefinitely via face-to-face contact between two pancakes. Once a face of a pancake has touched syrup it is considered coated in syrup forever, and will make any non-syrup coated face that touches it syrup coated as well. It is possible to transfer syrup to and from the top side of the plate as well.

You proceed to coat every pancake face with syrup by inserting a spatula below one or more pancakes and flipping them all over, exactly as is done in pancake sorting. (Unfortunately this spatula is syrup-resistant, and does not help to distribute the syrup by touching pancake faces.) Sadly you lose track of which pancake faces have touched syrup but you do remember the flips you have made.

Given your past flips can you determine if your pancakes are all coated with syrup yet?

Challenge

Write a program that takes in a positive integer N for the number of pancakes, and a list of positive integers (all <= N) for the flips you have made so far. Each number in the list represents the number of pancakes that were flipped. Output a truthy value if the pancakes are done being coated and a falsy value if not. (truthy/falsy definition)

The input should come from stdin or the command line and the output should go to stdout (or closest alternatives). It's fine if your input needs a little extra formatting: e.g. [1, 1, 2, 2] instead of 1 1 2 2 for the list.

Examples

Assume N = 2, so we have a stack of two pancakes on a plate, starting with the syrup on top.

If the list is 1 1 2 2, this means we...

  • flip the top pancake - coating the upper face of the bottom pancake
  • flip the top again - coating the original bottom face of the top pancake
  • flip both - coating the plate
  • flip both again - coating the original bottom face of the bottom pancake

Since all four faces are coated the output would be something like True or 1.

If the list is 1 2 2 1, this means we...

  • flip the top pancake - coating the upper face of the bottom pancake
  • flip both - coating nothing
  • flip both again - coating nothing
  • flip the top again - coating the original bottom face of the top pancake

Since the face touching the plate is still syrup-free the output would be something like False or 0.

Notes

  • The flip list may be arbitrarily large and can be empty, in which case the output is falsy.
  • The plate acts as a syrup-carrier but it doesn't matter if it gets coated or not. (In fact any flip solution will coat the plate because the pancake face it touches must be coated, but regardless.)
  • The plate cannot be flipped.
  • You can assume these pancakes are unit disks with no sides to speak of, only two opposite faces.

Scoring

This is code-golf. The shortest solution in bytes wins.

Calvin's Hobbies

Posted 2014-09-27T08:13:41.183

Reputation: 84 000

4This is a very, very nice challenge. ;) – Soham Chowdhury – 2014-09-27T09:13:19.023

is a function that gets a list and returns a boolean is okay? – proud haskeller – 2014-09-27T10:43:08.330

@proudhaskeller Not if your language has support for stdin/command line. – Calvin's Hobbies – 2014-09-27T10:46:53.800

"The top side of the plate can also be syrup coated" is ambiguous. I think it would be clearer as "It is possible to transfer syrup to and from the top side of the plate". – Peter Taylor – 2014-09-27T11:21:24.830

9

There should be a bonus if anyone can implement it in this language.

– grc – 2014-09-27T12:25:20.943

3@grc There is now a bounty for just that! – Calvin's Hobbies – 2014-10-01T04:00:00.077

@Calvin'sHobbies Awesome! It looks hard though... – grc – 2014-10-01T05:48:07.950

Is there an upper limit for the number of pancakes? – TwiNight – 2014-10-03T15:15:06.580

@TwiNight No, except for some reasonable int max value like 2^16. – Calvin's Hobbies – 2014-10-03T16:31:39.957

I did try to do this in Pancake Stack. It is way too hard. However, I feel honored to have my ugly, quickly thrown together interpreter being used (hopefully). – Justin – 2014-10-07T06:31:19.563

2Heres my solution in Pancake Stack: Put syrup on the pancakes! ;) – rodolphito – 2014-10-07T07:20:30.983

If I have understood that correctly, a working Pancake Stack solution should be about 300 lines long. It has neither arrays nor 3-variable rotations. – jimmy23013 – 2014-10-09T11:29:54.857

Answers

9

CJam, 32 30 29 bytes

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

Try it online.

Test cases

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

How it works

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)                                              ";

Dennis

Posted 2014-09-27T08:13:41.183

Reputation: 196 637

17CJam? More like CRup. – Ingo Bürk – 2014-09-29T05:41:57.920

12

Haskell, 92 90 86 84 114 110 99 98

the requirement of a full program is so annoying. I wonder why would anyone require this.

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

this solution works by representing the pile of pancakes by a list of the sides, when adjacent pancakes share the same side. every side is a number, and a side is coated if it has a zero value.

run as:

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

proud haskeller

Posted 2014-09-27T08:13:41.183

Reputation: 5 866

1+1 for not using Python 2 ;) – Calvin's Hobbies – 2014-09-27T10:23:27.813

@Calvin'sHobbies lol – proud haskeller – 2014-09-27T10:23:55.480

I'm afraid a full program is required... – John Dvorak – 2014-09-27T10:40:08.797

1@JanDvorak I didn't see that... I just asked if a function is okay in the comments of the question. if it isn't, i'll change it – proud haskeller – 2014-09-27T10:44:17.370

@proudhaskeller now you have been told explicitly by OP... I expect a change soon. – John Dvorak – 2014-09-27T10:52:28.223

@JanDvorak of course – proud haskeller – 2014-09-27T10:54:35.880

It's possible to tweak the input format, meaning you can read it as a whole without splitting into words. Another hint of mine is that using interact isn't always beneficial ;-) – John Dvorak – 2014-09-27T11:15:29.613

@JanDvorak thanks for the hints! I never thought of giving hints instead of giving straightforward tips. I used your first tip, but I still use interact. is there any better than this? – proud haskeller – 2014-09-27T12:16:24.073

Here's another hint before I get home: there's a function that combines half of interact with read, and there's a function that combines half of interact with show. Can you guess their signatures? The rest is Hoogle. – John Dvorak – 2014-09-27T13:49:42.100

@JanDvorak thanks for the hints! is this what you thought of? – proud haskeller – 2014-09-27T14:47:01.303

10

Python, 92 bytes

I think this works:

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)

It uses a list of pancake faces (plate included) to remember which are coated with syrup. Pancakes are flipped by reversing part of the list, but any syrup is first transferred between the top face and the newly revealed face.

Usage:

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

grc

Posted 2014-09-27T08:13:41.183

Reputation: 18 565

That is a really, really clever way to reverse. +1 – Soham Chowdhury – 2014-09-27T09:32:00.310

It looks like you're excluding the plate from the "is everything syrupy" check. Do you need to? When all pancake faces are coated, the plate will be touching a syrupy pancake face, so the plate will be syrupy too. – user2357112 supports Monica – 2014-09-28T01:52:24.237

@user2357112 Yes, you're right. Thanks! – grc – 2014-09-28T02:11:44.307

8

Python 2: 75

A simplification of grc's and feersum's solution.

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

Storing the syrup state of 2*n+1 pancake edges is redundant because touching edges are always the same. This instead remembers the state of each of n+1 pancake junctions. That way, syrup transfer is automatically accounted for.

The only update needed is to preserve the syrup at the x junction when a flip cuts it. This is done by or-ing the post-flip syrup at 0 into x.

Taking input twice doesn't affect the character count.

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

xnor

Posted 2014-09-27T08:13:41.183

Reputation: 115 687

5

Python 2, 93 bytes

At first I was going to post my answer, but then grc had already posted a very similar one a minute before. So I tried to come up with some improvements. The only one I could find is to use a lexicographic list comparison instead of all().

Edit: Fixed a mistake introduced by unsuccessfully trying different input methods which doesn't change character count.

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

Sample input/output:

2, [1, 1, 2]

 

False

feersum

Posted 2014-09-27T08:13:41.183

Reputation: 29 566

3

APL, 77

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

TwiNight

Posted 2014-09-27T08:13:41.183

Reputation: 4 187

2

Python 2, 107

d=[1]+[0,0]*input()
for i in input():n=2*i;d[:n]=reversed(d[:n]);d[n]=d[n-1]=d[n]|d[n-1]
print(all(d[:-1]))

Soham Chowdhury

Posted 2014-09-27T08:13:41.183

Reputation: 1 449

2

Haskell, 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

Probably not completely golfed yet, but it works without manipulating a list of coated sides. Instead, it works its way backwards to figure out whether a given side of a given pancake has ever come in contact with anything that was the top side at the beginning. foldr effectively traverses the list of flips backwards, therefore there is no reverse.

So here is the algorithm: We map over all relevant sides ([0..m]) and make a list of sides that our side inherits syrup from at each step, starting from the back: initially the list is just [i], but with a flip of n pancakes, each entry becomes [n-i] if i<n, [n,0] if i==n, and [i] if i>n. The side in question has been coated if and only if the resulting list after all flips contains a 0 (any (<1)). all does the rest, and main converts all this into a runnable program.

The program takes its input from stdin in the form of [n_pancakes, flip1, flip2, flip3, ...], terminated by a newline.

TheSpanishInquisition

Posted 2014-09-27T08:13:41.183

Reputation: 421

interesting approach. – proud haskeller – 2014-10-04T09:53:27.930

how about instead of using functions to code the inherits list to use lists, i.e. n%i|i>n=[i]|i<n=[n-i]|0<1=[n,0] and instead of foldr($)[].map(n%) have (=<<).(%), that will map all inherits and join them. – proud haskeller – 2014-10-04T10:02:41.453

you made me realize I can start with a stack of [0..] and represent a coated pancake as 0 instead of making nonzero pancakes coated. thanks! – proud haskeller – 2014-10-04T10:08:04.113