11 = (1 + 2 + 3 + 4 + 5) - (1 + 2 + 3) + (6) - (4)


35

รับจำนวนเต็มบวกNงานของคุณคือส่งคืนจำนวนขั้นตอนที่ต้องการโดยอัลกอริทึมต่อไปนี้เพื่อไปถึงN :

  1. หาจำนวนที่น้อยที่สุดสามเหลี่ยมT ฉันเช่นว่าT ฉัน  ≥ N สร้างรายการที่สอดคล้องกันL = [1, 2, ... , ผม]

  2. ในขณะที่ผลรวมของเงื่อนไขของLมากกว่าNให้ลบคำแรกออกจากรายการ

  3. หากผลรวมของเงื่อนไขของLน้อยกว่าNให้เพิ่มค่าiและผนวกเข้ากับรายการ ดำเนินการต่อด้วยขั้นตอนที่ 2

เราจะหยุดทันทีที่Nถึง เฉพาะขั้นตอนแรกเท่านั้นที่ดำเนินการอย่างเป็นระบบ ขั้นตอนที่ # 2 และ # 3 อาจไม่ได้รับการดำเนินการเลย

ตัวอย่าง

ด้านล่างนี้เป็นตัวอย่างสำหรับN = 11 :

ตัวอย่าง

ดังนั้นการส่งออกคาดว่าN = 11คือ4

ตัวอย่างอื่น ๆ :

  • N = 5 - เราเริ่มต้นด้วย T 3 = 1 + 2 + 3 = 6ตามด้วย 2 + 3 = 5 ผลลัพธ์ที่คาดหวัง:2
  • N = 10 - เฉพาะขั้นตอนแรกคือต้องเนื่องจาก 10เป็นจำนวนสามเหลี่ยม: T 4 = 1 + 2 + 3 + 4 = 10 ผลลัพธ์ที่คาดหวัง:1

100 ค่าแรก

ด้านล่างนี้เป็นผลลัพธ์สำหรับ1 ≤ N ≤ 100 :

  1,  2,  1,  4,  2,  1,  2, 10,  2,  1,  4,  2,  6,  2,  1, 22,  8,  2, 10,  2,
  1,  2, 12,  6,  2,  4,  2,  1, 16,  2, 18, 50,  2,  6,  2,  1, 22,  6,  2,  4,
 26,  2, 28,  2,  1,  8, 30, 16,  2,  6,  4,  2, 36,  2,  1,  2,  4, 12, 40,  2,
 42, 14,  2,108,  2,  1, 46,  2,  6,  4, 50,  2, 52, 18,  2,  4,  2,  1, 56, 12,
  2, 20, 60,  4,  2, 22, 10,  2, 66,  2,  1,  4, 10, 24,  2, 40, 72,  8,  2,  6

กฎระเบียบ

  • คุณสามารถเขียนโปรแกรมเต็มรูปแบบหรือฟังก์ชั่นที่พิมพ์หรือส่งคืนผลลัพธ์
  • คุณต้องประมวลผลN ≤ 65536ในเวลาน้อยกว่าหนึ่งนาทีสำหรับฮาร์ดแวร์ระดับกลาง
  • ให้เวลาเพียงพอโปรแกรม / ฟังก์ชั่นของคุณควรทำงานในทางทฤษฎีสำหรับค่าใด ๆ ของNที่ได้รับการสนับสนุนโดยภาษาของคุณ หากไม่เป็นเช่นนั้นโปรดอธิบายว่าเพราะอะไรในคำตอบของคุณ
  • นี่คือรหัสกอล์ฟดังนั้นคำตอบที่สั้นที่สุดในจำนวนไบต์ชนะ!

ที่เกี่ยวข้อง (ฉันสงสัยว่าคุณรู้แล้วเกี่ยวกับอันนี้ แต่เพิ่งโพสต์ไว้สำหรับลูกหลาน)
ETHproductions

ค่าสูงสุดของ N ที่เราต้องจัดการคืออะไร?
ลุ

@Luke โปรดดูกฎที่อัปเดต
Arnauld

คำตอบ:


4

เยลลี่ , 29 31 ไบต์

ÆDµ’H+Ṛ%1$ÐḟṂ
>TḢ_@Ç}‘Ḥ
R+\ðċȯç

ลิงก์ monadic ที่ส่งคืนผลลัพธ์ (N = 65536 ใช้เวลาน้อยกว่าสองวินาที)

ลองออนไลน์!

อย่างไร?

สำหรับคำอธิบายอย่างละเอียดของขั้นตอนวิธีดูโพสต์ที่ยอดเยี่ยมโดยมาร์ตินเอนเดอร์

ÆDµ’H+Ṛ%1$ÐḟṂ - Link 1, smallest natural number, M, that satisfies the below*, N
              - * N = T(M) - T(i) for some non-negative integer i <= M
