llhuii ส่งผลให้ Evil Numbers ใน Python ขนาด 42 ไบท์ได้อย่างไร?


71

นี่คือคำถามที่เคล็ดลับสำหรับการเล่นกอล์ฟในหลามเกี่ยวกับเบอร์ Evilคำถามเกี่ยวกับความโกลาหลกอล์ฟ

จำนวนนั้นเป็นสิ่งที่ชั่วร้ายถ้าการขยายแบบไบนารีนั้นมีจำนวนเท่ากับ 1 ความท้าทายคือการพิมพ์ตัวเลขความชั่วร้าย 400 หมายเลขแรก0,3,5,...,795,797,798ต่อหนึ่งบรรทัด

การส่ง Python 2นำโดย llhuii ด้วยโซลูชันขนาด 42 ไบต์ สิ่งที่ดีที่สุดถัดไปคือ 46 ไบต์โดย mitchs ตามด้วยการส่ง 47- ห้าไบต์ ดูเหมือนว่า llhuii ได้ค้นพบบางสิ่งที่มหัศจรรย์อย่างแท้จริงซึ่งทำให้นักกอล์ฟ Python แข็งแกร่งจำนวนมากมานานกว่า 2 ปี การประหยัด 4 หรือ 5 ไบต์มีขนาดใหญ่มากสำหรับการเล่นกอล์ฟระยะสั้น

ตารางคะแนนของ Python 2

ฉันยังอยู่ที่ 47 ไบต์ ฉันหวังว่าเราจะสามารถไขปริศนานี้เป็นชุมชนได้ หากเราได้รับคำตอบร่วมกันฉันจะส่งมันภายใต้ชื่อของทุกคนที่ร่วมให้ข้อมูล คำตอบสำหรับคำถามนี้อาจเป็นโค้ดหรือแนวคิดใหม่หรือการวิเคราะห์ หากคุณเป็น llhuii โปรดอย่าทำลายมันสำหรับเรา

แม้ว่าการส่งจะไม่ถูกเปิดเผยเนื่องจากปัญหานี้ไม่มีที่สิ้นสุด แต่เราได้รับโอกาสในการขายจำนวนหนึ่ง การส่งผลงานชนะเลิศนั้นใช้เวลา 0.1699 วินาทีในการวิ่งนานกว่าระยะเวลาอื่น ๆ ซึ่งแนะนำวิธีการที่ไม่มีประสิทธิภาพ จากสถิติไบต์ของอักขระ 42 ตัว 23 ตัวคือตัวอักษร[0-9A-Za-z]และตัวเลขและ 19 เป็นสัญลักษณ์ ASCII ซึ่งหมายความว่าไม่มีช่องว่างในโซลูชันของ llhuii

คุณสามารถทดสอบรหัสของคุณในหน้าปัญหาเลือก Python จากดรอปดาวน์ภาษาหรืออัปโหลด.pyไฟล์ โปรดทราบว่า:

  • ใช้ Python 2.7
  • รหัสของคุณจะต้องเป็นโปรแกรมเต็มรูปแบบที่พิมพ์
  • ไม่มีอินพุตสำหรับปัญหานี้เช่น
  • โปรแกรมของคุณจะต้องพิมพ์ค่า 400 ตามที่กำหนดแม้ว่ามันจะทำลายค่าที่ใหญ่กว่า
  • โปรแกรมมี 2 วินาทีในการทำงาน
  • โปรแกรมอาจจบลงด้วยข้อผิดพลาด
  • คุณสามารถใช้exec; "exec ถูกปฏิเสธ" หมายถึง shell exec

2
นอกจากนี้ยังอาจมีค่าที่จะต้องทราบว่าลำดับนี้คือ "ดัชนีของศูนย์ในลำดับ Thue-Morse A010060" (ที่มา: oeis )
Conor O'Brien

คำตอบ:


51

นี่ไม่ใช่วิธีเดียวกับ llhuii แต่ก็มีความยาว 42 ไบต์เช่นกัน

n=0;exec'print n;n^=(n^n+2)%3/2;n+=2;'*400

ลองออนไลน์!

ขอบคุณ @JonathanFrech ตอนนี้เราอยู่ที่ 40 ไบต์

n=0;exec'print n;n=n+2^(n^n+2)/2%3;'*400

ลองออนไลน์!

มีอีกหนึ่งไบต์ที่จะถูกบันทึกรวมเป็น 39

n=0;exec'print n;n=n+2^-(n^n+2)%3;'*400

ลองออนไลน์!


1
จากความอยากรู้คุณรู้ได้อย่างไรว่ารุ่น 42- ไบต์นั้นไม่เหมือนกับ llhuii (ฉันไม่เคยเข้าร่วม Anarchy Golf)
Luis Mendo

