Số tam giác lật


30

Giả sử bạn liệt kê các số nguyên dương trong một hình tam giác, sau đó lật nó sang trái sang phải. Cho một số, xuất số mà nó được gửi đến. Đây là một ánh xạ tự đảo ngược.

         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

Đây là phần tử thứ n của A038722 , được lập chỉ mục một:

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

Chuỗi này đảo ngược các khối liền kề của các số nguyên dương với độ dài tăng dần:

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

Các trường hợp thử nghiệm:

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

Bảng xếp hạng:

Câu trả lời:


15

JavaScript (ES7), 26 byte

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

Việc thực hiện các công thức sau từ OEIS :

công thức

Bản giới thiệu


Tôi thích thao tác OR để chia nó thành một số nguyên! công việc tốt!
CraigR8806

7

Thạch , 8 7 byte

RṁR€UFi

Cảm ơn @ErikTheOutgolfer đã tiết kiệm 1 byte!

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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

Alice , 27 byte

Cảm ơn Sp3000 cho .Cý tưởng.

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

Hãy thử trực tuyến!

Giải trình

Tôi nghĩ rằng có thể có một cách ngắn hơn để tính toán điều này bằng cách sử dụng các số tam giác, nhưng tôi nghĩ đây là một sự lạm dụng thú vị của một tích hợp, vì vậy đây là một giải pháp khác.

Ý tưởng cơ bản là sử dụng các gói "đóng gói" và "giải nén" của Alice. "Gói", hoặc Z, lấy hai số nguyên ánh xạ chúng về mặt sinh học thành một số nguyên duy nhất. "Giải nén", hoặc Y, đảo ngược phần chọn này và biến một số nguyên thành hai. Thông thường, điều này có thể được sử dụng để lưu trữ một danh sách hoặc cây số nguyên trong một số nguyên (lớn) và phục hồi các giá trị riêng lẻ sau đó. Tuy nhiên, trong trường hợp này, chúng ta có thể sử dụng các hàm theo thứ tự ngược lại, để cho bản chất của mệnh đề hoạt động cho chúng ta.

Giải nén một số nguyên thành hai số nguyên về cơ bản bao gồm ba bước:

  1. Bản đồ ℤ → (bao gồm số không) với cách "gấp" đơn giản. Đó là, ánh xạ các số nguyên âm thành các số tự nhiên lẻ và các số nguyên không âm cho cả các số tự nhiên.
  2. Bản đồ ℕ → 2 , sử dụng chức năng ghép nối Cantor . Đó là, các chữ tự nhiên được viết dọc theo các đường chéo của một lưới vô hạn và chúng ta trả về các chỉ số:

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

    Ví dụ, 8sẽ được ánh xạ đến cặp (1, 2).

  3. Bản đồ 22 , sử dụng nghịch đảo của bước 1 trên từng số nguyên riêng lẻ. Đó là, các số tự nhiên lẻ được ánh xạ tới các số nguyên âm và thậm chí các số tự nhiên cũng được ánh xạ tới các số nguyên không âm.

Để gói hai số nguyên thành một, chúng tôi chỉ cần đảo ngược từng bước đó.

Bây giờ, chúng ta có thể thấy rằng cấu trúc của chức năng ghép nối Cantor mã hóa thuận tiện tam giác mà chúng ta cần (mặc dù các giá trị là từng cái một). Để đảo ngược các đường chéo đó, tất cả những gì chúng ta cần làm là hoán đổi tọa độ xy vào lưới.

Thật không may, vì cả ba bước trên được kết hợp thành một Y(hoặc Z) tích hợp sẵn, chúng ta cần hoàn tác bản đồ → hoặc ℕ → . Tuy nhiên, trong khi làm như vậy, chúng ta có thể lưu một vài byte bằng cách sử dụng trực tiếp ánh xạ + hoặc ℤ → + , để xử lý lỗi tắt trong bảng. Vì vậy, đây là toàn bộ thuật toán:

  1. Bản đồ + → ℤ sử dụng (n / 2) * (-1) n-1 . Ánh xạ này được chọn sao cho nó hủy bỏ ánh xạ ℤ → ℕ ẩn trong khi giải nén, ngoại trừ việc nó làm giảm giá trị xuống 1.
  2. Giải nén kết quả thành hai số nguyên.
  3. Trao đổi chúng.
  4. Gói các giá trị hoán đổi thành một số nguyên một lần nữa.
  5. Bản đồ ℤ → + sử dụng | 2n | + (n≥0) . Một lần nữa, ánh xạ này được chọn sao cho nó hủy bỏ ánh xạ ℕ → ẩn trong khi đóng gói, ngoại trừ việc nó dịch chuyển giá trị lên 1.

