เลขสามเหลี่ยมพลิก


30

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

         1                      1         
       2   3                  3   2       
     4   5   6    <--->     6   5   4     
   7   8   9  10         10   9   8   7   
11  12  13  14  15     15  14  13  12  11

นี่คือองค์ประกอบที่nของA038722 ที่มีการจัดทำดัชนีแล้ว:

1, 3, 2, 6, 5, 4, 10, 9, 8, 7, 15, 14, 13, 12, 11, ...

ลำดับนี้ย้อนกลับชิ้นที่ต่อเนื่องกันของจำนวนเต็มบวกที่มีความยาวเพิ่มขึ้น:

 1, 3, 2, 6, 5, 4, 10, 9, 8, 7, 15, 14, 13, 12, 11, ...
<-><----><-------><-----------><------------------>

กรณีทดสอบ:

1 -> 1
2 -> 3
3 -> 2
4 -> 6
14 -> 12
990 -> 947
991 -> 1035
1000 -> 1026
1035 -> 991
1036 -> 1081
12345 -> 12305

ลีดเดอร์บอร์ด:

คำตอบ:


15

JavaScript (ES7), 26 ไบต์

n=>((2*n)**.5+.5|0)**2-n+1

การใช้งานสูตรต่อไปนี้จาก OEIS :

สูตร

การสาธิต


ฉันชอบการดำเนินการ OR เพื่อทำให้เป็นจำนวนเต็ม! งานที่ดี!
CraigR8806

7

เยลลี่ , 8 7 ไบต์

RṁR€UFi

ขอบคุณ @ErikTheOutgolfer สำหรับการบันทึก 1 ไบต์!

ลองออนไลน์!

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

RṁR€UFi  Main link. Argument: n

R        Range; yield [1, ..., n].
  R€     Range each; yield [[1], [1, 2], [1, 2, 3], ..., [1, ..., n]].
 ṁ       Mold the left argument like the right one, yielding
         [[1], [2, 3], [4, 5, 6], ...]. The elements of the left argument are 
         repeated cyclically to fill all n(n+1)/2 positions in the right argument.
    U    Upend; reverse each flat array, yielding [[1], [3, 2], [6, 5, 4], ...].
     F   Flatten, yielding [1, 3, 2, 6, 5, 4, ...].
      i  Index; find the first index of n in the result.

6

อลิซ 27 ไบต์

ขอบคุณ Sp3000 สำหรับ.Cแนวคิดนี้

/o
\i@/.2:e2,tE*Y~Z.H2*~.C+

ลองออนไลน์!

คำอธิบาย

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

แนวคิดพื้นฐานคือการใช้ประโยชน์จาก "แพ็ค" ของอลิซและ "ปลดแพ็ค" ในตัว "Pack" หรือZนำจำนวนเต็มสองจำนวนไปจับคู่กับ bijectively เป็นจำนวนเต็มเดียว "Unpack" หรือแปลงค่าความYผิดเพี้ยนนี้และเปลี่ยนจำนวนเต็มหนึ่งเป็นสอง โดยปกติสิ่งนี้สามารถใช้เพื่อเก็บรายการหรือต้นไม้ของจำนวนเต็มในจำนวนเต็มเดียว (ใหญ่) และกู้คืนค่าแต่ละค่าในภายหลัง อย่างไรก็ตามในกรณีนี้เราสามารถใช้ฟังก์ชั่นในลำดับที่ตรงกันข้ามเพื่อให้ธรรมชาติของ bijection ทำงานให้เรา