6
@LuisMendo แท็บสถิติแสดงรายการตัวอักษรและตัวเลข 23 ไบต์และ 19 สัญลักษณ์ ASCII ดังนั้นจึงไม่มีช่องว่าง เว้นแต่ llhuii เขียนprint+nวิธีการแก้ปัญหาของพวกเขาต้องแตกต่างจากเหมือง
เดนนิส

อ้าดังนั้นคุณสามารถรับข้อมูลบางอย่างแม้ว่าคุณจะไม่ทราบรหัส เยี่ยมมาก ขอบคุณ!
Luis Mendo

คุณคิดว่ามีโอกาสสำหรับ 38 หรือไม่? ในทางทฤษฎีมีระดับอิสระในการลบ-เครื่องหมายโดยขยับด้วยprint~nหรือprint-nใช้และ&หรือ~แม้ว่าฉันจะไม่ได้ทำงานอะไรเลย นอกจากนี้ยังn=0;exec"print n;d=n^n+2;n^=d^-d%3;"*400สวย แต่มี 40 ไบต์
xnor

print-nดูเหมือนว่าไม่น่าเป็นไม่มีความสัมพันธ์ง่ายระหว่างชุดบิตและn ฟังดูมีแนวโน้มมากกว่าในทางทฤษฎี แต่ฉันไม่สามารถรับได้ต่ำกว่า 40 ไบต์ด้วยวิธีการนี้ -nprint~n
เดนนิส

28

รับ 39 ไบต์

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

n=0
exec"print n;n=n+2^-(n+2^n)%3;"*400

เขียนนี้น้อย golfed และมี parens เพิ่มเติมดูเหมือนว่า:

n=0
for _ in range(400):
  print n
  n=(n+2)^(-((n+2)^n))%3

ความเท่าเทียมกันบิต

เราเริ่มต้นด้วยแนวคิดจากโซลูชัน 47 ไบต์ของฉันเพื่อแสดงตัวเลขทั้งหมดในแบบฟอร์มn=2*k+bที่kนับขึ้น0,1,...,399และbเป็นบิตพาริตีที่ทำให้จำนวนโดยรวมของ 1 เป็นเท่ากัน

ลองเขียนpar(x)สำหรับความเท่าเทียมกันบิตของxที่เป็นแฮคเกอร์ ( ^) xทั้งหมดของบิตใน นี่คือ 0 ถ้ามีจำนวน 1 บิต (เลขเป็นชั่ว) และ 1 ถ้ามีเลข 1 บิตคี่ สำหรับn=2*k+bเรามีpar(n) = par(k)^bเพื่อให้บรรลุความชั่วร้ายที่par(n)==0เราต้องการb=par(k)คือบิตสุดท้ายของnการเป็นบิตพาริตี้ของบิตก่อนหน้านี้

ความพยายามครั้งแรกของฉันในการเล่นกอล์ฟอยู่บนการแสดงpar(k), เป็นครั้งแรกที่ได้โดยตรงด้วยbin(k).count('1')%2และจากนั้นมีการจัดการบิต

อัพเดตพาริตี

ถึงกระนั้นก็ไม่ได้มีการแสดงออกสั้น ๆ แต่มันช่วยให้ตระหนักว่ามีข้อมูลมากขึ้นที่จะทำงานกับ แทนที่จะคำนวณบิตพาริตี้ของตัวเลขปัจจุบัน

k  ---->  par(k)

เราสามารถอัปเดตความเท่าเทียมกันบิตในขณะที่เราเพิ่มไปkk+1

k   ---->  par(k)
      |
      v
k+1 ---->  par(k+1)

นั่นคือเนื่องจากเรากำลังนับk=0,1,2,...เราเพียงแค่ต้องรักษาบิตพาริตี้ปัจจุบันแทนที่จะคำนวณจากรอยขีดข่วนในแต่ละครั้ง การปรับปรุงความเท่าเทียมกันของบิตpar(k+1)^par(k)คือความเท่าเทียมกันของจำนวนบิตที่พลิกจากkไปk+1เป็นpar((k+1)^k)กล่าวคือ

par(k+1) ^ par(k) = par((k+1)^k)
par(k+1) = par(k) ^ par((k+1)^k)

รูปแบบของ (k+1)^k