Với cách đó, chúng ta có thể xem chương trình:

/o
\i@/...

Đây chỉ đơn giản là một khung cho các chương trình số học tuyến tính với đầu vào và đầu ra số nguyên.

.    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

Octave , 71 68 byte

3 byte được lưu nhờ Conor O'Brien .

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

Điều này không hoạt động cho đầu vào lớn do giới hạn bộ nhớ.

Hãy thử trực tuyến!

Giải trình

Xem xét đầu vào n = 4. Mã đầu tiên xây dựng ma trận

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

Sau đó, nó sẽ thay thế các mục khác không theo thứ tự cột lớn (xuống, sau đó qua) bởi 1, 2, 3...:

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

Sau đó, nó lật ma trận theo chiều dọc:

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

Cuối cùng, nó lấy ngiá trị khác không thứ tự theo thứ tự chính của cột, trong trường hợp này là 6.


1
@ rahnema1 Đó elà thiên tài! Bạn chắc chắn nên đăng nó như một câu trả lời, cùng với các đề xuất rất tốt khác của bạn. Về phần ans =, tôi không bao giờ chắc chắn nó có hợp lệ hay không
Luis Mendo

4

Haskell , 31 byte

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

Hãy thử trực tuyến!

Câu trả lời này chỉ sử dụng công thức. Đây là câu trả lời ít thú vị nhất ở đây, nhưng nó cũng là câu lạc bộ nhất.

Haskell , 38 36 34 byte

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

Hãy thử trực tuyến!

(!0) là chức năng miễn phí điểm chúng tôi quan tâm.

Giải trình

Hãy để tôi bắt đầu bằng cách nói rằng tôi rất hài lòng với câu trả lời này.

Ý tưởng cơ bản ở đây là nếu chúng ta loại bỏ số tam giác lớn nhất nhỏ hơn đầu vào của chúng ta, chúng ta có thể đảo ngược nó và thêm số tam giác trở lại. Vì vậy, chúng tôi xác định một toán tử !, !lấy đầu vào thường xuyên của chúng tôi x, nhưng nó cũng cần thêm một số y. ytheo dõi kích thước của số tam giác đang phát triển. Nếu x>ychúng ta muốn recurse, chúng tôi giảm xdo yvà tăng ymột. Vì vậy, chúng tôi tính toán (x-y)!(y+1)và thêm y+1vào nó. Nếu x<=ychúng tôi đã đạt được trường hợp cơ bản của chúng tôi, để đảo ngược xvị trí của hàng trong tam giác chúng tôi trả lại 1-x.

Haskell , 54 byte

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

Hãy thử trực tuyến!

(!!)$0:(>>=)[1..]f là một hàm miễn phí

Giải trình

Điều đầu tiên chúng ta quan tâm là f, fmột hàm lấy xvà trả về xhàng thứ ba của tam giác ngược. Nó thực hiện điều này bằng cách tính x-1số tam giác thứ n và gán cho nó u. u<-div(x^2-x)2. Chúng tôi sau đó trả lại danh sách [u+x,u+x-1..u+1]. u+xxsố tam giác thứ và số thứ nhất trên hàng, u+x-1nhỏ hơn số đó và số thứ hai trên hàng u+1nhiều hơn số tam giác cuối cùng và do đó là số cuối cùng trên hàng.

Một khi chúng ta có fmột danh sách (>>=)[1..]f, đó là làm phẳng hình tam giác. Chúng tôi thêm số 0 vào trước 0:để các câu trả lời của chúng tôi sẽ không bị bù trừ bởi một và cung cấp cho hàm lập chỉ mục của chúng tôi (!!).

Haskell , 56 byte

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

Hãy thử trực tuyến!

Cái này dài hơn 2 byte nhưng theo tôi thì thanh lịch hơn một chút.


3

C (gcc) , 48 byte

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

Hãy thử trực tuyến!

Có lẽ là tối ưu, nhưng tôi khá hài lòng với cái này. Sử dụng thực tế là

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

(Nếu tôi viết công thức xuống một cách chính xác, đó là.)


Bạn không gọi trả về, nhưng giá trị trả về được sử dụng. Đó là hành vi không xác định.
2501

@ 2501 Miễn là chương trình hoạt động, nó được cho phép. Và, viết vào đối số đầu tiên của hàm tương đương với trả về một giá trị.
Conor O'Brien