การคลายจำนวนเต็มหนึ่งจำนวนเป็นสองจำนวนเต็มโดยทั่วไปประกอบด้วยสามขั้นตอน:

  1. แผนที่ℤ→ℕ (รวมศูนย์) ด้วย "การพับ" แบบง่าย นั่นคือแม็พจำนวนเต็มลบกับเนเชอรัลคี่และจำนวนเต็มลบที่ไม่ใช่เนเชอรัล
  2. แผนที่ℕ→ℕ 2โดยใช้ฟังก์ชั่นการจับคู่ต้นเสียง นั่นคือธรรมชาติจะถูกเขียนตามแนวทแยงมุมของกริดที่ไม่มีที่สิ้นสุดและเราคืนดัชนี:

       ...
    3  9 ...
    2  5 8 ...
    1  2 4 7 ...
    0  0 1 3 6 ...
    
       0 1 2 3
    

    เช่นจะได้รับการแมปไปทั้งคู่8(1, 2)

  3. แผนที่2 →ℤ 2โดยใช้ค่าผกผันของขั้นตอนที่ 1 ในแต่ละจำนวนเต็ม นั่นคือธรรมชาติจะได้รับการแมปกับจำนวนเต็มลบและแม้กระทั่งธรรมชาติได้รับการแมปกับจำนวนเต็มไม่เป็นลบ

ในการแพ็คจำนวนเต็มสองจำนวนเป็นหนึ่งเดียวเราจะกลับแต่ละขั้นตอนเหล่านั้น

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

น่าเสียดายเนื่องจากขั้นตอนทั้งสามขั้นตอนข้างต้นรวมกันเป็นหนึ่งเดียวในตัวY(หรือZ) เราจึงต้องยกเลิกการแมปℤ→ℕหรือℕ→ℤด้วยตนเอง อย่างไรก็ตามในขณะที่ทำเช่นนั้นเราสามารถบันทึกสองสามไบต์ได้โดยตรงโดยใช้การแมปℕ + →ℤหรือℤ→ℕ +โดยตรงเพื่อดูแลข้อผิดพลาดแบบออฟไลน์ในตาราง ดังนั้นนี่คืออัลกอริทึมทั้งหมด:

  1. แผนที่+ →ℤใช้(n / 2) * (-1) n-1 การแมปนี้ถูกเลือกจนสามารถยกเลิกการแม็พโดยนัยun →ℕในระหว่างการเอาออกยกเว้นว่าจะลดค่าลง 1
  2. แยกผลลัพธ์ออกเป็นจำนวนเต็มสองจำนวน
  3. สลับพวกเขา
  4. แพ็คค่าการแลกเปลี่ยนเป็นจำนวนเต็มเดียวอีกครั้ง
  5. แผนที่ℤ→ℕ +ใช้| 2n | + (n≥0) อีกครั้งการทำแผนที่นี้จะถูกเลือกเพื่อที่จะยกเลิกการทำแผนที่โดยนัยℕ→ℤในระหว่างการบรรจุยกเว้นว่ามันจะเลื่อนค่าขึ้น 1

เมื่อพ้นทางเราสามารถดูโปรแกรม:

/o
\i@/...

นี่เป็นเพียงกรอบสำหรับโปรแกรมคณิตศาสตร์เชิงเส้นที่มีอินพุตและเอาต์พุตจำนวนเต็ม

.    Duplicate the input.
2:   Halve it.
e    Push -1.
2,   Pull up the other copy of the input.
t    Decrement.
E    Raise -1 to this power.
*    Multiply. We've now computed (n/2) * (-1)^(n-1).
Y    Unpack.
~    Swap.
Z    Pack.
.H   Duplicate the result and take its absolute value.
2*   Double.
~    Swap with other copy.
.C   Compute k-choose-k. That's 1 for k ≥ 0 and 0 for k < 0.
+    Add. We've now computed |2n| + (n≥0).



4

อ็อกเทฟ , 71 68 ไบต์

3 ไบต์บันทึกขอบคุณที่Conor โอไบรอัน

x=triu(ones(n=input('')));x(~~x)=1:nnz(x);disp(nonzeros(flip(x))(n))

วิธีนี้ใช้ไม่ได้กับอินพุตขนาดใหญ่เนื่องจากข้อ จำกัด ของหน่วยความจำ

ลองออนไลน์!

คำอธิบาย

n = 4พิจารณาการป้อนข้อมูล รหัสแรกสร้างเมทริกซ์

 1     1     1     1
 0     1     1     1
 0     0     1     1
 0     0     0     1

จากนั้นก็จะเข้ามาแทนที่รายการภัณฑ์เพื่อคอลัมน์หลัก (ลงแล้วข้าม) โดย1, 2, 3...

 1     2     4     7
 0     3     5     8
 0     0     6     9
 0     0     0    10