par((k+1)^k)ตอนนี้เราต้องคำนวณ อาจดูเหมือนว่าเราไม่ได้อยู่ที่ใดเพราะการคำนวณบิตพาริตี้เป็นปัญหาที่เราพยายามแก้ไข แต่ตัวเลขที่แสดงเป็น(k+1)^kมีรูปแบบ1,3,7,15,..ที่เป็นหนึ่งด้านล่างอำนาจของ 2, ความจริงมักจะใช้ในการแฮ็กบิต เรามาดูเหตุผลว่าทำไม

เมื่อเราเพิ่มขึ้นkเอฟเฟกต์ของไบนารี่ก็จะกลับด้านสุดท้าย0และ1ไปทางขวาเพื่อสร้างผู้นำใหม่0หากไม่มีเลย ยกตัวอย่างเช่นk=43=0b101011

      **
  101011  (43)
 +     1
  ------
= 101100  (44)

  101011  (43)
 ^101100  (44)
  ------
= 000111  (77)   

*คอลัมน์ก่อให้เกิดการพกมีเครื่องหมาย เหล่านี้มี1การเปลี่ยนแปลงไป0และผ่านในบิตของการพกพา1ซึ่งช่วยให้การขยายพันธุ์ที่เหลือจนกว่าจะฮิต0ในซึ่งการเปลี่ยนแปลงไปk 1บิตใด ๆ ที่อยู่ทางด้านซ้ายจะไม่ได้รับผลกระทบ ดังนั้นเมื่อk^(k+1)ตรวจสอบตำแหน่งบิตที่เปลี่ยนkไปk+1จะพบว่าตำแหน่งของขวาสุด0และ1ขวาไป นั่นคือบิตที่เปลี่ยนแปลงเป็นส่วนต่อท้ายดังนั้นผลลัพธ์คือ 0 ตามด้วยหนึ่งหรือมากกว่า 1 ของ หากไม่มีศูนย์นำหน้าจะมีเลขฐานสอง1, 11, 111, 1111, ...ที่อยู่ต่ำกว่ากำลังสอง

การคำนวณ par((k+1)^k)

ตอนนี้เราเข้าใจแล้วว่า(k+1)^kมี จำกัด1,3,7,15,...เราลองหาวิธีคำนวณความเท่าเทียมกันของตัวเลขเหล่านี้ นี่เป็นความจริงที่มีประโยชน์คือว่า1,2,4,8,16,...โมดูโลสลับ3ระหว่าง1และตั้งแต่2 2==-1 mod 3ดังนั้นการให้1,3,7,15,31,63...โมดูโล่3ให้1,0,1,0,1,0...ซึ่งเป็นบิต parities ของพวกเขา ที่สมบูรณ์แบบ!

ดังนั้นเราสามารถทำการอัปเดตpar(k+1) = par(k) ^ par((k+1)^k)เป็น

par(k+1) = par(k) ^ ((k+1)^k)%3

การใช้bเป็นตัวแปรที่เราจัดเก็บพาริตี้อยู่จะมีลักษณะดังนี้

b^=((k+1)^k)%3

การเขียนรหัส

วางนี้ร่วมกันในรหัสที่เราจะเริ่มต้นkและความเท่าเทียมกันบิตbทั้งที่0แล้วพิมพ์ซ้ำ ๆn=2*k+bและการปรับปรุงและb=b^((k+1)^k)%3k=k+1

46 ไบต์

k=b=0
exec"print 2*k+b;b^=(k+1^k)%3;k+=1;"*400

ลองออนไลน์!

เราลบ parens รอบk+1ใน((k+1)^k)%3เพราะงูใหญ่มีความสำคัญไม่นอกจากครั้งแรกแล้วแปลกเป็นลักษณะ

การปรับปรุงรหัส

เราสามารถทำได้ดีกว่าโดยการทำงานกับตัวแปรเดี่ยวโดยตรงn=2*k+bและทำการอัปเดตโดยตรง ทำสอดคล้องกับk+=1 n+=2และการปรับปรุงที่สอดคล้องกับb^=(k+1^k)%3 n^=(k+1^k)%3ที่นี่ก่อนที่จะอัพเดตk=n/2n

44 ไบต์

n=0
exec"print n;n^=(n/2+1^n/2)%3;n+=2;"*400

ลองออนไลน์!

เราสามารถย่อให้สั้นลงn/2+1^n/2(จำได้ว่านี่คือ(n/2+1)^n/2) โดยเขียนใหม่

n/2+1 ^ n/2
(n+2)/2 ^ n/2
(n+2 ^ n)/2    