Và, viết vào đối số đầu tiên của hàm tương đương với trả về một giá trị. Không có điều đó tồn tại trong ngôn ngữ C. Tiêu chuẩn thậm chí nói rõ ràng bằng cách sử dụng giá trị được trả về từ một hàm không trả về là hành vi không xác định.
2501

1
@ 2501 Bạn dường như nhầm lẫn môi trường C (gcc) cho đặc tả C. Có, ngôn ngữ / thông số C gọi nó là không xác định, nhưng nó được thực hiện như vậy. Vì vậy, khi tôi nói "tương đương", tôi chắc chắn đề cập đến việc triển khai C bởi gcc và hầu hết các trình biên dịch khác. Trên PPCG, chúng tôi không viết mã "hoàn hảo" - nhiều mã đi ngược lại đặc điểm kỹ thuật vì mục đích chơi gôn. Như tôi đã nói, miễn là nó hoạt động, đó là một câu trả lời hợp lệ.
Conor O'Brien

@ 2501 Tôi khuyến khích bạn đọc một số bài viết trên trang meta, đặc biệt là bài này .
Conor O'Brien

2

05AB1E , 30 byte

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

Hãy thử trực tuyến!


Tôi chuẩn bị nói "Cái gì? Câu trả lời 05AB1E không có Unicode?" nhưng sau đó, một nhân vật không phải ASCII sẽ phá hỏng nó ...: Mặc dù vậy, câu trả lời đầu tiên rất hay, chào mừng bạn đến với Câu đố lập trình và Code Golf!
clismique

@ Qwerp-Derp Cảm ơn bạn rất nhiều! Tôi mới bắt đầu học ngôn ngữ này, vì vậy tôi không ngạc nhiên khi câu trả lời của tôi tệ đến thế.
Eduardo Hoefel

2

Husk , 6 byte

!ṁ↔´CN

Hãy thử trực tuyến!

Giải trình

!ṁ↔´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 byte

(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

Xác định hàm fthực hiện ánh xạ. Hãy thử trực tuyến!

Ung dung

Chúng tôi tìm thấy số tam giác nhỏ nhất lớn hơn hoặc bằng số đầu vào, cũng như hàng của tam giác mà số của chúng tôi nằm trong đó. Từ những số này, chúng tôi có thể tính toán phiên bản lật của số.

  • Nếu số tam giác hiện tại nhỏ hơn N, hãy lặp lại hàng tiếp theo của tam giác. (Chúng tôi coi hàng trên cùng là hàng 2 để làm cho phép toán đơn giản hơn.)
  • Mặt khác, phiên bản lật của N là (TN) + (TR) +2.

Hàm chính flipchỉ đơn giản gọi hàm trợ giúp _flipbắt đầu từ hàng trên cùng.

(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 byte

·LD£í˜¹<è

Hãy thử trực tuyến!

Giải trình

·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

Không may làm phẳng mảng không xử lý danh sách lớn hơn rất tốt.
Với chi phí 1 byte, chúng tôi có thể thực hiện · t2z + ïn¹-> bằng cách sử dụng công thức toán học floor(sqrt(2*n)+1/2)^2 - n + 1được tìm thấy trên OEIS .


1

Mẻ, 70 byte

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

Sử dụng một vòng lặp để tìm chỉ số của số tam giác ít nhất là lớn bằng n.




0

APL (Dyalog), 27 byte

Tôi đã có hai giải pháp tại cùng một bytecount.

Một chuyến tàu:

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

Hãy thử trực tuyến!

Và một dfn:

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

Hãy thử trực tuyến!

Cả hai giải pháp này trước tiên tạo ra tam giác lật và sau đó trích xuất phần tử tại chỉ mục được nêu bởi đối số ( 1dựa trên cơ sở).


0

J, 25 byte

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

Như một lời giải thích, xem xét f(n) = n(n+1)/2. f(r), được đưa ra hàng r, trả về số ngoài cùng bên trái của hàng rthứ ba của tam giác được nhân đôi. Bây giờ, hãy xem xét g(n) = ceiling[f⁻¹(n)]. g(i), đưa ra chỉ mục i, trả về hàng mà chỉ mục i được tìm thấy. Sau đó, f(g(n))trả về số ngoài cùng bên trái của hàng mà chỉ số n được tìm thấy. Vì vậy, h(n) = f(g(n)) - (n - f(g(n)-1)) + 1là câu trả lời cho vấn đề trên.

Đơn giản hóa, chúng tôi nhận được h(n) = [g(n)]² - n + 1 = ceiling[(-1 + sqrt(1 + 8n))/2]² - n + 1 .

Từ vẻ ngoài của công thức @ Arnauld, có vẻ như:

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


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.