หมายเลขฟิสไซล์


47

ฉันพบลำดับนี้ในขณะที่ทำงานกับEvolution of OEISแต่ไม่เคยมีโอกาสโพสต์มันเป็นคำตอบ หลังจากเขียนการนำการอ้างอิงไปใช้ใน Mathematica ฉันคิดว่านี่เป็นแบบฝึกหัดที่สนุกที่จะทำเป็นความท้าทายที่แยกจากกันดังนั้นที่นี่เราไปกันเลย

มาสร้างเครื่องปฏิกรณ์ฟิชชันเป็นตัวเลขกันเถอะ! Nพิจารณาเป็นจำนวนเต็มบวก 24เป็นตัวอย่างที่เราจะดูที่ ในการแยกจำนวนนี้เราต้องหาจำนวนเต็มบวกที่ต่อเนื่องสูงสุดที่รวมNกัน ในกรณีนี้นั่นก็7 + 8 + 9 = 24คือ ดังนั้นเราจึงแบ่งออก24เป็นสามตัวเลขใหม่ แต่นี่จะไม่เป็นเครื่องปฏิกรณ์ฟิชชันมากนักหากไม่มีปฏิกิริยาลูกโซ่ ดังนั้นให้ทำซ้ำขั้นตอนซ้ำสำหรับส่วนประกอบเหล่านี้:

       24
       /|\
      / | \
     /  |  \
    7   8   9
   / \     /|\
  3   4   / | \
 / \     /  |  \
1   2   2   3   4
           / \
          1   2

โปรดสังเกตว่าเราหยุดกระบวนการเมื่อใดก็ตามที่จำนวนไม่สามารถย่อยสลายเป็นจำนวนเต็มขนาดเล็กติดต่อกัน โปรดทราบด้วยว่าเราสามารถเขียน9เป็น4 + 5แต่2 + 3 + 4มีองค์ประกอบเพิ่มเติม จำนวนเซลล์ของNถูกกำหนดในขณะนี้เป็นจำนวน integers ได้ในขั้นตอนนี้รวมทั้งNตัวเอง ต้นไม้ดังกล่าวข้างต้นมี 13 F(24) = 13โหนดดังนั้น

ลำดับนี้เป็น OEIS รายการA256504

40 คำแรกที่เริ่มต้นจากN = 1คือ

1, 1, 3, 1, 5, 6, 5, 1, 6, 7, 12, 10, 12, 11, 12, 1, 8, 16, 14, 17, 18, 18,
23, 13, 21, 18, 22, 23, 24, 19, 14, 1, 22, 20, 23, 24, 31, 27, 25, 26

พบ 1,000 คำแรกใน Pastebinนี้

ความท้าทาย

ป.ร. ให้ไว้เป็นจำนวนเต็มบวกN, F(N)กำหนดจำนวนของเซลล์ (ดังนั้นคุณไม่จำเป็นต้องครอบคลุมผู้นำที่0ระบุไว้ใน OEIS)

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่น, รับอินพุตผ่าน STDIN (หรือทางเลือกที่ใกล้เคียงที่สุด), อาร์กิวเมนต์บรรทัดคำสั่งหรืออาร์กิวเมนต์ของฟังก์ชันและส่งผลลัพธ์ผ่าน STDOUT (หรือทางเลือกที่ใกล้เคียงที่สุด), ค่าส่งคืนของฟังก์ชันหรือพารามิเตอร์

นี่คือรหัสกอล์ฟดังนั้นคำตอบที่สั้นที่สุด (เป็นไบต์) ชนะ

คำถามโบนัส:คุณสามารถหาคุณสมบัติที่น่าสนใจของลำดับนี้ได้หรือไม่


ฉันสังเกตว่า OEIS ดูเหมือนว่าจะมีข้อผิดพลาดที่ n = 34: เริ่มต้นที่ n = 32 มัน (ปัจจุบัน) แสดงรายการ 1, 22, 22, 23, 24, 31, มากกว่า 1, 22, 20, 23, 24 31.
mathmandan

1
@ คณิตศาสตร์การจับที่ดีฉันอาจจะเสนอการแก้ไข (พร้อมกับแผนภาพแรก)
Martin Ender

ความท้าทายที่เกี่ยวข้อง: codegolf.stackexchange.com/questions/5703/… (และคำถามเดียวกันกับ math.SE: math.stackexchange.com/questions/139842/… )
Ilmari Karonen

@ คณิตศาสตร์ไทย FYI ฉันได้แก้ไขลำดับและตัวอย่างในขณะนี้และยังเพิ่มการใช้งานอ้างอิงของฉันและคำ 10k แรก
Martin Ender

ดูดี! ขอบคุณสำหรับการทำงานของคุณ!
mathmandan

คำตอบ:


16

Pyth, 23 22 21 ไบต์

Lh&lJfqbsT.:tUb)syMeJ

yนี้กำหนดฟังก์ชัน recursive ลองใช้งานออนไลน์: การสาธิต

คำอธิบาย:

L                      define a function y(b): return ...
            tUb          the list [1, 2, ..., b-1]
          .:   )         generate all consecutive sub-sequences
     f                   filter for sub-sequences T, which satisfy:
      qbsT                   b == sum(T)
    J                    and store them in J

                         return 
   lJ                        len(J)
  &                        and (if len(J) == 0 then 0 else ...)
                    eJ       last element of J (=longest sub-sequence) 
                  yM         recursive calls for all these numbers
                 s           sum
 h                         incremented by one (counting the current node)

52

ฟิชชัน , 1328 989 887 797 ไบต์

คำตอบนี้ยาวไปหน่อยอย่างไม่มีเหตุผล (ฉันหวังว่าเราจะมีพื้นที่ที่ยุบได้) ... โปรดอย่าลืมเลื่อนดูสิ่งนี้และแสดงคำตอบอื่น ๆ สำหรับความรัก!

การทำงานกับรหัสนี้เป็นสิ่งที่สร้างแรงบันดาลใจให้กับความท้าทายนี้ ฉันต้องการเพิ่มคำตอบใน Fission ให้กับ EOEIS ซึ่งทำให้ฉันอยู่ในลำดับนี้ อย่างไรก็ตามจริง ๆ แล้วการเรียนรู้การแบ่งเซลล์และการใช้งานสิ่งนี้ใช้เวลาสองสามสัปดาห์ในการเปิดและปิด ในขณะเดียวกันลำดับก็เพิ่มขึ้นอย่างมากกับฉันดังนั้นฉันตัดสินใจที่จะโพสต์ความท้าทายแยกต่างหากสำหรับมัน (บวกสิ่งนี้จะไม่ได้ลงไปที่ต้นไม้บน EOEIS ต่อไป)

