เคลือบทุกแพนเค้ก


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

ฟังก์ชั่นที่รับรายการและคืนค่าบูลีนก็โอเคไหม
ภูมิใจ haskeller

9
ควรมีโบนัสหากใครก็ตามสามารถใช้งานได้ในภาษานี้
grc

3
@grc ตอนนี้มีค่าหัวอยู่แค่นั้น!
งานอดิเรกของ Calvin

2
แก้ปัญหาของฉันใน Pancake Stack Put syrup on the pancakes!
:;

คำตอบ:


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
CJam? เหมือน CRup
Ingo Bürk

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;)
งานอดิเรกของ Calvin

@ Calvin'sHobbies lol
ภูมิใจ haskeller

ฉันเกรงว่าจะต้องมีโปรแกรมเต็มรูปแบบ ...
John Dvorak

1
@JanDvorak ฉันไม่เห็นว่า ... ฉันเพิ่งถามว่าฟังก์ชั่นใช้ได้ในความคิดเห็นของคำถามหรือไม่ ถ้าไม่ใช่ฉันจะเปลี่ยนมัน
ภูมิใจ haskeller

@proudhaskeller ตอนนี้คุณได้รับแจ้งอย่างชัดเจนจาก OP ... ฉันคาดว่าจะมีการเปลี่ยนแปลงในไม่ช้า
John Dvorak

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

ดูเหมือนว่าคุณจะไม่รวมจานจากเช็ค "is Everything syrupy" คุณต้องการที่จะ เมื่อเคลือบหน้าแพนเค้กทุกจานจะสัมผัสใบหน้าแพนเค้กที่เป็นน้ำเชื่อมดังนั้นแผ่นก็จะเป็นน้ำเชื่อมด้วย
user2357112 รองรับโมนิก้า

@ 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ทางแยกเมื่อมีการพลิกตัด นี้จะกระทำโดยไอเอ็นจีหรือน้ำเชื่อมโพสต์พลิกที่เข้ามา0x

การป้อนข้อมูลสองครั้งไม่ส่งผลกระทบต่อจำนวนตัวละคร

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



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

อาจจะยังไม่สมบูรณ์นักกอล์ฟ แต่มันใช้งานได้โดยไม่ต้องจัดการกับรายการด้านเคลือบ แต่กลับใช้วิธีย้อนกลับเพื่อค้นหาว่าด้านที่กำหนดของแพนเค้กที่ให้มาได้สัมผัสกับสิ่งใดก็ตามที่เป็นด้านบนสุดในตอนแรก ได้อย่างมีประสิทธิภาพลัดเลาะรายการพลิกไปข้างหลังจึงไม่มีfoldrreverse

ดังนั้นนี่คืออัลกอริทึม: เราแมปกับทุกด้านที่เกี่ยวข้อง ( [0..m]) และทำรายการด้านที่ด้านข้างของเราสืบทอดน้ำเชื่อมจากในแต่ละขั้นตอนเริ่มจากด้านหลัง: เริ่มแรกรายการเป็นเพียง[i]แต่มีnแพนเค้กพลิกแต่ละรายการ กลายเป็น[n-i]ถ้าi<n, [n,0]ถ้าi==nและถ้า[i] i>nด้านที่มีปัญหาถูกเคลือบถ้าหากรายการผลลัพธ์หลังจากการพลิกทั้งหมดมี0( any (<1)) allทำส่วนที่เหลือและmainแปลงทั้งหมดนี้เป็นโปรแกรมที่รันได้

โปรแกรมรับอินพุตจากstdinในรูปแบบของ[n_pancakes, flip1, flip2, flip3, ...]ยกเลิกโดยบรรทัดใหม่


วิธีการที่น่าสนใจ
ภูมิใจ haskeller

วิธีการเกี่ยวกับแทนที่จะใช้ฟังก์ชั่นในการเขียนรหัสรายการสืบทอดที่จะใช้รายการเช่นn%i|i>n=[i]|i<n=[n-i]|0<1=[n,0]และแทนที่จะเป็นfoldr($)[].map(n%)ได้(=<<).(%)ซึ่งจะแมปการสืบทอดทั้งหมดและเข้าร่วม
ภูมิใจ haskeller

คุณทำให้ฉันรู้ว่าฉันสามารถเริ่มต้นด้วยสแต็คของ[0..]และเป็นตัวแทนของแพนเค้กเคลือบเป็น 0 แทนที่จะทำแพนเค้กที่ไม่ใช่ศูนย์เคลือบ ขอบคุณ!
ภูมิใจ haskeller
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.