จากนั้นมันจะพลิกเมทริกซ์ในแนวตั้ง:

 0     0     0    10
 0     0     6     9
 0     3     5     8
 1     2     4     7

ในที่สุดก็เตะnค่าไม่ใช่ศูนย์ -th 6เพื่อคอลัมน์ที่สำคัญซึ่งในกรณีนี้คือ


1
@ rahnema1 นั่นeคืออัจฉริยะ! คุณควรโพสต์เป็นคำตอบแน่นอนพร้อมกับคำแนะนำที่ดีอื่น ๆ ของคุณ สำหรับans =ฉันไม่เคยแน่ใจว่ามันจะถูกต้องหรือไม่
Luis Mendo

4

Haskell , 31 ไบต์

r=round
f n=r(sqrt$2*n)^2-r n+1

ลองออนไลน์!

คำตอบนี้ใช้สูตร มันเป็นคำตอบที่น่าสนใจน้อยที่สุดที่นี่ แต่มันก็ยังเป็น Golfiest

Haskell , 38 36 34 ไบต์

x!y|x<=y=1-x|v<-y+1=v+(x-y)!v
(!0)

ลองออนไลน์!

(!0) เป็นฟังก์ชั่นจุดฟรีที่เรากังวล

คำอธิบาย

ให้ฉันเริ่มต้นด้วยการบอกว่าฉันมีความสุขมากกับคำตอบนี้

แนวคิดพื้นฐานที่นี่คือถ้าเราลบหมายเลขสามเหลี่ยมที่ใหญ่ที่สุดที่เล็กกว่าอินพุทของเราเราสามารถย้อนกลับได้และเพิ่มหมายเลขสามเหลี่ยมกลับ ดังนั้นเราจึงกำหนดประกอบการ!, !จะเข้าปกติของเราแต่ก็ยังใช้หมายเลขพิเศษ x ติดตามขนาดของตัวเลขสามเหลี่ยมที่กำลังเติบโต ถ้าเราต้องการที่จะ recurse เราลดลงโดยการและการเพิ่มขึ้นโดยหนึ่ง ดังนั้นเราคำนวณและเพิ่มลงไป ถ้าเราได้มาถึงกรณีฐานของเราที่จะย้อนกลับของตำแหน่งในแถวของผลตอบแทนที่เรารูปสามเหลี่ยมyyx>yxyy(x-y)!(y+1)y+1x<=yx1-x

Haskell , 54 ไบต์

f x|u<-div(x^2-x)2=[u+x,u+x-1..u+1]
(!!)$0:(>>=)[1..]f

ลองออนไลน์!

(!!)$0:(>>=)[1..]f เป็นฟังก์ชั่นไร้จุด

คำอธิบาย

สิ่งแรกที่เรามีความกังวลกับเป็นf, fเป็นฟังก์ชันที่ใช้เวลาxและผลตอบแทนxแถว TH ของรูปสามเหลี่ยม TH ในสิ่งที่ตรงกันข้าม มันเป็นเช่นนี้เป็นครั้งแรกโดยการคำนวณจำนวนครั้งที่สามเหลี่ยมและกำหนดที่จะx-1 . จากนั้นเราจะกลับรายการ คือหมายเลขสามเหลี่ยมที่สามและหมายเลขแรกในแถวคือหนึ่งที่น้อยกว่านั้นและหมายเลขที่สองในแถวนั้นมากกว่าหมายเลขสามเหลี่ยมสุดท้ายหนึ่งหมายเลขดังนั้นจึงเป็นหมายเลขสุดท้ายของแถวuu<-div(x^2-x)2[u+x,u+x-1..u+1]u+xxu+x-1u+1

เมื่อเรามีfรายการรูปแบบ(>>=)[1..]fซึ่งเป็นรูปสามเหลี่ยมแบน เราได้เพิ่มศูนย์ไปข้างหน้าด้วยเพื่อให้คำตอบของเราจะไม่ได้รับการชดเชยโดยหนึ่งและจำหน่ายไปยังฟังก์ชั่นการจัดทำดัชนีของเรา0:(!!)