ดังนั้นฉันจึงนำเสนอให้คุณความโหดร้าย:

 R'0@+\
/  Y@</ /[@ Y]_L
[? % \  / \ J
   \$@  [Z/;[{+++++++++L
UR+++++++++>/;
9\   ;    7A9
SQS  {+L  /$     \/\/\/\/\/   5/ @  [~ &@[S\/ \  D /8/
~4X /A@[  %5                   /; &    K  } [S//~KSA /
  3    \  A$@S  S\/  \/\/\/   \/>\ /S]@A  /  \ { +X
W7           X  X    /> \      +\ A\ /   \ /6~@/ \/
        /   ~A\;     +;\      /@
    ZX [K    / {/  / @  @ }  \ X @
       \AS   </      \V /    }SZS S/
         X   ;;@\   /;X  /> \ ; X X
 ;       \@+  >/ }$S SZS\+;    //\V
           / \\  /\; X X @  @  \~K{
           \0X /     /~/V\V /   0W//
    \        Z      [K \  //\
W       /MJ $$\\ /\7\A  /;7/\/ /
       4}K~@\ &]    @\  3/\
 /     \{   }$A/1 2  }Y~K <\
[{/\  ;@\@  /   \@<+@^   1;}++@S68
@\ <\    2        ;   \    /
$  ;}++ +++++++L
%@A{/
M  \@+>/
~     @
SNR'0YK
  \  A!/

คาดว่าจะไม่มีการขึ้นบรรทัดใหม่ของอินพุตดังนั้นคุณอาจต้องการเรียกว่าเป็นเช่นecho -n 120 | ./Fission oeis256504.fisนั้น

เลย์เอาต์อาจจะมีประสิทธิภาพมากกว่าดังนั้นฉันคิดว่ายังมีพื้นที่เหลือเฟือสำหรับการปรับปรุงที่นี่ (เช่นมี911 581 461 374 ช่องว่าง)

ก่อนที่เราจะไปถึงคำอธิบายให้ทราบเกี่ยวกับการทดสอบนี้: ล่ามอย่างเป็นทางการไม่ทำงานอย่างที่ ก) Mirror.cppไม่ได้รวบรวมในหลาย ๆ ระบบ หากคุณพบปัญหาดังกล่าวเพียงแค่คอมเม้นท์บรรทัดที่ละเมิด - ส่วนประกอบที่ได้รับผลกระทบ (มิรเรอร์แบบสุ่ม) จะไม่ถูกใช้ในรหัสนี้ b) มีข้อบกพร่องสองสามข้อที่สามารถนำไปสู่พฤติกรรมที่ไม่ได้กำหนด (และเป็นไปได้สำหรับโปรแกรมที่ซับซ้อนนี้) คุณสามารถใช้โปรแกรมแก้ไขนี้เพื่อแก้ไข เมื่อคุณทำสิ่งนั้นเสร็จแล้วคุณควรรวบรวมล่ามด้วย

g++ -g --std=c++11 *.cpp -o Fission

ความจริงที่สนุกสนาน: โปรแกรมนี้ใช้องค์ประกอบฟิชชันเกือบทุกอย่างที่มีให้ยกเว้น#(มิเรอร์แบบสุ่ม), :(มิเรอร์ครึ่งหนึ่ง) -หรือ|(มิเรอร์ธรรมดา) และ"(โหมดการพิมพ์)

เกิดอะไรขึ้นบนโลกนี้?

คำเตือน:นี่จะค่อนข้างนาน ... ฉันสมมติว่าคุณสนใจอย่างแท้จริงในเรื่องการทำงานของฟิชชันและวิธีที่โปรแกรมสามารถทำได้ เพราะถ้าคุณไม่ฉันไม่แน่ใจว่าฉันจะสรุปได้อย่างไร (ย่อหน้าถัดไปให้คำอธิบายทั่วไปของภาษาว่า)

ฟิชชันเป็นภาษาโปรแกรมสองมิติที่ทั้งข้อมูลและโฟลว์ควบคุมถูกแสดงโดยอะตอมที่เคลื่อนที่ผ่านกริด หากคุณเคยเห็นหรือเคยใช้Marbelousมาก่อนแนวคิดนี้น่าจะคุ้นเคย แต่ละอะตอมมีคุณสมบัติจำนวนเต็มสองอย่าง: มวลที่ไม่เป็นลบและพลังงานโดยพลการ หากมวลกลายเป็นลบอะตอมจะถูกลบออกจากกริด ในกรณีส่วนใหญ่คุณสามารถรักษามวลเป็น "ค่า" ของอะตอมและพลังงานเป็นคุณสมบัติเมตาบางประเภทที่ใช้โดยองค์ประกอบหลายอย่างเพื่อกำหนดการไหลของอะตอม (เช่นสวิตช์ส่วนใหญ่ขึ้นอยู่กับสัญลักษณ์ของ พลังงาน) ฉันจะแสดงอะตอมโดย(m,E)เมื่อจำเป็น ที่จุดเริ่มต้นของโปรแกรมตารางเริ่มต้นด้วยเครือ(1,0)อะตอมจากที่ใดก็ตามที่คุณวางบนส่วนประกอบทั้งสี่UDLR(ที่จดหมายระบุทิศทางที่อะตอมเคลื่อนที่ในตอนแรก) จากนั้นบอร์ดจะเต็มไปด้วยส่วนประกอบทั้งหมดซึ่งเปลี่ยนมวลและพลังงานของอะตอมเปลี่ยนทิศทางหรือทำสิ่งที่ซับซ้อนมากขึ้น สำหรับรายการทั้งหมดดูหน้า esolangsแต่ฉันจะแนะนำพวกเขาส่วนใหญ่ในคำอธิบายนี้ อีกจุดสำคัญ (ซึ่งโปรแกรมใช้หลายครั้ง) ก็คือตารางนั้นเป็น toroidal: อะตอมที่กระทบกับด้านใดด้านหนึ่งจะปรากฏขึ้นอีกด้านหนึ่งโดยเคลื่อนที่ไปในทิศทางเดียวกัน

ฉันเขียนโปรแกรมในชิ้นส่วนเล็ก ๆ หลาย ๆ ชิ้นและประกอบมันในตอนท้ายดังนั้นฉันจะอธิบายได้อย่างไร

atoi

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

ฟิชชันสามารถอ่านค่าไบต์จากอักขระแต่ละตัวเท่านั้นไม่ใช่ตัวเลขทั้งหมด ในขณะที่การปฏิบัติที่ยอมรับได้ที่นี่ฉันคิดในขณะที่ฉันอยู่ที่มันฉันสามารถทำได้ถูกต้องและแยกจำนวนเต็มจริงใน STDIN นี่คือatoiรหัส:

     ;
 R'0@+\
/  Y@</ /[@ Y]_L
[? % \  / \ J 
   \$@  [Z/;[{+++++++++L
UR+++++++++>/;
           O

สององค์ประกอบที่สำคัญที่สุดในฟิชชันคือฟิชชันและฟิวชั่นเครื่องปฏิกรณ์ เครื่องปฏิกรณ์ฟิชชันนั้นเป็นของอย่างใดอย่างหนึ่งV^<>(โค้ดด้านบนใช้<และ>) เครื่องปฏิกรณ์ฟิชชันสามารถเก็บอะตอม (โดยการส่งมันเข้าไปในตัวละครลิ่ม) (2,0)เริ่มต้นการเป็น หากอะตอมชนกับเอเพ็กซ์ของตัวละครอะตอมใหม่สองตัวจะถูกส่งออกไปที่ด้านข้าง มวลของพวกมันถูกกำหนดโดยการหารมวลที่เข้ามาด้วยมวลที่ถูกเก็บไว้ (เช่นลดลงครึ่งหนึ่งตามค่าเริ่มต้น) - อะตอมซ้ายไปจะได้รับค่านี้และอะตอมขวาไปจะได้รับส่วนที่เหลือของมวล . อะตอมทั้งสองจะมีพลังงานขาเข้าลบออกพลังงานที่เก็บไว้ ซึ่งหมายความว่าเราสามารถใช้เครื่องปฏิกรณ์ฟิชชันสำหรับเลขคณิต - ทั้งสำหรับการลบและการหาร หากเครื่องปฏิกรณ์ฟิชชันถูกโจมตีจากไซต์อะตอมก็จะสะท้อนให้เห็นในแนวทแยงมุมและจากนั้นจะเคลื่อนที่ไปในทิศทางของยอดของตัวละคร

เครื่องปฏิกรณ์ฟิวชั่นเป็นของใด ๆYA{}(รหัสข้างต้นใช้Yและ{) ฟังก์ชั่นของพวกเขาคล้ายกัน: พวกเขาสามารถเก็บอะตอม (ค่าเริ่มต้น(1,0)) และเมื่อถูกชนจากยอดสองอะตอมใหม่จะถูกส่งออกไปด้านข้าง อย่างไรก็ตามในกรณีนี้ทั้งสองอะตอมจะเหมือนกันเสมอรักษาพลังงานที่เข้ามาและคูณมวลที่เข้ามาโดยมวลที่เก็บไว้ นั่นคือโดยปกติเครื่องปฏิกรณ์ฟิวชั่นจะทำซ้ำอะตอมใด ๆ ที่กระทบยอด เมื่อถูกชนจากด้านข้างเครื่องปฏิกรณ์ฟิวชั่นนั้นซับซ้อนกว่าเล็กน้อย: อะตอมก็เช่นกันเก็บไว้ (เป็นอิสระจากหน่วยความจำอื่น) จนกระทั่งอะตอมชนกับด้านตรงข้าม เมื่อสิ่งนั้นเกิดขึ้นอะตอมใหม่จะถูกปล่อยออกมาในทิศทางของยอดที่มีมวลและพลังงานเป็นผลรวมของอะตอมเก่าสองอะตอม หากอะตอมใหม่ชนกับด้านเดียวกันก่อนที่อะตอมที่เข้าคู่จะถึงด้านตรงข้ามอะตอมเก่าก็จะถูกเขียนทับ เครื่องปฏิกรณ์ฟิวชั่นสามารถใช้เพื่อเพิ่มและคูณ

อีกองค์ประกอบที่เรียบง่ายที่ฉันต้องการหลีกทางคือ[และ]กำหนดทิศทางของอะตอมไปทางขวาและซ้ายตามลำดับ (โดยไม่คำนึงถึงทิศทางที่เข้ามา) ค่าเทียบเท่าแนวตั้งคือM(ลง) และW(ขึ้น) แต่ไม่ได้ใช้กับatoiรหัส UDLRทำหน้าที่เหมือนWM][หลังจากปล่อยอะตอมเริ่มต้นของพวกเขา

เอาล่ะลองดูโค้ดที่นั่น โปรแกรมเริ่มต้นด้วย 5 อะตอม:

  • RและLที่ด้านล่างเพียงได้รับการเพิ่มมวลของพวกเขา (กับ+) จะกลายเป็น(10,0)แล้วเก็บไว้ในการแบ่งเซลล์และเครื่องปฏิกรณ์ฟิวชั่นตามลำดับ เราจะใช้เครื่องปฏิกรณ์เหล่านี้เพื่อวิเคราะห์อินพุต -10
  • Lในมุมขวาด้านบนได้รับมวล decremented (กับ_) จะกลายเป็นและถูกเก็บไว้ในด้านข้างของเครื่องปฏิกรณ์ฟิวชั่น(0,0) Yนี่คือการติดตามจำนวนที่เรากำลังอ่านเราจะค่อยๆเพิ่มและทวีคูณเมื่อเราอ่านตัวเลข
  • Rในมุมซ้ายด้านบนได้รับมวลของมันตั้งค่ารหัสอักขระของ0(48) ด้วย'0แล้วมวลและพลังงานจะสลับกับ@และในที่สุดก็เพิ่มขึ้นมวลครั้งด้วยที่จะให้+ (1,48)จากนั้นจะถูกเปลี่ยนเส้นทางด้วยกระจกแนวทแยงมุม\และ/เก็บไว้ในเครื่องปฏิกรณ์ฟิชชัน เราจะใช้การ48ลบเพื่อเปลี่ยนข้อมูล ASCII ให้เป็นค่าจริงของตัวเลข นอกจากนี้เรายังมีการเพิ่มมวลเพื่อที่จะหลีกเลี่ยงการหารด้วย10
  • ในที่สุดที่Uมุมซ้ายล่างคือสิ่งที่ทำให้ทุกอย่างเคลื่อนไหวและเริ่มใช้เพื่อควบคุมการไหลเท่านั้น

หลังจากถูกเปลี่ยนเส้นทางไปทางขวาอะตอมควบคุมจะเข้า?สู่ นี่คือองค์ประกอบอินพุต มันอ่านตัวอักษรและการตั้งค่ามวลอะตอมของกับค่า ASCII 0การอ่านและพลังงานในการ ถ้าเราตี EOF 1แทนพลังงานจะถูกตั้งค่า

อะตอมยังคงดำเนินต่อ%ไป นี่คือสวิตช์กระจก สำหรับพลังงานที่ไม่เป็นบวกสิ่งนี้ทำหน้าที่เหมือน/กระจกเงา แต่สำหรับพลังงานบวกมันทำหน้าที่เหมือน\(และยังลดพลังงานลง 1) ดังนั้นในขณะที่เรากำลังอ่านตัวละครอะตอมจะสะท้อนขึ้นและเราสามารถประมวลผลตัวละคร แต่เมื่อเราทำกับอินพุตอะตอมจะสะท้อนลงและเราสามารถใช้ตรรกะต่าง ๆ เพื่อดึงผลลัพธ์ FYI &องค์ประกอบตรงข้ามคือ

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

อะตอมตัวอักษรตัวแรกฮิต (เริ่มต้น) Yเครื่องปฏิกรณ์ฟิวชั่น สิ่งนี้จะแยกอะตอมและเราใช้สำเนาซ้ายไปเป็นอะตอมควบคุมเพื่อวนกลับเข้าไปในองค์ประกอบอินพุตและอ่านอักขระถัดไป สำเนาที่ถูกต้องจะถูกดำเนินการ 3พิจารณากรณีที่เราได้อ่านตัวอักษร อะตอมของเราจะเป็น(51,0)อย่างไร เราแลกเปลี่ยนมวลและพลังงานด้วย@เช่นนั้นเราสามารถใช้การลบของเครื่องปฏิกรณ์ฟิชชันถัดไป เครื่องปฏิกรณ์ลบ48พลังงานออก (โดยไม่ต้องเปลี่ยนมวล) ดังนั้นมันจึงส่งออกไปสองชุด(0,3)- ตอนนี้พลังงานสอดคล้องกับหลักที่เราอ่าน สำเนาที่อยู่ข้างบนจะถูกยกเลิกเพียงแค่;(ส่วนประกอบที่เพิ่งทำลายอะตอมขาเข้าทั้งหมด) เราจะทำงานกับสำเนาต่อไป คุณจะต้องทำตามเส้นทางผ่าน/และ\กระจกเล็กน้อย

@เพียงก่อนที่เครื่องปฏิกรณ์ฟิวชั่น swaps มวลและพลังงานอีกครั้งเช่นที่เราจะเพิ่มการรวมการทำงานของเราใน(3,0) Yโปรดทราบว่าผลรวมการรันเองจะมี0พลังงานเสมอ

ตอนนี้Jเป็นกระโดด สิ่งที่มันจะกระโดดอะตอมที่เข้ามาใด ๆ ไปข้างหน้าด้วยพลังงานของมัน ถ้าเป็น0เช่นนั้นอะตอมก็จะเคลื่อนที่ต่อไปเรื่อย ๆ ถ้ามัน1จะข้ามเซลล์หนึ่งถ้า2มันจะข้ามสองเซลล์และอื่น ๆ 0พลังงานที่ใช้ในการกระโดดดังนั้นอะตอมมักจะจบลงด้วยการใช้พลังงาน นับตั้งแต่การรวมการทำงานจะมีศูนย์พลังงานกระโดดจะถูกละเว้นสำหรับในตอนนี้และอะตอมจะถูกนำเข้าสู่เครื่องปฏิกรณ์ฟิวชั่นซึ่งคูณมวลของมันโดย{ 10สำเนาที่ถูกตัดทิ้งจะถูกทิ้ง;ในขณะที่สำเนาที่ส่งกลับจะถูกป้อนกลับเข้าไปในYเครื่องปฏิกรณ์เป็นผลรวมการดำเนินการใหม่

ด้านบนยังคงทำซ้ำ (ในลักษณะที่สนุกสนานไปป์ไลน์ที่มีการประมวลผลตัวเลขใหม่ก่อนที่จะทำก่อนหน้านี้) จนกว่าเราจะกด EOF ตอนนี้%จะส่งอะตอมลง ความคิดที่จะเปิดอะตอมนี้ใน(0,1)ตอนนี้ก่อนกดปุ่มเครื่องปฏิกรณ์รวมการทำงานเพื่อให้) ทั้งหมดที่ไม่ได้รับผลกระทบ (ศูนย์มวล) และ b) เราได้รับพลังงานจากการกระโดดข้าม1 [เราสามารถดูแลพลังงานได้อย่างง่ายดายด้วย$ซึ่งจะเป็นการเพิ่มพลังงาน

ปัญหาคือ?ไม่ได้รีเซ็ตมวลเมื่อคุณกด EOF ดังนั้นมวลจะยังคงเป็นตัวอักษรสุดท้ายที่อ่านและพลังงานจะเป็น0(เพราะ%ลดค่า1กลับไป0) เราอยากกำจัดมวลนั้น เมื่อต้องการทำเช่นนั้นเราจะเปลี่ยนมวลและพลังงานด้วย@อีกครั้ง

Zฉันต้องการที่จะแนะนำองค์ประกอบหนึ่งมากขึ้นก่อนที่จะจบขึ้นส่วนนี้: นี้เป็นหลักเช่นเดียวกับหรือ% &ความแตกต่างคือช่วยให้อะตอมพลังงานบวกผ่าน (ในขณะที่ลดพลังงาน) และเบี่ยงเบนอะตอมที่ไม่ใช่พลังงานบวก 90 องศาไปทางซ้าย เราสามารถใช้สิ่งนี้เพื่อกำจัดพลังงานของอะตอมโดยการวนซ้ำZไปเรื่อย ๆ - ทันทีที่พลังงานหมดไปอะตอมก็จะเบี่ยงเบนและออกจากวง นั่นคือรูปแบบนี้:

/ \
[Z/

ที่ซึ่งอะตอมจะเคลื่อนที่ขึ้นเมื่อพลังงานเป็นศูนย์ ฉันจะใช้รูปแบบนี้ในรูปแบบเดียวหรือหลายครั้งในส่วนอื่น ๆ ของโปรแกรม

ดังนั้นเมื่ออะตอมออกจากลูปเล็ก ๆ นี้มันจะถูก(1,0)เปลี่ยนเป็น(0,1)โดย@ก่อนที่จะกดปุ่มเครื่องปฏิกรณ์ฟิวชั่นเพื่อปล่อยผลสุดท้ายของอินพุต อย่างไรก็ตามผลรวมการทำงานจะถูกปิดโดยปัจจัย 10 เนื่องจากเราได้คูณจำนวนนั้นกับตัวเลขอื่นแล้ว

ดังนั้นตอนนี้มีพลังงาน1อะตอมนี้จะข้ามและกระโดดลงไปใน[ /สิ่งนี้เบี่ยงเบนมันไปเป็นเครื่องปฏิกรณ์ฟิชชันซึ่งเราได้เตรียมที่จะหารด้วย 10 และแก้ไขการคูณภายนอกของเรา อีกครั้งเราละทิ้งครึ่งหนึ่ง;และเก็บไว้เป็นเอาท์พุท (ที่นี่เป็นตัวOแทนที่จะพิมพ์ตัวละครที่สอดคล้องกันและทำลายอะตอม - ในโปรแกรมเต็มรูปแบบที่เราให้ใช้อะตอมแทน)

itoa

           /     \
input ->  [{/\  ;@
          @\ <\   
          $  ;}++ +++++++L
          %@A{/
          M  \@+>/
          ~     @
          SNR'0YK
            \  A!/

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

รหัสนี้จะแนะนำองค์ประกอบฟิชชันใหม่ที่ทรงพลังมาก: สแต็Kก สแต็กแรกว่างเปล่า เมื่ออะตอมที่มีพลังงานไม่เป็นลบกระทบกับสแต็กอะตอมจะถูกผลักลงบนสแต็ก เมื่ออะตอมที่มีพลังงานเป็นลบกระทบกับสแต็คมวลและพลังงานของมันจะถูกแทนที่ด้วยอะตอมที่อยู่ด้านบนของสแต็ค หากสแต็คว่างเปล่าแม้ว่าทิศทางของอะตอมจะกลับกันและพลังงานของมันจะกลายเป็นบวก (เช่นคูณด้วย-1)

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

ครึ่งบนของโค้ดทำการคำนวณหลัก: Lด้วย pluses ให้ 10 ซึ่งเราโคลนและป้อนเข้าสู่ฟิชชันและเครื่องปฏิกรณ์ฟิวชั่นเพื่อให้เราสามารถหารและคูณด้วย 10 ห่วงเริ่มต้น[จากมุมซ้ายบน . ค่าปัจจุบันถูกแบ่ง: หนึ่งสำเนาถูกหารด้วย 10 จากนั้นคูณด้วย 10 และเก็บไว้ในเครื่องปฏิกรณ์ฟิชชัน นี้คำนวณเป็นi % 10 i - ((i/10) * 10)โปรดทราบว่าการAแบ่งผลกลางหลังจากการหารและก่อนการคูณดังนั้นเราสามารถป้อนi / 10เข้าไปในการวนซ้ำครั้งถัดไป

%ยกเลิกห่วงเมื่อตัวแปรซ้ำฮิต 0. ตั้งแต่นี้จะมากหรือน้อยวงทำในขณะนี้รหัสนี้แม้จะทำงานสำหรับการพิมพ์0(โดยไม่ต้องสร้างศูนย์ชั้นนำอื่น ๆ ) เมื่อเราออกจากวงเราต้องการที่จะล้างกองและพิมพ์ตัวเลข Sอยู่ตรงข้ามZดังนั้นจึงเป็นสวิตช์ที่จะเบี่ยงเบนอะตอมที่เข้ามาด้วยพลังงานที่ไม่เป็นบวก 90 องศาไปทางขวา ดังนั้นอะตอมเคลื่อนไปตามขอบจากทางSตรงไปยังที่Kจะโผล่ออกมาเป็นหลัก (หมายเหตุ~ซึ่งช่วยให้แน่ใจว่าอะตอมที่เข้ามามีพลังงาน-1) ตัวเลขนั้นจะถูกเพิ่มค่าโดย48รับรหัส ASCII ของอักขระหลักที่เกี่ยวข้อง Aแยกหลักในการพิมพ์สำเนาด้วย!และป้อนสำเนาอื่น ๆ กลับเข้าไปในYเครื่องปฏิกรณ์สำหรับตัวเลขถัดไป สำเนาที่พิมพ์จะถูกใช้เป็นทริกเกอร์ถัดไปสำหรับสแต็ก (โปรดทราบว่ามิรเรอร์จะส่งมันไปรอบ ๆ ขอบเพื่อชนMจากด้านซ้าย)

เมื่อสแต็คเป็นที่ว่างเปล่าที่Kจะสะท้อนให้เห็นถึงอะตอมและเปิดพลังงานของมันเข้าไปเช่นว่ามันผ่านตรงผ่าน+1 พิมพ์บรรทัดใหม่ (เพราะมันเป็นระเบียบ :)) และจากนั้นอะตอมไป thorugh อีกครั้งเพื่อจบลงในด้านของ เนื่องจากไม่มีอะตอมอยู่รอบ ๆ สิ่งนี้จะไม่ถูกปล่อยออกมาและโปรแกรมจะสิ้นสุดลงSNR'0Y

การคำนวณหมายเลขฟิชชัน: The Framework

ไปที่เนื้อของโปรแกรมกันเถอะ รหัสนั้นเป็นพอร์ตของการใช้การอ้างอิง Mathematica ของฉัน:

fission[n_] := If[
  (div = 
    SelectFirst[
      Reverse@Divisors[2 n], 
      (OddQ@# == IntegerQ[n/#] 
       && n/# > (# - 1)/2) &
    ]
  ) == 1,
  1,
  1 + Total[fission /@ (Range@div + n/div - (div + 1)/2)]
]

โดยที่divเป็นจำนวนเต็มในพาร์ติชันสูงสุด

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

นี่คือกรอบการทำงานสำหรับแนวคิดนี้:

                      +--- input goes in here
                      v 

                     SQS ---> compute div from n          D /8/
                     ~4X               |                /~KSA /
                       3               +----------->    { +X
initial trigger ---> W                               6~@/ \/
                              4                   
                     W        ^                     /
                              |              3
                     ^     generate range    |
                     |     from n and div  <-+----- S6
                     |         -then-      
                     +---- release new trigger

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

ถึงตอนนี้คุณอาจจะสามารถแยกแยะกรอบงานส่วนใหญ่ออกมาได้ด้วยตัวเอง มุมซ้ายบนมีคิวของค่าที่ยังคงถูกประมวลผลและปล่อยทีnละครั้ง สำเนาหนึ่งของnถูกเคลื่อนย้ายไปด้านล่างเพราะเราต้องการเมื่อคำนวณช่วงสำเนาอื่น ๆ จะเข้าสู่บล็อกที่ด้านบนซึ่งคำนวณdiv(นี่คือส่วนที่ใหญ่ที่สุดของรหัส) เมื่อdivได้รับการคำนวณก็จะซ้ำ - Kหนึ่งสำเนาเพิ่มเคาน์เตอร์ในมุมขวาด้านบนซึ่งถูกเก็บไว้ใน สำเนาอื่นจะถูกส่งไปที่ด้านล่าง ถ้าdivเป็น1เช่นนั้นเราเบี่ยงเบนมันขึ้นมาทันทีและใช้มันเป็นทริกเกอร์สำหรับการทำซ้ำครั้งถัดไปโดยไม่ต้องจัดคิวค่าใหม่ใด ๆ มิฉะนั้นเราจะใช้divและn ในส่วนที่ด้านล่างเพื่อสร้างช่วงใหม่ (เช่นกระแสของอะตอมที่มีมวลที่สอดคล้องกันซึ่งจะถูกใส่ในคิว) จากนั้นปล่อยทริกเกอร์ใหม่หลังจากช่วงเสร็จสมบูรณ์

เมื่อคิวว่างเปล่าไกจะสะท้อนให้เห็นผ่านตรงผ่านSและโผล่มาให้เห็นในมุมขวาด้านบนที่มันออกเคาน์เตอร์ (ผลสุดท้าย) จากAซึ่งหายตัวไปแล้วผ่านทางitoa8

การคำนวณหมายเลขฟิชชัน: The Loop Body

ดังนั้นสิ่งที่เหลืออยู่คือสองส่วนในการคำนวณdivและสร้างช่วง การคำนวณdivเป็นส่วนนี้:

 ;    
 {+L  /$     \/\/\/\/\/   5/ @  [~ &@[S\/ \
/A@[  %5                   /; &    K  } [S/
   \  A$@S  S\/  \/\/\/   \/>\ /S]@A  /  \ 
         X  X    /> \      +\ A\ /   \ /
    /   ~A\;     +;\      /@
ZX [K    / {/  / @  @ }  \ X @
   \AS   </      \V /    }SZS S/
     X   ;;@\   /;X  /> \ ; X X
     \@+  >/ }$S SZS\+;    //\V
       / \\  /\; X X @  @  \~K{
       \0X /     /~/V\V /   0W//
\        Z      [K \  //\
           \ /\7\A  /;7/\/

คุณอาจเห็นพอที่จะไขปริศนาตัวเองด้วยความอดทน รายละเอียดระดับสูงคือ: 12 2nคอลัมน์แรกหรือเพื่อสร้างกระแสของตัวหารของ 10 OddQ@# == IntegerQ[n/#]คอลัมน์ต่อไปกรองผู้ที่ไม่ตอบสนอง ถัดไป 8 n/# > (# - 1)/2)คอลัมน์กรองผู้ที่ไม่ตอบสนอง ในที่สุดเราก็ผลักดันตัวหารที่ถูกต้องทั้งหมดลงบนสแต็กและเมื่อเราเสร็จแล้วเราจะลบสแต็กทั้งหมดลงในเครื่องปฏิกรณ์ฟิวชั่น (เขียนทับทั้งหมดยกเว้นตัวหารสุดท้าย / ตัวใหญ่ที่สุด) แล้วปล่อยผลลัพธ์ตามด้วยการกำจัดพลังงาน - ศูนย์จากการตรวจสอบความไม่เท่าเทียมกัน)

มีเส้นทางบ้ามากมายที่นั่นไม่ทำอะไรเลย ส่วนใหญ่\/\/\/\/ความบ้าคลั่งที่ด้านบน ( 5s นั้นก็เป็นส่วนหนึ่งของมัน) และหนึ่งเส้นทางรอบด้านล่าง (ที่ผ่าน7s) ฉันต้องเพิ่มสิ่งเหล่านี้เพื่อจัดการกับสภาพการแข่งขันที่น่ารังเกียจ ฟิชชันสามารถใช้องค์ประกอบการหน่วงเวลา ...

รหัสที่สร้างช่วงใหม่จากnและdivนี่คือ:

 /MJ $$\
4}K~@\ &]    @\  3/\
\{   }$A/1 2  }Y~K <\
 \@  /   \@<+@^   1;}++@
  2        ;   \    /

เราคำนวณครั้งแรกn/div - (div + 1)/2(คำศัพท์ทั้งคู่ปูพื้นซึ่งให้ผลลัพธ์เหมือนกัน) และเก็บไว้ใช้ในภายหลัง จากนั้นเราจะสร้างช่วงจากdivล่างลงไป1และเพิ่มค่าที่เก็บไว้ในแต่ละช่วง

มีรูปแบบทั่วไปสองแบบใหม่ในทั้งสองรูปแบบที่ฉันควรกล่าวถึง: รูปแบบหนึ่งคือSXหรือZXถูกกดจากด้านล่าง นี่เป็นวิธีที่ดีในการทำซ้ำอะตอมหากคุณต้องการสำเนาหนึ่งชุดเพื่อไปข้างหน้าทันที SหรือZหมุนอะตอมเข้าที่Xแล้วหมุนสำเนามิเรอร์กลับเข้ามาในทิศทางเดิมของการขยายพันธุ์

อีกแบบคือ

[K
\A --> output

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

นั่นเป็นเรื่องที่ค่อนข้าง ... แต่ถ้าคุณผ่านเรื่องนี้ไปได้จริงฉันหวังว่าคุณจะมีความคิดที่ว่าฟิชชันi͝s̢̘̗̗ ͢i̟nç̮̩r̸̭̬̱͔e̟̹̟̜͟d̙i̠͙͎̖͓̯b̘̠͎̭̰̼l̶̪̙̮̥̮y̠̠͎̺̠̠͎̺͜͜


1
Now with 100% fewer scrollbars.ดังนั้นคุณจึงพูดว่า .. และยังคงต้องดำเนินการต่อไป ...
เครื่องมือเพิ่มประสิทธิภาพ

13
ยังอ่านได้ง่ายกว่าโค้ดส่วนใหญ่รุ่นเยาว์ของเรา
corsiKa

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

นอกจากนี้บรรทัดสุดท้ายของคำตอบของคุณดูเหมือนโปรแกรมฟิชชัน;)
C0deH4cker

12

CJam, 42 41 ไบต์

ri]{_{:X,:)_few:+W%{1bX=}=}%{,(},e_}h]e_,

การสำรวจเส้นทางแรกของ Breadth อย่างง่ายและเงื่อนไขการหยุดของระดับถัดไปที่ว่างเปล่า

มันทำงานอย่างไร :

ri]                                       e# This represents the root of the fissile tree
   {                               }h     e# Now we run a do-while loop
    _{                    }%              e# Copy the nodes at the current level and map them
                                          e# via this code block to get next level nodes
      :X,:)                               e# Store the node value in X and get array [1..X]
           _few                           e# Copy the array and get continuous slices of
                                          e# length 1 through X from the array [1..X]
               :+W%                       e# Right now, we have an array of array with each
                                          e# array containing slice of same length. We join
                                          e# those arrays and reverse them to get slices of
                                          e# higher length in front of lower lengths
                   {1bX=}=                e# Choose the first slice whose sum is same as X
                                          e# The reversal above makes sure that we give
                                          e# preference to slice of higher length in case of
                                          e# multiple slices add up to X
                            {,(},         e# Filter out slices of length 1 which basically
                                          e# mean that the current node cannot be split up
                                 e_       e# Join all slices in a single array. This is our
                                          e# next level in the Fissile tree. If this is empty
                                          e# it means that all no further node can be
                                          e# decomposed. In an {}h do-while loop, this fact
                                          e# itself becomes the stopping condition for the
                                          e# loop
                                     ]e_, e# Wrap all levels in an array. Flatten the array
                                          e# and take its length

ลองออนไลน์ได้ที่นี่


นี่อาจจะสามารถเล่นกอล์ฟได้ประมาณ 35 ไบต์ ฉันพยายามที่จะคิดออกว่า ..
เพิ่มประสิทธิภาพ

10

Python 3, 112 ไบต์

def f(n,c=0):
 d=n-c;s=(n-d*~-d/2)/d
 return(s%1or s<1)and f(n,c+1)or+(d<2)or-~sum(f(int(s)+i)for i in range(d))

บันทึก 4 ไบต์ด้วย @FryAmTheEggman

คำอธิบายมาในภายหลัง ...

ความเป็นจริงโบนัส:พลังของ 2 ทุกคนมีจำนวนฟิชชันที่ 1 นี่เป็นเพราะผลรวมของลำดับความยาวคู่นั้นมักจะเป็นผลรวมของตัวเลขกลางสองตัวซึ่งเป็นเลขคี่คูณด้วยความยาวครึ่งหนึ่งของลำดับซึ่งเป็นจำนวนเต็ม . ผลรวมของลำดับความยาวคี่คือหมายเลขกลางคูณด้วยความยาวของลำดับซึ่งเป็นเลขคี่ ดังนั้นเนื่องจากพลังของ 2 จึงไม่มีตัวหารที่แปลกจึงสามารถแสดงออกได้เป็นผลรวมของตัวมันเองเท่านั้น


2 + 3 + 4 + 5 = 14 ซึ่งไม่แปลก อาร์กิวเมนต์ของคุณสำหรับลำดับความยาวเท่ากันควรเปลี่ยนเป็น "ผลรวมของลำดับความยาวคู่คือผลรวมของตัวเลขกลางสองตัวซึ่งเป็นเลขคี่คูณด้วยความยาวครึ่งหนึ่ง" ส่วนที่เหลือของคำสั่งของคุณจะไม่ได้รับผลกระทบ
Bruno Le Floch

@BrunoLeFloch ขอบคุณ! การแก้ไข
Randomra

ชื่อของคุณไม่ควรสะท้อนการปรับปรุงหรือไม่ เช่น <strike> 117 </strike> <strike> 113 </strike> 112
corsiKa

@corsiKa ฉันมักจะทำเพื่อการปรับปรุงที่สำคัญเท่านั้น จะมีตัวเลขที่ทับซ้อนกันมากเกินไป
Randomra

8

Python 2, 111 102 97 ไบต์

ค่อนข้างอ่านได้:

def f(n,c=0):a=n-c;b=n-a*~-a/2;return 1/a or-~sum(map(f,range(b/a,b/a+a)))if b>b%a<1else f(n,c+1)

ไม่ให้สามารถอ่านได้:

def f(n,a=0):b=n-a*~-a/2;return b>0and(f(n,a+1)or b%a<1and(1/a or-~sum(map(f,range(b/a,b/a+a)))))

ทั้ง 97 ไบต์

bคือnลบด้วย(a-1)thเลขสามเหลี่ยม หากb % a == 0แล้วnคือผลรวมของหมายเลขติดต่อกันเริ่มต้นจากab


8
ฉันเคยคิดว่า Python เป็นภาษาที่อ่านได้โดยทั่วไปจนกระทั่งฉันเข้าร่วม PPCG
Alex A.

ฉันคิดว่าคุณต้องปรับปรุงคำจำกัดความของคุณที่สามารถอ่านได้ .. : P
เครื่องมือเพิ่มประสิทธิภาพ

งูหลาม 2 1elseไม่อนุญาตให้ ทางออกที่ 2 เท่านั้นที่ใช้งานได้ มันไม่ได้จนกว่า Python 3 ที่elseสามารถติดตามตัวเลขได้ทันที
mbomb007

@ mbomb007 สำหรับความรู้ของฉันมันใช้งานได้ดีจาก 2.7.8 เป็นต้นไป
Sp3000

ตกลงฉันใช้ 2.7.2
mbomb007

7

Python 2, 86

f=lambda n,R={1}:n-sum(R)and f(n,R^{[min(R),max(R)+1][n>sum(R)]})or-~sum(map(f,R-{n}))

หักกอล์ฟ:

def f(n,R={1}):
    d=sum(R)-n
    if d==0:return (sum(map(f,R-{n}))
    if d<0:return f(n,R|{max(R)+1})
    if d>0:return f(n,R-{min(R)})

nความคิดคือการทดสอบวิ่งที่มีศักยภาพของจำนวนเต็มติดต่อกันที่จะสรุปผล การรันจะถูกเก็บโดยตรงเป็นชุดโดยตรงRแทนที่จะผ่านจุดปลาย

เราตรวจสอบว่าผลรวมของการวิ่งปัจจุบันเปรียบเทียบกับผลรวมที่ต้องการnผ่านความแตกต่างได้อย่างไร

  • หากผลรวมมีขนาดใหญ่เกินไปเราจะตัดองค์ประกอบที่เล็กที่สุดในการวิ่ง
  • หากผลรวมมีขนาดเล็กเกินไปเราจะขยายระยะเวลาโดยเพิ่มให้ใหญ่ขึ้นเป็น 1
  • หากผลรวมนั้นถูกต้องเราจะfเรียกคืนทำแผนที่ไปยังการทำงานการรวมและการเพิ่ม 1 สำหรับโหนดปัจจุบัน หากการดำเนินการคือ{n}เราได้ลองหาจำนวนเงินที่เป็นไปได้ที่ไม่สำคัญทั้งหมดหยุดการสอบถามซ้ำโดยลบnครั้งแรก

ขอบคุณ Sp3000 สำหรับการบันทึก 3 ตัวอักษร


7

Python 2, 85

ฉันภูมิใจในคำตอบนี้มากเพราะใช้เวลานับสิบวินาทีสำหรับ n = 9 และ 5-10 นาทีสำหรับ n = 10 ในการตีกอล์ฟนี่ถือว่าเป็นคุณสมบัติที่พึงประสงค์ของโปรแกรม

f=lambda n,a=1,d=1:a/n or[f(a)+f(n-a,1+1%d*a)+1/d,f(n,a+d/n,d%n+1)][2*n!=-~d*(2*a+d)]

นอกจากนี้ยังมีเวอร์ชั่นลัดวงจรที่ใช้เวลาไม่นานและใช้จำนวนไบต์เท่ากัน:

f=lambda n,a=1,d=1:a/n or~d*(2*a+d)+n*2and f(n,a+d/n,d%n+1)or f(a)+f(n-a,1+1%d*a)+1/d 

อาจเร็วกว่า แต่อย่างน้อยก็เกินขีด จำกัด การเรียกซ้ำเริ่มต้นเมื่อ n ไปเกิน 40 เล็กน้อย

ความคิดที่จะทำในการค้นหาแรงเดรัจฉานสำหรับตัวเลขaและdดังกล่าวว่าa + a+1 + ... + a+d == nในระหว่างวันที่ 1 nค่าและ f(n,a+d/n,d%n+1)สาขาของ recursion ลูปผ่าน(a, d)คู่ ในกรณีที่ความเสมอภาคเป็นที่พอใจฉันจัดการเพื่อหลีกเลี่ยงการmap(range(...))โทรที่มีราคาแพงโดยแยกออกเป็นสองสาขาโดยไม่คำนึงว่าลำดับนั้นจะนานแค่ไหน ตัวเลขa+1ผ่านdจะถูกรวมเข้าในการเรียกหนึ่งครั้งfโดยการตั้งค่าaพารามิเตอร์เพื่อไม่สามารถใช้วิธีการแยกลำดับที่แตกต่างกันได้


มันทำงานอย่างไร
xnor

"ฉันภูมิใจในคำตอบนี้มากเพราะใช้เวลานับสิบวินาทีสำหรับ n = 9 และ 5-10 นาทีสำหรับ n = 10 ในการเขียนโค้ดนี่ถือว่าเป็นคุณลักษณะที่พึงประสงค์ของโปรแกรม" +1 สำหรับสิ่งนั้น
Soham Chowdhury

6

Haskell, 76 69 ไบต์

f x=head$[1+sum(map f[y..z])|y<-[1..x-1],z<-[y..x],sum[y..z]==x]++[1]

การใช้งาน:

*Main> map f [1..40]
[1,1,3,1,5,6,5,1,6,7,12,10,12,11,12,1,8,16,14,17,18,18,23,13,21,18,22,23,24,19,14,1,22,20,23,24,31,27,25,26]

มันทำงานอย่างไร:

[  [y..z] |y<-[1..x-1],z<-[y..x],sum[y..z]==x]

           make a list of lists with all consecutive integers (at least 2 elements)
           that sum up to x, sorted by lowest number, e.g. 9 -> [[2,3,4],[4,5]].

1+sum(map f[...]) 

           recursively calculate the Fission Number for each list

[...]++[1]

           always append the 1 to the list of Fission Numbers.

head

           take the first element, which is either the Fission Number of the
           longest list or if there's no list, the 1 appended in the step before.  

3

เรติน่า 66 ไบต์

^|$
,
(`,(1+?)(?=(?<1>1\1)+\D)
$0;
+)`,(1*);1\1
,$1,1$1;
^,|1

.
1

ใช้อินพุตและพิมพ์เอาต์พุตใน unary

คุณสามารถใส่แต่ละบรรทัดในไฟล์เดียวหรือเรียกใช้รหัสเช่นเดียวกับ-sธง เช่น:

> echo -n 1111111|retina -s fission
11111

คำอธิบาย:

  • เราเก็บรายการตัวเลขที่คั่นด้วยจุลภาคเพื่อแยก
  • สำหรับทุกหมายเลขเราจะใช้ค่าเริ่มต้นที่เล็กที่สุดซึ่งสามารถสร้างการแยกที่ถูกต้องและกำหนดขอบเขตจากส่วนที่เหลือด้วยเครื่องหมายอัฒภาค
  • หากมีเครื่องหมายอัฒภาคอยู่ในตัวเลขเราจะเปลี่ยนเป็นเครื่องหมายจุลภาคและคั่นส่วนถัดไปที่เหมาะสม (ความยาวขององค์ประกอบก่อนหน้า + 1) ส่วนหนึ่งของตัวเลข
  • เราทำซ้ำขั้นตอนที่ 2 และ 3 จนกระทั่งมีการเปลี่ยนแปลงเกิดขึ้น
  • เราได้เครื่องหมายจุลภาคสำหรับทุก ๆ leaf และเครื่องหมายอัฒภาคสำหรับทุกโหนดด้านในบวกด้วยเครื่องหมายจุลภาคพิเศษเพราะเราเริ่มด้วยเครื่องหมายจุลภาคสอง ดังนั้นเราจึงลบเครื่องหมายจุลภาคและส่วนของตัวเลข1และแปลงส่วนที่เหลือ1เป็น

สถานะของสตริงตลอดกระบวนการด้วยอินพุต11111111111111 (unary 14):

,11111111111111,
,11;111111111111,
,11,1;11,1111,11;111;,
,11,1,11;,1111,11,1;11;;,
,11,1,11;,1111,11,1,11;;;,
,,;,,,,;;;,
11111111111

ขอบคุณมากสำหรับ @MartinButtner สำหรับความช่วยเหลือในการแชท!


3

CJam (43 ไบต์)

qi,{):X),_m*{{_)*2/}/-X=}=~\,>0\{~$+}/)}%W=

การสาธิตออนไลน์

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


พรุ่งนี้ฉันจะได้ดูอย่างใกล้ชิด แต่สำหรับการเริ่มต้นคุณไม่จำเป็นต้อง,เริ่มต้น /และ%อีกสองสามคนเปลี่ยนตัวเลขให้อยู่ในช่วงโดยปริยาย
Martin Ender

,_m*2m*สามารถถูกแทนที่ด้วย สูตรก้าวหน้าเลขคณิตสามารถถูกแทนที่ด้วย~,>:Y_,+:+และกลายเป็น~\,>0\ !Yสุดท้ายหากคุณใช้{}#แทน{}=คุณไม่จำเป็นต้องหลังจากที่) Xวางไว้ทั้งหมดเข้าด้วยกัน:ri{):X2m*{~,>:Y_,+:+X=}#!Y{~$+}/)}%W=
เดนนิส

2

ไปที่ 133 ไบต์

func 算(n int)int{Σ:=1;for i:=0;i<n;i++{for j:=0;j<n;j++{if i*i+i-j*j-j==2*n{for k:=j+1;k<=i;k++{Σ+=算(k)};j,i=n,n}}};return Σ}

นี่คือรหัสกอล์ฟครั้งแรกของฉันขอโทษถ้าฉันทำผิดพลาด

สิ่งนี้ใช้แนวคิดที่ว่า "การรวมกัน" ฟิชไซล์สามารถมองเห็นได้ว่าเป็นความแตกต่างระหว่างสองลำดับของจำนวนเต็มสั่ง ตัวอย่างเช่นใช้ "การจัดองค์ประกอบ" แยกส่วนสำหรับหมายเลข 13 มันคือ 6,7 แต่มันสามารถเห็นได้ว่าเป็นผลรวมของจำนวนเต็ม 1 ... 7 ลบผลรวมของจำนวนเต็ม 1 ... 5

  A: 1 2 3 4 5 6 7  sum = 28
  B: 1 2 3 4 5      sum = 15 
A-B:           6 7  sum = 13, which is also 28-15 = 13

เรียกคืนสูตรจากสมัยเรียนของเกาส์รวม 1 ... n = (n ^ 2 + n) / 2 เพื่อหาองค์ประกอบของจำนวนเต็มตามลำดับสำหรับ n เราอาจพูดได้ว่าเรากำลังค้นหา 'จุดสิ้นสุด' p และ q ตามช่วง 1 ... n ดังนั้น (p ^ 2 + p) / 2 - ( q ^ 2 + q) / 2 = n ในตัวอย่างข้างต้นเราจะค้นหา 'จุดปลาย' 5 และ 7 เพราะ 7 ^ 2 + 7 = 56/2, 5 ^ 2 + 5 = 30/2, 56 / 2-30 / 2 = 28-15 = 13

ขณะนี้มีวิธีที่เป็นไปได้หลายวิธีในการรวบรวมจำนวนฟิชไซล์ตามที่ Martin ระบุ 9 = 2 + 3 + 4 แต่ยัง 4 + 5 แต่ดูเหมือนชัดเจนว่าลำดับการเริ่มต้นที่ "ต่ำที่สุด" จะยาวที่สุดเพราะใช้เวลามากกว่า ตัวเลขน้อย ๆ ที่จะรวมกันเป็นจำนวนมากกว่าจะเป็นตัวเลขขนาดกลาง (ฉันไม่มีข้อพิสูจน์ที่น่าเสียดาย)

ดังนั้นในการค้นหาองค์ประกอบของ 9 ให้ทดสอบ 'จุดสิ้นสุดคู่', p และ q, ทำซ้ำทั้ง p และ q แยกจาก 0 ถึง 9 และทดสอบว่า p ^ p + p / 2 - q ^ 2 + q / 2 = 9. หรือง่ายกว่านั้นคูณสมการด้วย 2 เพื่อหลีกเลี่ยงปัญหาการหารของการปัดเศษและเก็บคณิตศาสตร์ทั้งหมดเป็นจำนวนเต็ม จากนั้นเรากำลังค้นหา p และ q เช่นนั้น (p ^ p + p) - (q ^ q + q) = 9 * 2 การจับคู่ครั้งแรกที่เราพบจะเป็นจุดสิ้นสุดการแต่งฟิซไซล์เพราะตามที่ระบุไว้กลุ่มที่มีตัวเลขต่ำที่สุดจะยาวที่สุดและเรากำลังค้นหาจากต่ำไปสูง (0 ถึง 9) เราแตกออกจากวงทันทีที่เราพบการแข่งขัน

ตอนนี้ฟังก์ชั่นแบบเรียกซ้ำค้นหา p 'fissile end points' และ p สำหรับ q ที่กำหนดจากนั้นให้เรียกคืนตัวเองสำหรับ 'เด็ก' แต่ละคนในต้นไม้จาก p ถึง q สำหรับ 9 มันจะหา 1 และ 4 (20-2 = 18) จากนั้นมันจะเรียกตัวเองอีกครั้งใน 2, 3 และ 4 โดยรวมผลลัพธ์ สำหรับตัวเลขอย่างที่ 4 จะไม่พบการจับคู่ดังนั้นจะส่งกลับ '1' สิ่งนี้อาจสั้นลงได้ แต่นี่เป็นเหมือนโปรแกรมโปรแกรมที่สามของฉันและฉันไม่มีผู้เชี่ยวชาญด้านการสอบถามซ้ำ

ขอบคุณที่อ่าน.


เยี่ยมมาก! แต่ทำไม Unicode ฟังก์ชั่น / ชื่อตัวแปร นั่นเป็นค่าใช้จ่ายที่ไม่จำเป็นของไบต์และแน่นอนว่าคุณสามารถใช้ตัวอักษรปกติได้บ้าง?
Martin Ender

ขอบคุณสำหรับความคิดเห็นของคุณ แต่ผมถามตัวเองว่าทำไมไม่นับตัวอักษรแทนการไบต์ :)
don สดใส

เพราะสิ่งเหล่านี้เป็นกฎเริ่มต้นที่นี่ :) เหตุผลที่เรามักจะนับไบต์และไม่ใช่ตัวละครเป็นเพราะอย่างอื่นเกิดขึ้นซึ่งสนุกเล็กน้อยสำหรับทุกฝ่ายที่เกี่ยวข้อง ;) (ที่กล่าวว่าผู้เขียนท้าทายใด ๆเป็นอิสระในการระบุการนับตัวละครแทนของไบต์ แต่ฉันเฉพาะไม่ได้).
มาร์ตินเอนเดอร์

1

CJam, 40 35 33 ไบต์

ri{__,f-_few:+{1b1$=}=|{F}*}:F~],

ขอบคุณ @Optimizer สำหรับการแนะนำfewซึ่งบันทึกไว้ 2 ไบต์

ลองใช้ออนไลน์ในล่าม CJam

มันทำงานอย่างไร

ri      e# Read an integer from STDIN.
{       e# Define function F(X):
  _     e# Push X.
  _,    e# Push [0 ... X-1].
  f-    e# Subract each from X. Pushes Y := [X ... 1].
  _few  e# Push all overlapping slices of Y of length in Y.
  :+    e# Consolidate the slices of different lenghts in a single array.
  {     e# Find the first slice S such that...
    1b  e#   the sum of its elements...
    1$= e#   equals X.
  }=    e#   Since Y is in descending order, the first matching slice is also the longest.
  |     e# Set union with [X]. This adds X to the beginning of the S if S != [X].
  {F}*  e# Execute F for each element of S except the first (X).
}:F     e#
~       e# Execute F for the input.
],      e# Count the integers on the stack.

หากคุณรวมครึ่งแรกของฉันเข้ากับครึ่งหลังคุณจะได้ 34:ri{_,:)_few:+W%{1b1$=}=|{F}*}:F~],
เครื่องมือเพิ่มประสิทธิภาพ

@Optimizer: ดี ที่ช่วยให้การปรับปรุงเพิ่มเติม ขอบคุณ!
Dennis
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.