ตั้งแต่/2ลบบิตสุดท้ายมันไม่สำคัญว่าเราจะทำก่อนหรือหลัง xor-ing n^=(n+2^n)/2%3ดังนั้นเรามี เราสามารถบันทึกไบต์อื่นโดยสังเกตว่าโมดูโล3, /2เทียบเท่ากับ*2เทียบเท่ากับการ-สังเกตว่าn+2^nเป็นแม้ดังนั้นส่วนที่เป็นลดลงครึ่งหนึ่งที่เกิดขึ้นจริงโดยไม่ต้องปูพื้น สิ่งนี้จะช่วยให้n^=-(n+2^n)%3

41 ไบต์

n=0
exec"print n;n^=-(n+2^n)%3;n+=2;"*400

ลองออนไลน์!

ในที่สุดเราสามารถรวมการดำเนินการn^=c;n+=2เข้าn=(n+2)^cด้วยกันซึ่งcเป็นบิต วิธีนี้ใช้งานได้เพราะ^cทำหน้าที่เฉพาะบิตสุดท้ายและ+2ไม่สนใจบิตสุดท้ายดังนั้นการดำเนินการเดินทาง อีกครั้งมีความสำคัญช่วยให้เราละเว้น parens n=n+2^cและเขียน

39 ไบต์

n=0
exec"print n;n=n+2^-(n+2^n)%3;"*400

ลองออนไลน์!


13