Haskell , 56 ไบต์

f 0=[0]
f x|u<-f(x-1)!!0=[u+x,u+x-1..u+1]
(!!)$[0..]>>=f

ลองออนไลน์!

อันนี้ยาวกว่า 2 ไบต์ แต่ความเห็นของฉันก็ดูดีขึ้นไปอีกเล็กน้อย


3

C (gcc) , 48 ไบต์

k,j,l;f(n){for(k=j=0;k<n;)l=k,k+=++j;n=1+k-n+l;}

ลองออนไลน์!

อาจจะไม่ดีนัก แต่ฉันค่อนข้างมีความสุขกับอันนี้ ใช้ความจริงที่ว่า

NTF N = T N + A057944 ( N ) - N + 1

(ถ้าฉันเขียนสูตรลงอย่างถูกต้องนั่นคือ)


คุณไม่ได้โทรกลับ แต่ใช้ค่าส่งคืน นั่นคือพฤติกรรมที่ไม่ได้กำหนด
2501

@ 2501 ตราบใดที่โปรแกรมทำงานได้ก็อนุญาต และการเขียนอาร์กิวเมนต์แรกของฟังก์ชันนั้นเท่ากับการคืนค่า
Conor O'Brien

และการเขียนอาร์กิวเมนต์แรกของฟังก์ชันนั้นเท่ากับการคืนค่า ไม่มีสิ่งนั้นอยู่ในภาษา C มาตรฐานยังระบุอย่างชัดเจนว่าการใช้ค่าที่ส่งคืนจากฟังก์ชันที่ไม่ส่งคืนคือพฤติกรรมที่ไม่ได้กำหนด
2501

1
@ 2501 ดูเหมือนว่าคุณจะสับสนกับสภาพแวดล้อม C (gcc) สำหรับข้อมูลจำเพาะ C ใช่ภาษา C / ข้อมูลจำเพาะเรียกมันว่าไม่ได้กำหนด แต่มันถูกนำไปใช้เช่นนั้น ดังนั้นเมื่อฉันพูดว่า "เทียบเท่า" ฉันหมายถึงการนำ C ไปใช้โดย gcc และคอมไพเลอร์อื่น ๆ เป็นส่วนใหญ่ บน PPCG เราไม่ได้เขียนรหัส "สมบูรณ์แบบ" - รหัสจำนวนมากขัดกับข้อกำหนดเพื่อการตีกอล์ฟ อย่างที่ฉันพูดตราบใดที่มันใช้ได้ผลก็เป็นคำตอบที่ถูกต้อง
Conor O'Brien

@ 2501 ผมแนะนำให้คุณอ่านบทความบางส่วนในเว็บไซต์เมตาโดยเฉพาะอย่างยิ่งคนนี้
Conor O'Brien

2

05AB1E , 30 ไบต์

U1V[YLO>X›iYLOX-UY<LO>X+,q}Y>V

ลองออนไลน์!


ฉันกำลังจะพูดว่า "อะไรคำตอบ 05AB1E ที่ไม่มี Unicode หรือไม่" แต่แล้วตัวละครที่ไม่ใช่ ASCII ก็ทำลายมัน ... : P คำตอบแรกที่ดี แต่ยินดีต้อนรับสู่ Programming Puzzles และ Code Golf!
clismique

@ Qwerp-Derp ขอบคุณมาก! ฉันเพิ่งเริ่มเรียนภาษานี้ดังนั้นฉันจึงไม่แปลกใจที่คำตอบของฉันไม่ดี
Eduardo Hoefel

2

Husk , 6 ไบต์

!ṁ↔´CN

ลองออนไลน์!

คำอธิบาย