ÆD            - divisors of N
  µ           - monadic chain separation, call that d
   ’          - increment d (vectorises)
    H         - halve (vectorises
      Ṛ       - reverse d
     +        - add (vectorises)
          Ðḟ  - filter discard if:
       %1$    -   modulo one is truthy (those which are the result of even divisors)
            Ṃ - minimum

>TḢ_@Ç}‘Ḥ - Link 2, evaluate result for non-triangular: list of T(1) to T(N), N
>         - T(i) > N
 T        - truthy indexes
  Ḣ       - head (yields the first i for which T(i) > N)
     Ç}   - call last link (1) as a monad converted to a dyad using the right argument
   _@     - subtract with reverse @rguments
       ‘  - increment
        Ḥ - double 

R+\ðċȯç - Main link: N
R       - range -> [1,2,...,N]
 +\     - reduce with addition -> [1,3,6,10,...T(N)]
   ð    - dyadic chain separation, call that t
    ċ   - count occurrences of N in t (1 if N is triangular else 0)
      ç - call last link (2) as a dyad(t, N)
     ȯ  - or

การนำไปใช้แบบเต็มโปรแกรม 29 ไบต์ฉันสร้างอัลกอริทึมที่อธิบายใช้เวลา 4 นาที 30 สำหรับ N = 65536 บนแล็ปท็อปของฉันดังนั้นฉันคิดว่ามันจะไม่นับ

Ṁ‘ṭµS<³µ¿
ḊµS>³µ¿
0®Ḃ‘©¤ĿÐĿL’

ใช้ a while loop สำหรับทุกขั้นตอน 3 และนำกลับมาใช้ใหม่เนื่องจากขั้นตอนที่ 1 มีความยาวเท่ากับสิ่งที่ฉันสามารถจัดการด้วยการเริ่มต้นรายการเนื่องจากไม่มีการตรวจสอบในขั้นตอนที่ 3 หมายถึงการสร้างรายการจนกว่าจะไม่มีอะไรเหลืออยู่แล้วหาดัชนีแรกของค่า

ḊµS>³µ¿
Ṁ‘ṭ
Ḥ½_.ĊR®Ḃ‘©¤ĿÐĿS€i

25