นี่ให้โซลูชัน 47 ไบต์ (xnor's) ของฉันและความคิดที่นำฉันไปสู่มัน อย่าอ่านสิ่งนี้หากคุณต้องการเข้าใจตัวเอง

แนวคิดแรกที่เป็นธรรมชาติคือการวนซ้ำตัวเลข 0 ถึง 799 โดยพิมพ์เฉพาะที่มีเลข 1 เป็นเลขคู่

52 ไบต์

for n in range(800):
 if~bin(n).count('1')%2:print n

ลองออนไลน์!

ที่นี่~จะใช้เวลาบิตเสริมเพื่อที่จะเปลี่ยนeven<->oddในการนับและให้คุณค่าความจริงเพียงแม้กระทั่งการนับ

เราสามารถปรับปรุงวิธีนี้โดยการสร้างค่าทั้งหมดแทนการกรอง สังเกตว่าค่าเอาต์พุตเป็นตัวเลข 0 ถึง 399 โดยแต่ละบิตมีการต่อท้ายเพื่อให้มีจำนวน 1 บิตเท่ากัน

0 = 2*0 + 0
3 = 2*1 + 1
5 = 2*2 + 1
6 = 2*3 + 0
...

ดังนั้นnจำนวนวันเป็นอย่างใดอย่างหนึ่ง2*n+bอย่างใดอย่างหนึ่งหรือb=0 b=1บิตbสามารถพบได้โดยการนับ1ในบิตของnและการนับโมดูโล 2

49 ไบต์

for n in range(400):print 2*n+bin(n).count('1')%2

ลองออนไลน์!

เราสามารถตัด 2 ไบต์2*โดย iterating กว่า0,2,4,...ซึ่งไม่ได้มีโอกาสนับ1's เราสามารถทำได้โดยใช้การexecวนซ้ำที่รัน 400 ครั้งและเพิ่มขึ้นอีกn2 รอบ

47 ไบต์

n=0;exec"print n+bin(n).count('1')%2;n+=2;"*400

ลองออนไลน์!

และนั่นคือโซลูชัน 47 ไบต์ของฉัน ฉันสงสัยมากที่สุดถ้าไม่ใช่โซลูชัน 47 ไบต์อื่น ๆ ทั้งหมดนั้นเหมือนกัน


1
execอนุญาตให้ใช้งานแบบยาว 47 ไบต์หรือไม่
Jonathan Frech

1
@JonathanFrech ใช่เมื่อหน้านั้นระบุว่า "exec ถูกปฏิเสธ" ก็ไม่ได้หมายถึงงูใหญ่แต่บรรทัดคำสั่งexec exec
xnor

9

การส่ง Python 3 ของ llhuii

นี่คือการส่ง Python 3 สำหรับ Evil Numbers ตอนที่เขียน:

ป้อนคำอธิบายรูปภาพที่นี่

llhuii อาจจะบอกกล่าวเคล็ดลับของพวกเขาให้กับ Python 3 และหาวิธีแก้ปัญหานั่นคือ

  • 3 ไบต์ยาวกว่าโซลูชัน Python 2 และ
  • มี 45 - (25 + 18) = ช่องว่าง 2 ไบต์

การโอน 47B ไปยัง Python 3 ของ xnor อย่างแท้จริงเราจะได้ 50B นี้:

n=0;exec("print(n+bin(n).count('1')%2);n+=2;"*400)

ppcg(xnor)ฉันส่งเป็น (มันเพิ่มวงเล็บในexecและprintซึ่งตอนนี้ใช้งานได้แล้ว) มันมีสถิติรหัสที่แตกต่างจาก Python 3 คำตอบอื่น ๆ ซึ่งทั้งหมดมีบางส่วนของช่องว่างในนั้น ที่น่าสนใจ!

มีวิธีที่สั้นกว่าในการเขียนซ้ำ ( execมีแนวโน้มเสียการแข่งขันใน Python 3):

n=0
while n<800:print(n+bin(n).count('1')%2);n+=2

มันคือ 49 ไบต์ ppcg(xnor,alternative)ฉันส่งเป็น นี่มีพื้นที่ว่างสองไบต์เช่นเดียวกับคำตอบของ llhui! สิ่งนี้ทำให้ฉันเชื่อว่าคำตอบ Python 3 ของ llhui จะมีลักษณะเช่นนี้ (ขึ้นบรรทัดใหม่แล้วwhileวนซ้ำ) ดังนั้น llhuii อาจใช้execใน Python 2 และwhilePython 3 เหมือนกับเรา สิ่งนี้อธิบายถึงความคลาดเคลื่อนของช่องว่าง


47B ของเรากลายเป็น 49B ใน Python 3 สิ่งที่น่าสนใจในตอนนี้คือ 42B ของ llhuii ไม่ได้กลายเป็น 44B แต่กลายเป็น 45B! สิ่งที่เกี่ยวกับวิธีการแก้ปัญหาของ llhuii ใช้หนึ่งไบต์พิเศษใน Python 3ซึ่งอาจหมายถึงความหลากหลาย

  • สิ่งแรกที่ควรคำนึงถึงคือการแบ่ง : บางที llhuii ใช้/ใน Python 2 ซึ่งกลายเป็น//Python 3 (หากพวกเขานับเป็นสองเท่าอย่างพวกเราแล้วn/2อาจถูกใช้เพื่อเลื่อนnกลับไปทางขวาทีละบิตหรือไม่)

  • สิ่งอื่น ๆ ที่อยู่ในใจเป็นผู้ประกอบการเอกหลังจากการพิมพ์ เราprint blahกลายเป็นprint(blah)(1 ไบต์พิเศษ) แต่ถ้า llhuii เขียนอะไรบางอย่างprint~-blahใน Python 2 มันจะกลายเป็นprint(~-blah)Python 3

  • อาจมีความคิดอื่น ๆ โปรดแจ้งให้เราทราบ

สถิติรหัสสำหรับโซลูชัน Py3 ทั้งหมดรวมถึงของฉันตอนนี้:

ป้อนคำอธิบายรูปภาพที่นี่


1
สิ่งที่ฉันคิดว่าน่าสนใจคือโซลูชัน Python 3 ของพวกเขานั้นเร็วกว่าโซลูชัน Python 2 อย่างมาก พวกเขากำลังใช้คุณสมบัติ Python บางอย่างที่มีประสิทธิภาพมากขึ้นใน Python 3 หรือไม่ใช่พอร์ตธรรมดาหลังจากนั้น (บางทีพวกเขาอาจพบโซลูชัน Python 3 ซึ่งสั้นกว่าพอร์ตโดยตรง)
Jonathan Frech

2
runtimes บน anagol มีความแปรปรวนอย่างมากฉันให้ความเห็นเกี่ยวกับ OP ที่รันไทม์ของ llhuii ที่นี่ทำให้ฉันคิดว่า Py2 runtime ของพวกเขานั้นเป็นเพียงควัน / แฮงค์สีแดง
Lynn

นอกจากนี้ผมถือว่า XNOR พบเคล็ดลับที่คล้ายกันมากและการปรับปรุงเกี่ยวกับมัน (มีไม่สามารถเป็นที่หลายวิธีที่จะพิมพ์หมายเลขชั่วขวา ?!) และวิธีการแก้ปัญหาของพวกเขาคือความอุดมสมบูรณ์ได้อย่างรวดเร็ว!
ลินน์

7

แนวทางอื่น ๆ

1) การใช้สูตรสำหรับ A001969

แทนที่จะแปลงเป็นไบนารีอาจเป็นไปได้ที่จะใช้ประโยชน์จากสูตรต่อไปนี้ (จากOEIS ):

a(1) = 0
for n > 1: a(n) = 3*n-3-a(n/2) if n is even
           a(n) = a((n+1)/2)+n-1 if n is odd

ฉันเล่นกอล์ฟใน Python แย่มากดังนั้นฉันจะไม่ลองด้วยซ้ำ แต่นี่เป็นความพยายามอย่างรวดเร็วใน JS