!ṁ↔´CN  -- implicit input N, for example: 4
   ´ N  -- duplicate the natural numbers:
           [1,2,3,…] [1,2,3,…]
    C   -- cut the second argument into sizes of the first:
           [[1],[2,3],[4,5,6],[7,8,9,10],…]
 ṁ↔     -- map reverse and flatten:
           [1,3,2,6,5,4,10,9,8,7,15,…
!       -- index into that list:
           6

2

tinylisp , 78 ไบต์

(d _(q((R N T)(i(l T N)(_(a R 1)N(a T R))(a 2(a T(s T(a N R
(d f(q((N)(_ 2 N 1

กำหนดฟังก์ชั่นfที่ดำเนินการทำแผนที่ ลองออนไลน์!

Ungolfed

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

  • หากหมายเลขสามเหลี่ยมปัจจุบันน้อยกว่า N ให้เติมเข้าไปในแถวถัดไปของสามเหลี่ยม (เราถือว่าแถวบนสุดเป็นแถว 2 เพื่อทำให้คณิตศาสตร์ง่ายขึ้น)
  • มิฉะนั้นเวอร์ชันที่พลิกกลับของ N คือ (TN) + (TR) +2

ฟังก์ชั่นหลักflipเพียงเรียกใช้ฟังก์ชันตัวช่วย_flipเริ่มจากแถวบนสุด

(load library)

(def _flip
 (lambda (Num Row Triangular)
  (if (less? Triangular Num)
   (_flip Num (inc Row) (+ Triangular Row))
   (+ 2
    (- Triangular Num)
    (- Triangular Row))))))

(def flip
 (lambda (Num) (_flip Num 2 1)))

1

05AB1E , 9 ไบต์

·LD£í˜¹<è

ลองออนไลน์!

คำอธิบาย

·L          # push range [1 ... 2n]
  D         # duplicate
   £        # split the first list into pieces with size dependent on the second list
    í       # reverse each sublist
     ˜      # flatten
      ¹<è   # get the element at index <input>-1

อาเรย์แบนราบน่าเสียดายที่ไม่สามารถจัดการกับรายการขนาดใหญ่ได้เป็นอย่างดี
ค่าใช้จ่ายของ 1 ไบต์ที่เราสามารถทำได้· t2z + ïn¹->โดยใช้สูตรทางคณิตศาสตร์floor(sqrt(2*n)+1/2)^2 - n + 1ที่พบในOEIS


1

รุ่นที่ 70 ไบต์

@set/ai=%2+1,j=%3+i
@if %j% lss %1 %0 %1 %i% %j%
@cmd/cset/ai*i+1-%1

nใช้การวนรอบเพื่อหาดัชนีของจำนวนสามเหลี่ยมอย่างน้อยเป็นใหญ่เป็น




0

APL (Dyalog) 27 ไบต์

ฉันมีโซลูชันสองรายการในจำนวนเดียวกัน

รถไฟ:

⊢⊃⊃∘(,/{⌽(+/⍳⍵-1)+⍳⍵}¨∘⍳)

ลองออนไลน์!

และ dfn:

{⍵⊃⊃((⍳⍵),.{1+⍵-⍳⍺}+\⍳⍵)}

ลองออนไลน์!

โซลูชันทั้งสองนี้จะสร้างสามเหลี่ยมที่พลิกแล้วก่อนจากนั้นแยกองค์ประกอบที่ดัชนีที่ระบุโดยอาร์กิวเมนต์ ( 1-based)


0

J, 25 ไบต์

3 :'>:y-~*:>.-:<:%:>:8*y'

f(n) = n(n+1)/2เป็นคำอธิบายให้พิจารณา f(r)ให้แถวrกลับจำนวนซ้ายสุดของrวันที่แถวของสามเหลี่ยมมิเรอร์ g(n) = ceiling[f⁻¹(n)]ตอนนี้พิจารณา g(i)กำหนดให้ดัชนีiส่งคืนแถวที่พบดัชนี i จากนั้นf(g(n))ส่งคืนจำนวนซ้ายสุดของแถวที่พบดัชนี n ดังนั้นh(n) = f(g(n)) - (n - f(g(n)-1)) + 1คำตอบของปัญหาข้างต้นคือ

h(n) = [g(n)]² - n + 1 = ceiling[(-1 + sqrt(1 + 8n))/2]² - n + 1ง่ายที่เราได้รับ

จากรูปลักษณ์ของสูตรของ @ Arnauld ดูเหมือนว่า:

ceiling[(-1 + sqrt(1 + 8n))/2] = floor[1/2 + sqrt(2n)].


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