สร้าง n หลักของลำดับ Gijswijt


19

บทนำ

ลำดับของ Gijswijt ( A090822 ) มีชื่อเสียงมากจริงๆช้ามาก เพื่อแสดง:

  • 3 รายการแรกจะปรากฏในเทอมที่ 9 (ไม่เป็นไร)
  • 4 รายการแรกจะปรากฏในเทอมที่ 220 (อยู่ไกล แต่เป็นไปได้)
  • 5 ตัวแรกจะปรากฏขึ้นที่ (โดยประมาณ) คำที่10 ^ (10 ^ 23) th (ไม่ถึง)
  • ไม่มีใครรู้จริง ๆ ว่า 6 ตัวแรกคืออะไร ... มันน่าสงสัยว่ามันอยู่ที่ ...

    2 ^ (2 ^ (3 ^ (4 ^ 5))) คำศัพท์ที่

คุณสามารถสันนิษฐานได้ว่าคุณไม่ต้องจัดการกับตัวเลขสองหลัก

มีการสร้างลำดับดังนี้:

  1. เทอมแรกคือ 1
  2. แต่ละคำหลังจากนั้นคือจำนวนการ "บล็อก" ซ้ำก่อนหน้า (ถ้ามี "บล็อก" ซ้ำหลายครั้งจะใช้จำนวนการทำซ้ำบล็อกที่ใหญ่ที่สุด)

เพื่ออธิบายให้ชัดเจนนี่เป็นคำศัพท์สองสามคำแรก

1 -> 1, 1(หนึ่งบล็อกที่ซ้ำกัน ( 1) ดังนั้นตัวเลขที่บันทึกไว้คือ1)

1, 1 -> 1, 1, 2(บล็อกที่ทำซ้ำสองบล็อก ( 1) ดังนั้นหลักที่บันทึกคือ2)

1, 1, 2 -> 1, 1, 2, 1(หนึ่งบล็อกซ้ำ ( 2หรือ1, 1, 2) ดังนั้นตัวเลขที่บันทึกไว้คือ1)

1, 1, 2, 1 -> 1, 1, 2, 1, 1 (คุณได้รับความคิด)

1, 1, 2, 1, 1 -> 1, 1, 2, 1, 1, 2

1, 1, 2, 1, 1, 2 -> 1, 1, 2, 1, 1, 2, 2(บล็อกที่ทำซ้ำสองบล็อก ( 1, 1, 2) ดังนั้นหลักที่บันทึกคือ2)

งาน

งานของคุณตามที่ระบุไว้ในคำถามเพื่อสร้างตัวเลข n ของลำดับ Gijswijt

คำแนะนำ

  • nการป้อนข้อมูลจะเป็นจำนวนเต็ม
  • รหัสของคุณสามารถส่งออกตัวเลขในรูปแบบใด ๆ (รายการหลายผลลัพธ์ ฯลฯ )

นี่คือรหัสกอล์ฟดังนั้นรหัสที่สั้นที่สุดในหน่วยไบต์ชนะ

คำตอบ:


7

Pyth, 25 22 21 ไบต์

t_u+eSmtfxG*Td1._GGQN

OP ยืนยันว่าเราต้องการเพียงจัดการตัวเลขหลักเดียว สิ่งนี้อนุญาตให้เก็บรายการเป็นสตริงตัวเลข -> บันทึก 3 ไบต์

ลองใช้งานออนไลน์: การสาธิต

คำอธิบาย:

t_u+...GQN      implicit: Q = input number
         N      start with the string G = '"'
  u     Q       do the following Q times:
    ...            generate the next number
   +   G           and prepend it to G
 _              print reversed string at the end
t               remove the first char (the '"')

และนี่คือวิธีที่ฉันสร้างหมายเลขถัดไป:

eSmtfxG*Td1._G
           ._G    generate all prefixes of G
  m               map each prefix d to:
    f     1          find the first number T >= 1, so that:
       *Td              d repeated T times
     xG                 occurs at the beginning of G
 S                  sort all numbers
e                   take the last one (maximum)   