Mathematica, 79 ไบต์

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]-2⌊(2#)^.5+.5⌋+⌈Sqrt[8#+1]~Mod~1⌉&

คำอธิบาย

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

ดังนั้นฉันอ้างว่าลำดับที่เราควรจะคำนวณคือ:

f (n) = 2 * ( A212652 (n) - A002024 (n)) + 1 + A023532 (n-1)

อีกวิธีหนึ่งคือf (n) = 1ถ้าnเป็นตัวเลขสามเหลี่ยมและf (n) = 2 * ( A212652 (n) - A002024 (n) + 1)มิฉะนั้น

ในนิพจน์แรกA023532เพียงเข้ารหัสสองกรณีนี้ อีกสองลำดับ (บวก 1) คือความแตกต่างระหว่างจำนวนเต็มที่มากที่สุดkในการสลายตัวที่ยาวที่สุดของnเป็นจำนวนเต็มต่อเนื่อง(k-i + 1) + (k-i + 2) + ... + k = nและ ที่ใหญ่ที่สุดจำนวนเต็มเจเพื่อที่1 + 2 + ... + J <n

ในคำค่อนข้างง่ายนี่คือวิธีการที่เราหาคำตอบสำหรับตัวเลขที่ไม่ใช่รูปสามเหลี่ยม: แรกพบที่ใหญ่ที่สุดจำนวนสามเหลี่ยมT Jซึ่งเป็นน้อยกว่าn จากนั้นjคือจำนวนเต็มสุดท้ายที่เพิ่มระหว่างขั้นตอนที่1 (เพราะหลังจากเพิ่มj + 1เราจะได้เกินn ) จากนั้นย่อยสลายnเข้ามาเป็นจำนวนมาก (หรือเล็ก) จำนวนเต็มติดต่อกันเป็นไปได้และเรียกสูงสุดในหมู่ตัวเลขเหล่านี้k ผลที่ได้คือเพียงแค่2 * (kJ) เหตุผลที่เข้าใจง่ายสำหรับสิ่งนี้คือค่าสูงสุดของการสลายตัวจะเพิ่มขึ้น1ขั้นทุก ๆ ก้าวและเราหยุดเมื่อถึงเค .

เราจำเป็นต้องแสดงสี่สิ่งเพื่อพิสูจน์ว่างานนี้:

  1. f (n) = 1สำหรับตัวเลขสามเหลี่ยม นี่เป็นเรื่องเล็กน้อยเพราะขั้นตอนแรกจะวนซ้ำผ่านตัวเลขสามเหลี่ยมทั้งหมด หากเรากดnในระหว่างกระบวนการนี้เราก็เสร็จสิ้นและมีเพียงหนึ่งขั้นตอนในการคำนวณ
  2. สำหรับหมายเลขอื่น ๆ เราจะสิ้นสุดหลังจากขั้นตอนการลบเสมอโดยไม่ต้องทำตามขั้นตอนการแทรก นั่นหมายความว่าf (n)อื่น ๆ ทั้งหมดจะเท่ากัน
  3. ในแต่ละขั้นตอนการแทรกหลังจากครั้งแรกเราจะเพิ่มหมายเลขเดียวเท่านั้น สิ่งนี้รับประกันได้ว่าเราจะไปถึงการสลายตัวซึ่งรวมถึงkหลังจากขั้นตอนkjคู่
  4. การสลายตัวสุดท้ายของnที่เราได้รับคือการสลายตัวที่ยาวที่สุดที่เป็นไปได้ของnเป็นจำนวนเต็มต่อเนื่องหรือในคำอื่น ๆ ก็คือการสลายตัวของn ที่มีค่าสูงสุดต่ำสุดในจำนวนที่สรุป กล่าวอีกนัยหนึ่งจำนวนสุดท้ายที่เราเพิ่มลงในผลรวมนั้นคือA212652 (n)เสมอ

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

สมมติว่าเราสิ้นสุดในขั้นตอนการแทรกถึงnหลังจากเพิ่มค่าpให้กับผลรวม นั่นหมายความว่าก่อนขั้นตอนการแทรกนี้ค่าคือnp ( หรือน้อยกว่าหากเราเพิ่มหลายค่าพร้อมกัน) แต่ขั้นตอนการแทรกนี้ถูกนำหน้าด้วยขั้นตอนการลบ (เนื่องจากเราไม่สามารถกดปุ่มnระหว่างขั้นตอนที่ 1) ค่าสุดท้ายQเราเอาออกในระหว่างขั้นตอนการลบนี้คือจำเป็นต้องน้อยกว่าPเนื่องจากวิธีการทำงานของอัลกอริทึม แต่นั่นหมายความว่าก่อนที่เราจะลบqเรามีn-p + q ( หรือน้อยกว่า ) ซึ่งน้อยกว่าn. แต่นั่นเป็นข้อขัดแย้งเพราะเราจะต้องหยุดลบจำนวนเต็มเมื่อเรากดn-p + qแทนที่จะลบqอีกตัว นี่เป็นการพิสูจน์จุด (2) ด้านบน ตอนนี้เรารู้แล้วว่าเรามักจะจบลงด้วยการลบและดังนั้นตัวเลขที่ไม่ใช่รูปสามเหลี่ยมทั้งหมดจึงมีผลลัพธ์

ต่อไปเราจะพิสูจน์ (3) ว่าแต่ละขั้นตอนการแทรกสามารถแทรกได้เพียงหนึ่งค่าเท่านั้น นี่เป็นข้อพิสูจน์ที่สำคัญของ (2) เราแสดงให้เห็นว่าหลังจากเพิ่มหนึ่งค่าที่เราไม่สามารถตี n ได้อย่างแน่นอนและเนื่องจากการพิสูจน์ว่าใช้ความไม่เท่าเทียมกันเราก็ไม่สามารถจบลงต่ำกว่าn ได้ (ตั้งแต่นั้นn-p + qจะยังน้อยกว่าnและเราไม่ควรลบออก หลายค่าในตอนแรก) ดังนั้นเมื่อใดก็ตามที่เราเพิ่มค่าเดียวเราจะรับประกันเกินnเพราะเราต่ำกว่าnโดยการลบค่าที่น้อยลง ดังนั้นเราจึงทราบว่าจุดสูงสุดของผลรวมเพิ่มขึ้น1ทุกขั้นตอนอื่น ๆ เรารู้ค่าเริ่มต้นของปลายด้านบนนี้ (มันคือm ที่เล็กที่สุดเช่นนั้นT m > n ) ตอนนี้เราแค่ต้องหาจุดปลายด้านบนนี้เมื่อเราไปถึงผลรวมสุดท้าย จากนั้นจำนวนขั้นตอนจะต่างกันสองเท่า (บวก 1)

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

บอกว่าการสลายตัวที่เร็วที่สุด / ยาวที่สุดที่เป็นไปได้ของnคือa + (a + 1) + ... (b-1) + b , a ≤ bและพูดว่าอัลกอริธึมข้าม นั่นหมายความว่าในเวลาที่เพิ่มb , aต้องไม่เป็นส่วนหนึ่งของผลรวมอีกต่อไป หากเป็นส่วนหนึ่งของผลรวมของแล้วเราจะมีn ≤ sในขณะนั้น ดังนั้นผลรวมมีเพียงค่าจากaถึงbซึ่งเท่ากับnและเราหยุด (ดังนั้นเราจึงไม่ข้ามการสลายตัวนี้) หรือมีค่าอย่างน้อยหนึ่งค่าที่น้อยกว่าaในผลรวมชนะกรณีใดn <sและค่านั้นจะถูกลบออกจนกว่าเราจะตียอดรวมที่แน่นอน (อีกครั้งการสลายตัวไม่ได้ข้ามไป) ดังนั้นเราจะต้องกำจัดก่อนที่จะเพิ่มข แต่นั่นหมายความว่าเราจะต้องไปให้ถึงในสถานการณ์ที่เป็นส่วนประกอบที่เล็กที่สุดของผลรวมและที่ใหญ่ที่สุดไม่ได้เป็นเลย อย่างไรก็ตาม ณ จุดนั้นเราไม่สามารถลบaได้เนื่องจากผลรวมนั้นน้อยกว่าn (เนื่องจากbหายไป) ดังนั้นเราจึงต้องเพิ่มค่าก่อนจนกว่าเราจะเพิ่มbและกดnอย่างแน่นอน สิ่งนี้พิสูจน์ได้ (4)

ดังนั้นการสิ่งเหล่านี้ร่วมกัน: เรารู้ว่าคู่แรกของขั้นตอนที่ช่วยให้เรามีค่าสูงสุดของA002024 (n) เรารู้ว่าค่าสูงสุดของการสลายตัวสุดท้ายคือ A212652 (n) และเรารู้ว่าค่าสูงสุดนี้เพิ่มขึ้นหนึ่งครั้งในทุกขั้นตอน ดังนั้นการแสดงออกสุดท้ายคือ 2 * ( A212652 (n) - A002024 (n) + 1) สูตรนี้ใช้งานได้กับตัวเลขสามเหลี่ยมยกเว้นว่าสำหรับเราต้องการเพียง 1 ขั้นตอนแทน 2 ซึ่งเป็นสาเหตุที่เราแก้ไขผลลัพธ์ด้วยฟังก์ชันตัวบ่งชี้ของตัวเลขสามเหลี่ยม

ในที่สุดสำหรับการดำเนินการ สำหรับลำดับเดิมฉันใช้สูตรMIN (คี่ d | n; n / d + (d-1) / 2)จาก OEIS มันกลับกลายเป็นบันทึกสองสามไบต์ถ้าเราใช้ตัวคูณ2ในการแสดงออกนี้เพื่อให้ได้ MIN (เลขคี่ | n; 2n / d + d-1) , เพราะนั่น-1แล้วยกเลิกด้วย+1ในเวอร์ชันแรกของฉัน ของf (n)ซึ่งเข้ารหัสสองกรณีโดยตรงสำหรับตัวเลขสามเหลี่ยมและไม่ใช่สามเหลี่ยม ในรหัสนี่คือ:

Min[2#/(d=Divisors@#~Cases~_?OddQ)+d]

สำหรับลำดับหลัง ( 1, 2, 2, 3, 3, 3, ...) เราสามารถใช้รูปแบบปิดแบบง่าย:

⌊(2#)^.5+.5⌋

และสุดท้ายฟังก์ชันอินดิเคเตอร์อินดิเคเตอร์ของตัวเลขสามเหลี่ยมคือ0เมื่อ8n + 1เป็นสี่เหลี่ยมจัตุรัส นี้สามารถแสดงใน Mathematica เป็น

⌈Sqrt[8#+1]~Mod~1⌉

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

ตั้งแต่ที่ฉันไปที่ปัญหาทั้งหมดนี้นี่คือพล็อตของลำดับถึง n = 1,000 (ฉันสามารถคำนวณ 100k ภายในสองสามวินาที แต่มันไม่แสดงข้อมูลเชิงลึกใด ๆ เพิ่มเติม):

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

อาจเป็นเรื่องที่น่าสนใจที่จะตรวจสอบความแตกต่างของเส้นตรงเหล่านั้น แต่ฉันจะปล่อยให้คนอื่น ...


ในที่สุดฉันก็ใช้เวลาอ่านคำตอบของคุณอย่างละเอียด อันนี้ยอดเยี่ยม โปรดทราบว่า (3) ได้ถูกสันนิษฐานไว้แล้วในอัลกอริทึม (ขั้นตอนที่ 3 คือถ้าไม่ใช่ในขณะที่ ) แต่หลักฐานได้รับการต้อนรับอย่างแน่นอน
Arnauld

@Arnauld ขอบคุณ :) ฉันต้องมองข้าม / เข้าใจผิด if / while สิ่งที่ดีมันไม่ได้สร้างความแตกต่างแล้ว
Martin Ender

7

Mathematica ขนาด 72 ไบต์

(For[l=u=c=k=0,k!=#,c++,If[#>k,While[#>k,k+=++u],While[#<k,k-=l++]]];c)&

ฟังก์ชั่นแท้รับอาร์กิวเมนต์จำนวนเต็ม

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

For[ ... ]

Forห่วง

l=u=c=k=0

การเริ่มต้น; set l(ด้านล่าง), u(ด้านบน), c(ตัวนับ) และk(ผลรวม) ถึง 0

k!=#

เงื่อนไข; ทำซ้ำในขณะที่kไม่เท่ากับอินพุต

c++

เพิ่ม; cเพิ่มเคาน์เตอร์

If[#>k,For[,#>k,,k+=++u],For[,#<k,,k-=l++]]

ร่างกาย

If[#>k, ... ]

หากอินพุตมากกว่าk:

While[#>k,k+=++u]

ในขณะที่การป้อนข้อมูลที่มีค่ามากกว่าk, เพิ่มขึ้นuและเพิ่มขึ้นโดยku

หากอินพุตไม่มากกว่าk:

While[#<k,k-=l++]

ในขณะที่การป้อนข้อมูลที่มีค่าน้อยกว่าkพร่องkโดยและเพิ่มขึ้นll

( ... ;c)

กลับมาcหลังจากวนซ้ำ


1
For[,...]While[...]เต้น
Martin Ender

5

Python 2 , 104 ไบต์

N=input();i=s=0;l=()
while N!=sum(l):exec'while sum(l)'+['<N:i+=1;l+=i,','>N:l=l[1:]'][s%2];s+=1
print s

ลองออนไลน์!

สลับระหว่างการเพิ่มคำศัพท์ลงในตอนท้ายของรายการและลบคำศัพท์จากจุดเริ่มต้น


5

Haskell , 70 63 68 64 ไบต์

แก้ไข:

  • -7 ไบต์: Got aกำจัดช่องว่างสองสัญญาณและวงเล็บบางส่วนโดยการกวนความรู้สึกของ แก้ไขข้อผิดพลาดในแต่ละคำอธิบาย
  • +5 ไบต์: Argh พลาดความต้องการ 65536 อย่างสมบูรณ์และปรากฎว่า (1) พลังของ 2 มีราคาแพงเป็นพิเศษเพราะมันจะได้รับผลกระทบเมื่อคุณไปถึงตัวเลขนั้นเอง (2) ดังนั้นจึงเป็นการรวมช่วงระยะยาว ล้อมรอบศูนย์) ตลอดเวลา แทนที่ผลรวมด้วยสูตรทางคณิตศาสตร์
  • -4 ไบต์: ปรับaและbเชิงเส้นเพื่อรับเงื่อนไขในสูตรการรวมที่จะยกเลิก

1#1 เป็นฟังก์ชั่นที่ไม่ระบุชื่อการรับและคืนค่าจำนวนเต็ม

(1#1) 100ใช้เป็น

1#1
(a#b)n|s<-a*a-b*b=sum$[a#(b+2)$n|s>8*n]++[(b#a)(-n)+1|s<8*n]

ลองออนไลน์!

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

  • (a#b)nแสดงถึงขั้นตอนการคำนวณปัจจุบัน a, bเป็นตัวเลขใน1, 3, 5, ..ขณะที่nสามารถเป็นได้ทั้งบวกหรือลบขึ้นอยู่กับขั้นตอน
    • เมื่ออยู่ในขั้นตอนที่ 1 หรือ 3 จะหมายถึงรายการ [(a+1)/2,(a+3)/2..(b-1)/2]-nและเป้าหมายของจำนวน
    • เมื่ออยู่ในขั้นตอนที่ 2 จะแสดงรายการและเป้าหมายของจำนวน[(b+1)/2,(b+3)/2..(a-1)/2]n
  • การติดต่อที่แปลก ๆ ระหว่างa, bและรายการต่าง ๆ เพื่อที่จะสามารถสรุปด้วยการแสดงออกสั้น ๆs=a*a-b*bและรายชื่ออยู่ในลำดับที่จะสามารถที่จะทำผลบวกกับการแสดงออกสั้น
    • ในขั้นตอนที่ 1 และ 3 นี่เป็นเช่นเดียวกับ s= -8*sum[(a+1)/2..(b-1)/2]นี้เป็นเช่นเดียวกับ
    • ในขั้นตอนที่ 2 s=8*sum[(b+1)/2..(a-1)/2]นี้เป็นเช่นเดียวกับ
  • การแยกย่อยทำได้โดยการมีรายการความเข้าใจที่สร้างองค์ประกอบในแต่ละกรณีเท่านั้นและรวมผลลัพธ์
    • ถ้าเป็นs>8*nเช่นนั้นbจะเพิ่มขึ้น 2 ก่อนที่จะเรียกซ้ำ
      • ในขั้นตอนที่ 1 และ 3 สิ่งนี้จะเพิ่มจำนวนรายการในขณะที่ในขั้นตอนที่ 2 จะทำให้รายการเล็กลง
    • ถ้าการs<8*nเรียกซ้ำนั้นเปลี่ยนขั้นตอนโดยการสลับaและbและปฏิเสธnและ 1 จะถูกเพิ่มไปยังผลลัพธ์
    • หากs==8*nแล้วทั้งสอง comprehensions รายการให้องค์ประกอบใด ๆ 0เพื่อให้รวมเป็น
  • (1#1) nหมายถึงการจำลอง "ระยะที่ 2" ก่อนที่จะเริ่มว่าทันทีที่ได้รับการเปลี่ยนแปลงที่จะขั้นตอนที่ 1 [1..0]=[]การสร้างรายชื่อจาก

4

PHP> = 7.0, 74 ไบต์

while($i=$r<=>$argn)for($s++;($r<=>$argn)==$i;)$r+=$i+1?-++$y:++$x;echo$s;

ใช้โอเปอเรเตอร์ยานอวกาศ

ลองออนไลน์!

ขยาย

while($i=$r<=>$argn) # if input is not equal sum of array
  for($s++;  # raise count steps
  ($r<=>$argn)==$i;)
  # so long as value compare to input has not change to lower/higher to higher/lower or equal  
    $r+=$i+1
      ?-++$y # if $i was higher remove the first integer
      :++$x;} # if $i was lower add the next highest integer     
echo$s; # Output steps

อะไรนะ$argn?
chx

@chx ตัวแปรที่พร้อมใช้งานเมื่อคุณใช้ PHP จากบรรทัดคำสั่งด้วย -R Option php.net/manual/en/features.commandline.options.php
JörgHülsermann

ว้าว. ผมไม่เคยได้ยิน-Rมากน้อยหรือargv argiฉันรู้ของ argc และ argv แน่นอน น่าสนใจมากขอบคุณ
chx

4

C, 94 91 ไบต์

ลองออนไลน์

c;s;m;M;f(n){while(s-n){while(s<n)s+=++M;c++;if(s==n)break;while(s>n)s-=++m;c++;}return c;}

ใช้อย่างกว้างขวางกับตัวแปรที่ไม่ได้กำหนดค่าเริ่มต้น oO
YSC

@YSC ใน C จำนวนเต็มที่ประกาศทั่วโลกถูกกำหนดเป็นศูนย์ในเวลารวบรวม อ่านเพิ่มเติม
Khaled.K

ลืมเรื่องนี้ ขอบคุณสำหรับคำเตือนนี้
YSC

FYI ผมโพสต์คำตอบ C อีก อย่างน้อยหนึ่งในกลอุบายที่ฉันใช้จะไม่ทำงานกับคอมไพเลอร์อื่น ๆ (ที่หายไปreturn) แต่สำหรับกลวิธีที่ทำได้อย่าลังเลที่จะรวมมันไว้ในคำตอบของคุณ
hvd

3

JavaScript (ES6), 82 ไบต์

D=(o,a=0,b=1,d=1,c=0)=>a<o?D(o,a+=b,b+1,d,c+(a>=o)):a>o?D(o,a-=d,b,d+1,c+(a<=o)):c

ตัวอย่างการทดสอบ


ขออภัยที่จะพูดเรื่องนี้ แต่ละↄนับเป็น 3 ไบต์ ฉันคิดว่ามันไม่สำคัญเพราะมันเปลี่ยนชื่อได้เล็กน้อย
Ørjan Johansen

@ ØrjanJohansenขอบคุณที่เตือนฉัน ฉันควรจำรหัสคะแนนของฉันเป็นไบต์มากกว่าความยาว ฉันไม่คิดว่าจะมีฉันทามติของชุมชนเกี่ยวกับ "เปลี่ยนชื่อได้เล็กน้อย [ตัวแปร]" ดังนั้นฉันจึงแก้ไขโพสต์ โอ้ดี
R. Kap

3
ตัวอย่างข้อมูลล้มเหลวด้วย“ การเรียกซ้ำมากเกินไป” ใน 6553 6553 ทำงานในโหนด (6.9.1) ในเครื่อง แต่ 65536 ไม่ได้ (“ เกินขนาดสแต็กการโทรสูงสุด”)
eush77

3

dc , 61 ไบต์

dsN[ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx]dsFxz2-

ลองออนไลน์!

คำอธิบาย

มาโครเรียกซ้ำหลัก:

ddd9k4*d2*1+dv-0k2/-d1+*2/-d[q]s.0=.-lN-0lN-sNlFx
   9k4*d2*1+dv-0k2/-                              # Compute triangular root
                    d1+*2/                        # Compute triangular number
  d                       -d[q]s.0=.              # Check if sum is exact
 d                                  -lN-          # Compute S-N or S+N
                                        0lN-sN    # Update N := -N
d                                             lFx # Leave the trail and recurse

มาโครนี้:

  1. ค้นหาหมายเลขสามเหลี่ยมขั้นต่ำที่เกินจำนวนปัจจุบันในสแต็ก (โดยใช้สูตรรูตสามเหลี่ยมที่แก้ไขแล้ว)
  2. ตรวจสอบว่าผลรวมสามเหลี่ยมSหมายถึงตัวเลขปัจจุบันหรือไม่ ออกถ้ามันเป็น
  3. ดำเนินการจนถึงขั้นตอนที่ 1 ด้วยS+N(เกินการประมาณ) หรือS-N(ภายใต้การประมาณ) ตัวเลือกจะสลับไปมาระหว่างการทำซ้ำ

เมื่อมันออกไปเส้นทางที่เหลืออยู่ในสแต็กจะบอกโปรแกรมหลักว่าจะใช้การวนซ้ำหลายครั้ง


3

Python 3, 150 138 ไบต์

n=int(input())
S=sum
l=[1]
i=s=1
while S(l)<n:i+=1;l+=[i]
while S(l)!=n:
 while S(l)>n:l.pop(0)
 s+=1
 if S(l)<n:i+=1;l+=[i];s+=1
print(s)

การเปลี่ยนแปลง:

  • เปลี่ยนต่อท้ายเป็น + =, นำออกอย่างอื่น (ขอบคุณ musicman523, Loovjo; -12 ไบต์)

1
ขั้นตอนที่ # 2 สามารถลบหนึ่งคำหรือหลายคำพร้อมกันจากรายการ (เช่น 1, 2 และ 3 ในตัวอย่างสำหรับ N = 11) แต่ถูกนับเป็นขั้นตอนเดียวแบบใดแบบหนึ่ง
Arnauld

@ Arnauld มองข้ามว่า คงที่
L3viathan

1
คุณช่วยอธิบายได้ไหมว่าทำไมจึงelseจำเป็น ผมเชื่อว่าelseทำงานทุกครั้งเพราะห่วงเสมอยุติตามปกติ (ไม่break) และมันดูเหมือนว่าจะปรับการทำงานโดยไม่ได้
musicman523

คุณสามารถข้ามA=l.appendส่วนและใช้l+=[x]แทน
Loovjo

3

แบตช์ 126 ไบต์

@echo off
set/an=s=l=u=0
:l
if %s% lss %1 set/as+=u+=1,n+=!!l&goto l
if %s% gtr %1 set/as-=l+=1&goto l
cmd/cset/an+n+2-!l

คำอธิบาย: lเป็นศูนย์หากขั้นตอนที่ 2 ไม่เคยดำเนินการ วิธีนี้ช่วยให้nสามารถติดตามจำนวนการวนซ้ำของขั้นตอนที่ 3 เนื่องจากอัลกอริทึมไม่เคยหยุดที่ขั้นตอนที่ 3 ดังนั้นจึงต้องเรียกใช้ขั้นตอนที่ 1 ครั้งเดียวและขั้นตอนที่ 2 n+1ครั้งสำหรับn+n+2ขั้นตอนทั้งหมด อย่างไรก็ตามหากพารามิเตอร์เป็นตัวเลขสามเหลี่ยมดังนั้นขั้นตอนที่ 2 จะไม่ดำเนินการดังนั้นเราจำเป็นต้องลบหนึ่งขั้นตอน


3

Python 2, 86 81 ไบต์

n=input()
l=u=i=s=0
while n:k=n>0;i+=k^s;s=k;l+=k;n-=l*k;u+=k^1;n+=u*-~-k
print i

ลองออนไลน์!

คำนวณกรณีทดสอบ65536 รายการใน0.183sTIO


เวอร์ชันแบบเรียกซ้ำนี้ที่ 84 ไบต์ไม่สามารถคำนวณค่าทั้งหมดได้สูงสุด 65536:

def f(n,l=[0],m=1):k=n>sum(l);return n==sum(l)or f(n,[l[1:],l+[l[-1]+1]][k],k)+(m^k)

ลองออนไลน์!


2

Mathematica, 92 ไบต์

(For[q=a=b=0;t={},t~AppendTo~q;q!=#,If[q<#,q+=++b,q-=++a]];Length@Split@Sign@Differences@t)&

ฟังก์ชันบริสุทธิ์รับอาร์กิวเมนต์จำนวนเต็มและส่งคืนเลขจำนวนเต็ม

ตัวแปรaและbหมายถึงตัวเลขเริ่มต้นและสิ้นสุด (เปลี่ยนแปลงตลอดเวลา) ในผลรวมภายใต้การพิจารณาขณะที่qย่อมาจากผลรวมสะสม (ของตัวเลขจากa+1ถึงb) tติดตามค่าทั้งหมดของการqพบจนถึง หลังจากเริ่มต้นตัวแปรเหล่านี้แล้วForลูปจะยังคงIf[q<#,q+=++b,q-=++a]ทำงานซึ่งจะเพิ่มหมายเลขใหม่ไปยังจุดสิ้นสุดหรือลบหมายเลขที่ด้านหน้าตามที่กำหนดโดยข้อมูลจำเพาะจนกระทั่งqเท่ากับอินพุต

ตอนนี้เราต้องแยกจำนวนขั้นตอนออกจากtรายการqค่าที่พบตลอดทาง ตัวอย่างเช่นเมื่อเข้าเป็น11ที่Forออกจากวงด้วยเท่ากับt {0,1,3,6,10,15,14,12,9,15,11}วิธีที่ดีที่สุดที่ฉันพบว่าการคำนวณจำนวนขั้นตอนจากนี้คือการนับจำนวนครั้งที่ความแตกต่างเปลี่ยนจากการขึ้นไปเป็นลง นั่นคือสิ่งที่คำสั่ง verbose Length@Split@Sign@Differences@tทำ แต่ฉันสงสัยว่าสามารถปรับปรุงได้


2

C (tcc), 71 ไบต์ (61 + 10)

อาร์กิวเมนต์บรรทัดคำสั่ง (รวมช่องว่าง):

-Dw=while

ที่มา:

c,m,M,s;f(n){w(++c,s-n){w(c&s<n)s+=++M;w(~c&s>n)s-=m++;}--c;}

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

cนับจำนวนขั้นตอน mและMเก็บค่าต่ำสุดและสูงสุดของช่วงsผลรวม เริ่มแรกพวกเขาทั้งหมดเป็นศูนย์

อย่างต่อเนื่องcจะเพิ่มขึ้นและเมื่อเทียบกับs nตราบใดที่มันไม่เท่ากัน:

  • ถ้าcเป็นเลขคี่แล้วตราบใดที่s<nเพิ่มจำนวนเต็มไปยังจุดสิ้นสุดของช่วง: เพิ่มขึ้นMโดยหนึ่งและโดยsM

  • หากcแม้แล้วตราบใดที่s>nเอาจำนวนเต็มจากจุดเริ่มต้นของช่วง: ลดลงsโดยการmและการเพิ่มขึ้นmโดยหนึ่ง

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

ขันที่เกิดขึ้นที่จะใช้ชื่อตัวแปรเดียวกันแน่นอนเป็นKhaled.K คำตอบของ พวกเขาไม่ได้คัดลอก


1

Perl 6 , 114 bytes

{((0,0,1),->(\a,\b,\c){b,(a..*).first(->\d{(d,b).minmax.sum*c>=$_*c}),-c}...->(\a,\b,\c){(a,b).minmax.sum==$_})-1}

(แรงบันดาลใจจากการใช้งานHaskellก่อนหน้านี้)

ลองใช้
มันทำงานด้วยอินพุต 65536 ในไม่เกิน 45 วินาทีบนคอมพิวเตอร์ของฉัน แต่ฉันไม่สามารถเรียกใช้ภายใน 60 วินาทีด้วย TIO.run
ฉันมี Rakudo v2017.04 + ที่มันมีv2017.01
Rakudo / NQP / MoarVM ได้รับการปรับให้เหมาะสมเกือบทุกวันดังนั้นอาจมีจำนวนใดก็ได้จากระหว่างกาลที่จำเป็นต้องใช้เพื่อให้ได้ภายในเวลาที่กำหนด


ขยาย

{
  (

    # generate a sequence

    (0,0,1),           # initial value 

    -> (\a,\b,\c) {
      b,               # swap the first two values

      (a..*)
      .first(          # find the first number that brings us to or past the input

        -> \d {
          (d,b).minmax # get a Range object regardless of which is larger
          .sum * c     # sum it, and negate it every other time

          >=           # is it equal to or greater than

          $_ * c       # negate the original input every other time
        }

      ),

      -c               # invert for next round
    }

    ...                # keep doing that until

    -> (\a,\b,\c) {
     (a,b).minmax.sum == $_ # it finally reaches the input
    }

  ) - 1 # count the number of elements in the sequence
        # and subtract one for the initializer
}

โปรดทราบว่า Rakudo มีการปรับให้เหมาะสมRange.sumเพื่อที่จะได้ไม่ต้องวนซ้ำในทุกค่า

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