หมายเหตุ: ฉันไม่คิดว่ามันจะเป็นการส่ง JS ที่ถูกต้องเพราะมันเป็นเพียงการกรอกอาร์เรย์โดยไม่แสดงมัน ยิ่งไปกว่านั้นมันมีขนาดยาวกว่า 5 ไบต์มากกว่าโซลูชัน JS ที่ดีที่สุดในปัจจุบัน (ซึ่งคือ 45 ไบต์) แต่นั่นไม่ใช่จุดที่นี่

for(a=[n=0,3];n<199;)a.push(2*++n+a[n],6*n+3-a[n])

หวังว่ามันอาจให้แรงบันดาลใจ

การใช้อาร์เรย์อาจไม่ใช่ความคิดที่ดีเพราะต้องมีการเริ่มต้นและอัปเดต มันอาจจะมีประสิทธิภาพมากขึ้น (ฉลาดขนาดรหัส) เพื่อใช้ฟังก์ชั่นซ้ำซ้ำซึ่งจะอธิบายว่าทำไมการแก้ปัญหาที่ชนะจะใช้เวลามากกว่าคนอื่น ๆ

2) การสร้างลำดับ Thue-Morse ด้วยการแทนที่

ในทางทฤษฎีแล้วรหัสนี้ควรใช้งานได้:

n=0;a="1";b="0";exec"t=a;a+=b;b+=t;print(int(b[n]))+n;n+=2;"*400

ลองออนไลน์!(เวอร์ชั่นที่รันได้ จำกัด 20 เทอม)

มันคำนวณลำดับ Thue-Morse ด้วยการเปลี่ยนตัวต่อเนื่องและค้นหาตำแหน่งของ 1 (Evil Numbers) ในลูปเดียวกัน

แต่:

  • มันยาวเกินไปในรูปแบบปัจจุบัน
  • มันนำไปสู่หน่วยความจำล้นอย่างรวดเร็ว

3) การสร้างลำดับ Thue-Morse ด้วยการใช้งานระดับบิต

เริ่มต้นจากคำจำกัดความโดยตรงของ Wikipedia ของลำดับ Thue-Morseฉันมาถึงอัลกอริทึมนี้ (เปลี่ยนกลับเป็น JS ... ขออภัย):

for(e=n=0;n<799;)(e^=!(((x=n++^n)^x/2)&170))||console.log(n)

ที่เราติดตามความชั่วร้ายในปัจจุบันของลำดับในeและใช้170เป็น bitmask ของบิตคี่ในไบต์


ฉันชอบความคิดของฟังก์ชั่นวนซ้ำ แต่ไพ ธ อนนั้นแย่มากสำหรับการสร้างสำเร็จรูป: f=lambda n:_ for n in range(400):print f(n)ใช้เวลา 43 ไบต์แล้ว อาจมีวิธีการจำลองการสอบถามซ้ำโดยการสร้างอาร์เรย์ที่อ้างอิงตัวเองหรืออาร์เรย์ที่เพิ่มองค์ประกอบในอนาคตไปยังจุดสิ้นสุด
xnor

2
นอกจากนี้ยังมีวิธีการแก้ปัญหา llhuii มีช่องว่างในมันไม่มีดังนั้นเขาจึงไม่ได้ใช้def, for, while, lambda(กับพารามิเตอร์อย่างน้อย) ฯลฯ
สตีเฟ่น

@ สตีเฟ่นสิ่งที่ต้องการwhile~0:print~1ไม่จำเป็นต้องมีช่องว่าง
Jonathan Frech

ในวิธีที่ 3 ((x=n++^n)^x/2)ดูเหมือนว่าค่อนข้างจะเพียงแค่หาบิตเซ็ตที่ต่ำที่สุด ++n&-nนั่นระเบียบทั้งหมดจะถูกแทนที่ด้วย ลองออนไลน์!
Primo

@primo ฉันไม่รู้ว่าฉันกำลังคิดอะไรอยู่ที่นี่และฉันมาถึงสูตรที่ยุ่งยากนี้ได้อย่างไร ¯ \ _ (ツ) _ / ¯
Arnauld

5

วิธีการนับที่ซ้อนกัน

ฉันมีความคิดสำหรับแนวทางที่แตกต่างกัน แต่ฉันไม่เคยมีประสบการณ์เพียงพอในการเล่น python ดังนั้นฉันจะทิ้งมันไว้ที่นี่เพื่อให้พวกคุณพิจารณาว่าเป็นจุดเริ่มต้นที่เป็นไปได้สำหรับการเล่นกอล์ฟ

ความคิดที่ไม่ดี