21 ไบต์พร้อมลิสต์

_u+eSmhhrcGd8SlGGtQ]1

ลองใช้งานออนไลน์: การสาธิต

ใช้ความคิดเดียวกันกับมาร์ตินและปีเตอร์ ในแต่ละขั้นตอนฉันแยกสตริงออกเป็นชิ้นส่วนของความยาว 1 ชิ้นส่วนของความยาว 2, ... จากนั้นฉันเข้ารหัสช่วงความยาวและใช้การวิ่งครั้งแรกสูงสุดเป็นหมายเลขถัดไป

20 ไบต์พร้อมสตริง

t_u+eSmhhrcGd8SlGGQN

ลองใช้งานออนไลน์: การสาธิต

รวมแนวคิดของรหัสทั้งสองข้างต้น


1
ขอบคุณที่สอนฉัน ฉันมักจะลืม._ฟังก์ชั่นและฟังก์ชั่นที่มีประโยชน์อื่น ๆ ใน Pyth
Leun Nun

ฉันชอบโซลูชั่นดั้งเดิมมากกว่าเดิม แต่เอ๊ะ
clismique

@Jakube Ah ฉันขอดูหน่อยได้ไหม ถ้าใช่ขอบคุณ!
clismique

@DerpfacePython สามารถเพิ่มอีกหนึ่งไบต์ในโซลูชันเดิมของฉัน ฉันยังโพสต์โซลูชันการเข้ารหัสความยาวรันตามมาร์ตินและจากนั้นก็สามารถรวมสองวิธีเพื่อสร้างโซลูชัน 20 ไบต์
Jakube

5

CJam, 33 31 30 27 bytes

ขอบคุณ Peter Taylor ที่ช่วยประหยัด 1 ไบต์

1sri({),:)1$W%f/:e`$W=sc+}

ทดสอบที่นี่

คำอธิบาย

1s      e# Initialise the sequence as "1".
ri(     e# Read input N and decrement.
{       e# For each I from 0 to N-1...
  )     e#   Increment to get I from 1 to N.
  ,     e#   Turn into a range [0 1 ... I-1].
  :)    e#   Increment each element to get [1 2 ... I].
  1$    e#   Copy sequence so far.
  W%    e#   Reverse the copy.
  f/    e#   For each element x in [1 2 ... I], split the (reversed) sequence
        e#   into (non-overlapping) chunks of length x. These are the potentially
        e#   repeated blocks we're looking for. We now want to find the splitting
        e#   which starts with the largest number of equal blocks.
  :e`   e#   To do that, we run-length encode each list blocks.
  $     e#   Then we sort the list of run-length encoded splittings, which primarily
        e#   sorts them by the length of the first run.
  W=    e#   We extract the last splitting which starts with the longest run.
  sc    e#   And then we extract the length of the first run by flattening
        e#   the list into a string and retrieving the first character.
  +     e#   This is the new element of the sequence, so we append it.
}/

+1 สำหรับ :) (อีก 5 ไป ... )
Leun Nun

5

CJam ( 30 29 27 24 ไบต์)

'1ri{{)W$W%/e`sc}%$W>+}/

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

นี่เป็นความพยายามร่วมกันกับ Martin

  • การใช้การเข้ารหัสความยาววิ่ง ( e`) ที่ชาญฉลาดเพื่อระบุการทำซ้ำคือของมาร์ติน
  • ดังนั้นการใช้W$เพื่อลดความซับซ้อนของการจัดการสแต็ก
  • ฉันกำจัดการดำเนินการเพิ่ม / ลดลงสองสามครั้งโดยใช้$W>+เคสพิเศษดังที่อธิบายไว้ในการผ่าด้านล่าง

วิธี 30 ไบต์แรกของฉัน:

1ari{,1$f{W%0+_@)</{}#}$W>+}/`

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

การผ่า

1a        e# Special-case the first term
ri{       e# Read int n and iterate for i=0 to n-1
  ,1$f{   e#   Iterate for j=0 to i-1 a map with extra parameter of the sequence so far
    W%0+  e#     Reverse and append 0 to ensure a non-trivial non-repeating tail
    _@)</ e#     Take the first j+1 elements and split around them
    {}#   e#     Find the index of the first non-empty part from the split
          e#     That's equivalent to the number of times the initial word repeats
  }
  $W>+    e#   Add the maximal value to the sequence
          e#   NB Special case: if i=0 then we're taking the last term of an empty array
          e#   and nothing is appended - hence the 1a at the start of the program
}/
`         e# Format for pretty printing

3

Haskell, 97 ไบต์

f 1=[1]
f n|x<-f$n-1=last[k|k<-[1..n],p<-[1..n],k*p<n,take(k*p)x==([1..k]>>take p x)]:x
reverse.f

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

คำอธิบาย

ฟังก์ชั่นตัวช่วยfสร้างลำดับย้อนกลับโดยการตรวจสอบซ้ำว่าลำดับก่อนหน้าเริ่มต้นด้วยบล็อกซ้ำ kคือจำนวนการทำซ้ำและpเป็นความยาวของบล็อก

f 1=[1]                                   -- Base case: return [1]
f n|x<-f$n-1=                             -- Recursive case; bind f(n-1) to x.
  last[k|k<-[1..n],                       -- Find the greatest element k of [1..n] such that
  p<-[1..n],                              -- there exists a block length p such that
  k*p<n,                                  -- k*p is at most the length of x, and
  take(k*p)x                              -- the prefix of x of length p*k
    ==                                    -- is equal to
  ([1..k]>>take p x)                      -- the prefix of length p repeated k times.
  ]:x                                     -- Insert that k to x, and return the result.
reverse.f                                 -- Composition of reverse and f.


1

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

+1`((\d+)?(?<1>\2)*(?<!\3(?>(?<-1>\3)*)(?!.*\2)(.+)))!
$1$#1

อินพุตเป็นจำนวนเต็มแบบนารีที่ใช้!เป็นตัวเลข (แม้ว่าจะสามารถเปลี่ยนเป็นอักขระอื่นที่ไม่ใช่ตัวเลข) เอาต์พุตเป็นสตริงของตัวเลข

ลองออนไลน์! (หรืออีกทางหนึ่งเพื่อความสะดวกนี่คือรุ่นที่ป้อนทศนิยม )

สำหรับวัตถุประสงค์ในการทดสอบสิ่งนี้สามารถเร่งความเร็วได้มากด้วยการดัดแปลงเล็กน้อยซึ่งช่วยให้การทดสอบอินพุต 220 ภายในไม่กี่นาที:

+1`((\d+)?(?<1>\2)*(?=!)(?<!\3(?>(?<-1>\3)*)(?!.*\2)(.+)))!
$1$#1

ลองออนไลน์! ( เวอร์ชันทศนิยม )

หากคุณต้องการที่จะทดสอบแม้ตัวเลขขนาดใหญ่ก็จะดีที่สุดที่จะเพียงแค่อาหารมันป้อนข้อมูลขนาดใหญ่บางและใส่หลังจากที่เริ่มต้น: +สิ่งนี้จะทำให้ Retina พิมพ์ลำดับปัจจุบันในแต่ละครั้งที่การคำนวณตัวเลขใหม่เสร็จสมบูรณ์

คำอธิบาย

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

ตามปกติถ้าคุณต้องการไพรเมอร์ในกลุ่มสมดุลผมหมายถึงคุณจะตอบ SO ของฉัน

นี่คือ regex รุ่นที่มีคำอธิบายประกอบ 1หมายเหตุว่าเป้าหมายคือการจับจำนวนสูงสุดของบล็อกซ้ำในกลุ่ม

(                 # Group 1, this will contain some repeated block at the end
                  # of the existing sequence. We mainly need this so we can
                  # write it back in the substitution. We're also abusing it
                  # for the actual counting but I'll explain that below.
  (\d+)?          # If possible (that is except on the first iteration) capture
                  # one of more digits into group 2. This is a candidate block
                  # which we're checking for maximum repetitions. Note that this
                  # will match the *first* occurrence of the block.
  (?<1>\2)*       # Now we capture as many copies of that block as possible
                  # into group 1. The reason we use group 1 is that this captures
                  # one repetition less than there is in total (because the first
                  # repetition is group 2 itself). Together with the outer
                  # (unrelated) capture of the actual group one, we fix this
                  # off-by-one error. More importantly, this additional capture
                  # from the outer group isn't added until later, such that the
                  # lookbehind which comes next doesn't see it yet, which is
                  # actually very useful.
                  # Before we go into the lookbehind note that at the end of the
                  # regex there's a '!' to ensure that we can actually reach the
                  # end of the string with this repetition of blocks. While this 
                  # isn't actually checked until later, we can essentially assume
                  # that the lookbehind is only relevant if we've actually counted
                  # repetitions of a block at the end of the current sequence.

  (?<!            # We now use a lookbehind to ensure that this is actually the
                  # largest number of repetitions possible. We do this by ensuring
                  # that there is no shorter block which can be matched more
                  # often from the end than the current one. The first time this
                  # is true (since, due to the regex engine's backtracking rules,
                  # we start from longer blocks and move to shorter blocks later),
                  # we know we've found the maximum number of repetitions.
                  # Remember that lookbehinds are matched right-to-left, so
                  # you should read the explanation of the lookbehind from
                  # bottom to top.
    \3            # Try to match *another* occurrence of block 3. If this works,
                  # then this block can be used more often than the current one
                  # and we haven't found the maximum number of repetitions yet.
    (?>           # An atomic group to ensure that we're actually using up all
                  # repetitions from group 1, and don't backtrack.
      (?<-1>\3)*  # For each repetition in group 1, try to match block 3 again.
    )
    (?!.*\2)      # We ensure that this block isn't longer than the candidate
                  # block, by checking that the candidate block doesn't appear
                  # right of it.
    (.+)          # We capture a block from the end into group 3.
  )               # Lookbehind explanation starts here. Read upwards.
)
!                 # As I said above, this ensures that our block actually reaches
                  # the end of the string.

ในที่สุดหลังจากสิ่งนี้เสร็จสิ้นเราจะเขียนกลับ$1(ดังนั้นจึงเป็นการลบ!) รวมถึงจำนวนการดักจับในกลุ่ม$#1ที่สอดคล้องกับจำนวนการทำซ้ำสูงสุด


ทำไม Retina ถึงใช้วิธีแก้ปัญหาแบบเอกนารีแทนที่จะเป็นตัวเลข?
clismique

@DerpfacePython เพราะมันถูกกว่าและได้รับอนุญาตโดยฉันทามติ คุณสามารถลบล้างสิ่งนั้นได้โดยการระบุอินพุตนั้นต้องเป็นตัวเลขทศนิยม (ซึ่งในกรณีนี้ฉันยินดีที่จะเปลี่ยนวิธีแก้ปัญหา)
Martin Ender

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

@DerpfacePython เพิ่มลิงก์แยกต่างหากโดยใช้อินพุตทศนิยม
Martin Ender

คำอธิบายเมื่อฉันเล่นกอล์ฟเสร็จแล้ว?
CalculatorFeline

0

Ruby, 84 ไบต์

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

->n{s='';n.times{s+=(1..n).map{|i|s=~/(\d{#{i}})\1+$/?$&.size/i: 1}.max.to_s};s[-1]}

ให้ลำดับที่สร้างขึ้นsแล้วมันแมปทั้งหมดiจาก1ถึงs.length( nถูกใช้ในกรณีนี้เพื่อบันทึกไบต์นับตั้งแต่n>=s.length) และจากนั้นใช้ regex นี้เพื่อช่วยคำนวณจำนวนการวนซ้ำของความต่อเนื่องที่มีความยาวi:

/(.{#{i}})\1+$/
/(                 # Assign the following to group 1
  .{#{i}}          # Match `i` number of characters
         )         # End group 1
          \1+      # Match 1 or more repetitions of group 1
             $/    # Match the end of string

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

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