n=0
i=1
for _ in"01":
 i^=1
 for _ in"01":
  i^=1
  for _ in"01":
   i^=1
   for _ in"01":
    i^=1
    for _ in"01":
     i^=1
     for _ in"01":
      i^=1
      for _ in"01":
       i^=1
       for _ in"01":
        i^=1
        for _ in"01":
          i^=1
          if n<800:print i+n
          n+=2

ลองออนไลน์!

เก้าระดับซ้อนกันลึกทุกลูปเหมือนกันดังนั้นในใจฉันควรจะสร้างขึ้นด้วย exec"something"*9+"deepest stuff"เก้าระดับความลึกรังลูปทั้งหมดที่มีเหมือนกันดังนั้นในใจของฉันพวกเขาควรจะถูกสร้างขึ้นโดยในทางปฏิบัติฉันไม่รู้ว่าเป็นไปได้ไหมที่จะทำสิ่งนี้ด้วยวงจร

สิ่งที่ควรพิจารณาในการตีกอล์ฟ:

  • อาจมีความเป็นไปได้อื่น ๆ ที่จะวนรอบสองครั้งนอกเหนือจาก for loop (ฉันลองใช้วิธีคล้าย quine กับสตริงที่จะดำเนินการส่งผ่านไปยังตัวเองเป็นการโต้แย้งการจัดรูปแบบสองครั้ง แต่หัวของฉันระเบิด)

  • นอกจากนี้ยังอาจเป็นทางเลือกที่ดีกว่าif n<800:ซึ่งจำเป็นสำหรับที่นี่เพราะมิฉะนั้นเราจะพิมพ์เลขชั่วถึง 2 ^ 10


116 ไบต์
Jonathan Frech

อาจลองใช้ความเข้าใจของรายการซ้อนกันแทนที่จะซ้อนสำหรับลูป?
Sparr

@Sparr ปัญหาจากนั้นคือการพิมพ์ตัวเลขจริง ใน Python 2 printเป็นคำสั่งไม่ใช่ฟังก์ชันดังนั้นจึงไม่สามารถปรากฏในความเข้าใจได้
Jonathan Frech

อาจprint '\n'.join([[[[[[[[[foo]foo]foo]foo]foo]foo]foo]foo]foo])
Sparr

@ Sparr จากนั้นปัญหาอยู่ที่การทำให้รายการแบน str.joinใช้ได้กับรายการที่มีสตริงเท่านั้นและต้องไม่พิมพ์อักขระพิเศษของรายการ การจัดรูปแบบเพียงอย่างเดียวอาจใช้จำนวนไบต์ที่มากพอ
Jonathan Frech

5

แนวคิด: บิตที่สั้นกว่า

ใช้อักขระหลายตัวในbin(n).count('1')%2การคำนวณพาริตีของการนับบิต อาจเป็นวิธีการทางคณิตศาสตร์ที่สั้นกว่าโดยเฉพาะอย่างยิ่งที่มีความยาวบิต จำกัด

วิธีที่มีความยาวเท่ากันที่น่ารักคือint(bin(n)[2:],3)%2การตีความค่าไบนารีเป็นฐาน3(หรือฐานแปลก ๆ ) น่าเสียดายที่ 4 ในจำนวนไบต์ใช้การลบ0bคำนำหน้า นอกจากนี้ยังใช้งานint(bin(n)[2:])%9%2ได้ดี

แนวคิดอื่นมาจากการรวมบิตโดยใช้ xor หากnมีการเป็นตัวแทนไบนารีabcdefghiแล้ว

n/16 = abcde
n%16 =  fghi

r = n/16 ^ n%16 has binary representation (a)(b^f)(c^g)(d^h)(e^i)

ดังนั้นr=n/16^n%16ถ้าชั่วร้ายก็ต่อเมื่อnชั่วร้าย แล้วเราสามารถทำซ้ำที่เป็นs=r/4^r%4ค่าsใน0,1,2,3ซึ่ง1และไม่ได้เป็นความชั่วร้ายที่ตรวจสอบได้ด้วย20<s<3

52 ไบต์

n=0;exec"r=n/16^n%16;print(0<r/4^r%4<3)+n;n+=2;"*400

ลองออนไลน์!

เรื่องนี้กลายเป็นข้อตกลงที่ดีอีกต่อไป มีปุ่มหมุนจำนวนมากเพื่อเปลี่ยนวิธีแบ่งตัวเลขวิธีตรวจสอบหมายเลขสุดท้าย (อาจเป็นตารางการค้นหาแบบบิต) ฉันสงสัยว่าสิ่งเหล่านี้สามารถไปได้ไกลแค่ไหน


เป็นไปได้to_bytesไหมที่จะใช้ฟังก์ชันของจำนวนเต็ม? ฉันสงสัยมัน แต่สิ่งที่ต้องพิจารณา :)
HyperNeutrino

@HyperNeutrino ฉันคิดว่าเป็น Python 3 เท่านั้น?
xnor

yup my bad: / rip
HyperNeutrino

9
เพียงใช้0b: int(bin(n),13)%2! : D
Noodle9

3
ความคืบหน้า! เคล็ดลับของ Noodle9 มีวิธีแก้ปัญหา 44 ไบต์:n=0;exec"print~int(bin(n),13)%2+n;n+=2;"*400
Lynn

4

โดยการก่อสร้างนั้นn+n^nเป็นสิ่งที่ชั่วร้ายอยู่เสมอ แต่ทักษะ Python ที่ไม่ดีของฉันสามารถทำได้ด้วยวิธีแก้ปัญหา 61 ไบต์:

for n in sorted(map(lambda n:n+n^n,range(512)))[:400]:print n

ขอบคุณ @Peilonrayz สำหรับการบันทึก 5 ไบต์และ @ Mr.Xcoder สำหรับการบันทึก 1 ไบต์:

for n in sorted(n^n*2for n in range(512))[:400]:print n

55 ไบต์for n in sorted(n^n*2for n in range(512))[:400]:print n : n+n^nเหมือนกับn^n*2
Mr. Xcoder

3

แนวคิด: A006068 (“ a (n) คือรหัสสีเทาเป็น n”)

ความคิดของนีลในการจัดเรียงทั้งหมดที่2n XOR nฉันสนใจดังนั้นฉันพยายามค้นหาดัชนีที่อยู่เบื้องหลังการจัดเรียงนี้ ฉันเขียนรหัสนี้และมันแสดงให้เห็นว่าเราสามารถเขียนสิ่งนี้:

for n in range(400):x=a(n);print 2*x^x

อยู่ที่ไหนa(n)A006068 (n) ลองออนไลน์!

อย่างไรก็ตามนี่ถือว่าเรามีวิธีสั้น ๆ ในการคำนวณ A006068 นี่เป็น 38 ไบต์แล้วโดยสมมติว่าเราสามารถคำนวณได้ 4 ไบต์ ( a(n)ส่วน) การใช้งานจริง (ในส่วนหัวของ TIO) นั้นยาวกว่านั้น ฉันไม่คิดว่าจะมีความหวังในเรื่องนี้


3

แนวคิด: ลดมากกว่า XOR

หากคุณแฮคบิตทั้งหมดnเข้าด้วยกันมันจะเป็น0ความชั่วร้ายและ1ไม่ใช่ความชั่วร้าย คุณสามารถทำสิ่งนี้ได้ด้วยฟังก์ชั่นวนซ้ำ (ซึ่งอาจต้องใช้เวลามากขึ้น?) เช่น:

f=lambda n:f(n/2^n&1)if n>1else-~-n

สิ่งนี้จะส่งกลับ 1 สำหรับความชั่วร้าย

นั่นคือ 35 ไบต์และตรวจสอบว่าตัวเลขนั้นชั่วหรือไม่ น่าเสียดายที่filterมีขนาด 6 ไบต์อยู่แล้วดังนั้นนี่จึงไม่ใช่คำตอบที่ดีที่สุด แต่ความคิดนี้อาจจะสามารถเล่นกอล์ฟได้


ฉันคิดว่าคุณสามารถทำf=lambda n:n>1and f(n/2^n&1)or-~-n-1 ไบต์
Erik the Outgolfer

@EriktheOutgolfer ฉันพยายาม แต่นั่นทำให้เกิดข้อผิดพลาดเมื่อf(n/2^n&1)ส่งคืน 0 ...
HyperNeutrino

2

วิธีการทดแทน: {1 -> {1, -1}, -1 -> {-1, 1}}

นอกจากนี้คุณยังสามารถทำการทดแทน 10 ครั้ง {1 -> {1, -1}, -1 -> {-1, 1}} จากนั้นจึงแผ่และตรวจสอบตำแหน่งของ 1

นี่คือรหัสทางคณิตศาสตร์

(F = Flatten)@
Position[F@Nest[#/.{1->{1,-1},-1->{-1,1}}&,1,10],1][[;; 400]] - 1

คุณจะทำสิ่งนี้ในไพ ธ อนได้อย่างไร
Aneesh Durg

2
@AneeshDurg คุณพบสิ่งที่น่าสนใจในการแก้ปัญหานี้หรือไม่? คิดนอกกรอบและคุณอาจพบหนทางสู่ความหมายของชีวิต AKA 42
J42161217
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.