Flip angka segitiga

30

Katakanlah Anda mencantumkan bilangan bulat positif dalam segitiga, lalu balikkan dari kiri ke kanan. Diberi nomor, tampilkan nomor yang dikirim. Ini adalah pemetaan terbalik sendiri.

         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

Ini adalah elemen ke- 9 dari A038722 , yang diindeks satu:

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

Urutan ini membalik potongan yang berdekatan dari bilangan bulat positif dengan panjang yang bertambah:

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

Kasus uji:

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

Papan peringkat:

Tidak
sumber

Jawaban:

15

JavaScript (ES7), 26 byte

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

Implementasi formula berikut dari OEIS :

rumus

Demo

Arnauld
sumber
Saya suka operasi ATAU untuk memotongnya menjadi integer! pekerjaan yang baik!
CraigR8806
7

Jelly , 8 7 byte

RṁR€UFi

Terima kasih kepada @ErikTheOutgolfer untuk menghemat 1 byte!

Cobalah online!

Bagaimana itu bekerja

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.
Dennis
sumber
6

Alice , 27 byte

Terima kasih kepada Sp3000 untuk .Cidenya.

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

Cobalah online!

Penjelasan

Saya pikir mungkin ada cara yang lebih pendek untuk menghitung ini menggunakan angka segitiga, tapi saya pikir ini adalah penyalahgunaan yang menarik dari built-in, jadi inilah solusi yang berbeda.

Ide dasarnya adalah memanfaatkan "bawaan" Alice dan "membongkar" bawaan. "Paket", atau Z, mengambil dua bilangan bulat memetakannya secara bijektif ke satu bilangan bulat. "Buka kemasan", atau Y, membalikkan bualan ini dan mengubah satu bilangan bulat menjadi dua. Biasanya, ini dapat digunakan untuk menyimpan daftar atau pohon bilangan bulat dalam satu bilangan bulat (besar) dan memulihkan nilai individu nanti. Namun, dalam hal ini kita dapat menggunakan fungsi dalam urutan yang berlawanan, untuk membiarkan sifat dari penambangan bekerja untuk kita.

Membongkar satu bilangan bulat menjadi dua bilangan bulat pada dasarnya terdiri dari tiga langkah:

  1. Peta ℤ → ℕ (termasuk nol) dengan "lipat" sederhana. Yaitu, memetakan bilangan bulat negatif ke naturals yang aneh, dan bilangan bulat non-negatif ke naturals genap.
  2. Peta ℕ → ℕ 2 , menggunakan fungsi pemasangan Cantor . Yaitu, naturals ditulis di sepanjang diagonal grid yang tak terbatas dan kami mengembalikan indeks:

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

    Misalnya 8akan dipetakan ke pasangan (1, 2).

  3. Peta 2 → ℤ 2 , menggunakan kebalikan dari langkah 1 pada setiap bilangan bulat secara individual. Artinya, naturals yang aneh dipetakan ke bilangan bulat negatif, dan bahkan naturals dipetakan ke bilangan bulat yang tidak negatif.

Untuk mengemas dua bilangan bulat menjadi satu, kita cukup membalikkan masing-masing langkah tersebut.

Sekarang, kita dapat melihat bahwa struktur fungsi pasangan Cantor dengan mudah mengkodekan segitiga yang kita butuhkan (walaupun nilainya tidak dalam satu per satu). Untuk membalikkan diagonal itu, yang perlu kita lakukan adalah menukar koordinat x dan y ke dalam kisi.

Sayangnya, karena ketiga langkah di atas digabungkan menjadi satu built-in Y(atau Z), kita perlu membatalkan pemetaan ℤ → ℕ atau ℕ → ℤ sendiri. Namun, saat melakukan itu kita dapat menyimpan beberapa byte dengan langsung menggunakan pemetaan ℕ + → ℤ atau ℤ → ℕ + , untuk mengatasi kesalahan off-by-one dalam tabel. Jadi di sini adalah keseluruhan algoritma:

  1. Peta + → ℤ menggunakan (n / 2) * (-1) n-1 . Pemetaan ini dipilih sedemikian rupa sehingga membatalkan pemetaan implisit ℤ → ℕ selama pembongkaran, kecuali bahwa ia menggeser nilainya menjadi 1.
  2. Bongkar hasilnya menjadi dua bilangan bulat.
  3. Tukar mereka.
  4. Kemas nilai yang ditukar menjadi satu integer lagi.
  5. Peta ℤ → ℕ + menggunakan | 2n | + (n≥0) . Sekali lagi, pemetaan ini dipilih sedemikian rupa sehingga membatalkan pemetaan ℕ → ℤ implisit selama pengepakan, kecuali bahwa nilai tersebut naik nilainya sebesar 1.

Dengan itu, kita dapat melihat program:

/o
\i@/...

Ini hanyalah kerangka kerja untuk program aritmatika linier dengan input dan output integer.

.    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).
Martin Ender
sumber
5

Jelly , 8 byte

Ḥ½+.Ḟ²‘_

Cobalah online!

Port jawaban MATL saya.

Luis Mendo
sumber
4

MATL , 15 11 byte

EX^.5+kUG-Q

Cobalah online!

Ini menggunakan rumus

a(n) = floor(sqrt(2*n)+1/2)^2 - n + 1.
Luis Mendo
sumber
4

Oktaf , 71 68 byte

3 byte disimpan berkat Conor O'Brien .

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

Ini tidak berfungsi untuk input besar karena keterbatasan memori.

Cobalah online!

Penjelasan

Pertimbangkan input n = 4. Kode pertama membangun matriks

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

Kemudian menggantikan entri tidak nol dalam kolom-besar order (bawah, kemudian di) oleh 1, 2, 3...:

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

Kemudian ia membalik matriks secara vertikal:

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

Akhirnya, dibutuhkan nilai nbukan-nol dalam urutan kolom-utama, yang dalam hal ini adalah 6.

Luis Mendo
sumber
1
@ rahnema1 Itu ejenius! Anda harus mempostingnya sebagai jawaban, bersama dengan saran Anda yang sangat bagus lainnya. Adapun ans =, saya tidak pernah yakin itu valid atau tidak
Luis Mendo
4

Haskell , 31 byte

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

Cobalah online!

Jawaban ini hanya menggunakan rumus. Ini adalah jawaban yang paling tidak menarik di sini, tetapi juga merupakan golfiest.

Haskell , 38 36 34 byte

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

Cobalah online!

(!0) adalah fungsi titik bebas yang menjadi perhatian kita.

Penjelasan

Biarkan saya memulai dengan mengatakan saya sangat senang dengan jawaban ini.

Ide dasar di sini adalah bahwa jika kita menghapus angka segitiga terbesar lebih kecil dari input kita, kita dapat membalikkannya dan menambahkan angka segitiga kembali. Jadi kami mendefinisikan operator !, !mengambil input reguler kami x, tetapi juga mengambil angka tambahan y. ymelacak ukuran angka segitiga yang tumbuh. Jika x>ykita ingin recurse, kami menurunkan xoleh ydan meningkatkan yper satu. Jadi kami menghitung (x-y)!(y+1)dan menambahkannya y+1. Jika x<=ykita telah mencapai base case kita, untuk membalikkan xpenempatan di deretan segitiga kita kembali 1-x.

Haskell , 54 byte

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

Cobalah online!

(!!)$0:(>>=)[1..]f adalah fungsi point-free

Penjelasan

Hal pertama yang kami perhatikan adalah f, fadalah fungsi yang mengambil xdan mengembalikan xderetan ke tiga dari segitiga secara terbalik. Ini dilakukan dengan terlebih dahulu menghitung angka x-1segitiga nd dan menetapkannya u. u<-div(x^2-x)2. Kami kemudian mengembalikan daftar [u+x,u+x-1..u+1]. u+xadalah angka xsegitiga ke - t dan angka pertama pada baris, u+x-1adalah satu kurang dari itu dan angka kedua pada baris u+1adalah satu lebih dari angka segitiga terakhir dan dengan demikian angka terakhir pada baris.

Setelah kita memiliki fkita membentuk daftar (>>=)[1..]f, yang merupakan perataan segitiga. Kami menambahkan nol ke depan dengan 0:sehingga jawaban kami tidak akan diimbangi oleh satu, dan menyediakannya ke fungsi pengindeksan kami (!!).

Haskell , 56 byte

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

Cobalah online!

Yang ini 2 byte lebih lama tapi menurut saya agak lebih elegan.

Wisaya Gandum
sumber
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;}

Cobalah online!

Mungkin suboptimal, tapi saya cukup senang dengan yang ini. Menggunakan fakta itu

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

(Jika saya menuliskan formula dengan benar, itu adalah.)

Conor O'Brien
sumber
Anda tidak menelepon pengembalian, tetapi nilai pengembalian digunakan. Itu adalah perilaku yang tidak terdefinisi.
2501
@ 2501 Selama program bekerja, itu diizinkan. Dan, menulis ke argumen pertama dari suatu fungsi sama dengan mengembalikan nilai.
Conor O'Brien
Dan, menulis ke argumen pertama dari suatu fungsi sama dengan mengembalikan nilai. Tidak ada hal seperti itu dalam bahasa C. Standar bahkan secara eksplisit mengatakan menggunakan nilai yang dikembalikan dari fungsi yang tidak kembali adalah perilaku yang tidak terdefinisi.
2501
1
@ 2501 Anda sepertinya membingungkan lingkungan C (gcc) untuk spesifikasi C. Ya, bahasa C / spesifikasi menyebutnya tidak terdefinisi, tetapi diimplementasikan seperti itu. Jadi ketika saya mengatakan "setara", saya paling pasti merujuk pada implementasi C oleh gcc dan kebanyakan kompiler lainnya. Di PPCG, kami tidak menulis kode "sempurna" - banyak kode bertentangan dengan spesifikasi demi golf. Seperti yang saya katakan, selama ini berfungsi, itu adalah jawaban yang valid.
Conor O'Brien
@ 2501 Saya mendorong Anda untuk membaca beberapa artikel di situs meta, terutama yang ini .
Conor O'Brien
2

05AB1E , 30 byte

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

Cobalah online!

Eduardo Hoefel
sumber
Aku hampir mengatakan, "Apa? Jawaban 05AB1E tanpa Unicode?" tapi kemudian satu karakter non-ASCII merusaknya ...: P Jawaban pertama yang bagus, selamat datang di Programming Puzzles dan Code Golf!
clismique
@ Qwerp-Derp Terima kasih banyak! Saya baru mulai belajar bahasa ini, jadi saya tidak terkejut jawaban saya seburuk itu.
Eduardo Hoefel
2

Sekam , 6 byte

!ṁ↔´CN

Cobalah online!

Penjelasan

!ṁ↔´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
ბიმო
sumber
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

Menentukan fungsi fyang melakukan pemetaan. Cobalah online!

Tidak disatukan

Kami menemukan bilangan segitiga terkecil yang lebih besar dari atau sama dengan bilangan masukan, serta deretan mana dari segitiga bilangan kita. Dari ini, kita dapat menghitung versi bilangan terbalik dari bilangan tersebut.

  • Jika angka segitiga saat ini kurang dari N, kembalilah ke baris berikutnya dari segitiga. (Kami memperlakukan baris teratas sebagai baris 2 untuk membuat matematika lebih sederhana.)
  • Jika tidak, versi N yang terbalik adalah (TN) + (TR) +2.

Fungsi utama flipcukup memanggil fungsi helper _flipmulai dari baris atas.

(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)))
DLosc
sumber
1

05AB1E , 9 byte

·LD£í˜¹<è

Cobalah online!

Penjelasan

·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

Perataan array sayangnya tidak menangani daftar yang lebih besar dengan sangat baik.
Dengan biaya 1 byte kita bisa melakukan · t2z + ïn¹-> menggunakan rumus matematika yang floor(sqrt(2*n)+1/2)^2 - n + 1ditemukan di OEIS .

Emigna
sumber
1

Batch, 70 byte

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

Menggunakan loop untuk menemukan indeks angka segitiga setidaknya sebesar n.

Neil
sumber
0

PHP, 35 Bytes

<?=((2*$argn)**.5+.5^0)**2-$argn+1;

Formula yang sama yang digunakan dalam Pendekatan Arnaulds

Jörg Hülsermann
sumber
0

C #, 46 44 byte

n=>Math.Pow((int)(Math.Sqrt(2*n)+.5),2)-n+1;

Saya port solusi @ Arnauld . Terima kasih!

  • Pow 0,5 adalah Sqrt. 2 byte disimpan!
aloisdg kata Reinstate Monica
sumber
0

APL (Dyalog), 27 byte

Saya punya dua solusi di bytecount yang sama.

Kereta:

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

Cobalah online!

Dan sebuah dfn:

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

Cobalah online!

Kedua solusi ini pertama-tama membuat segitiga terbalik dan kemudian mengekstrak elemen pada indeks yang dinyatakan oleh argumen ( 1berbasis).

Kritixi Lithos
sumber
0

J, 25 byte

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

Sebagai penjelasan, pertimbangkan f(n) = n(n+1)/2. f(r), mengingat baris r, mengembalikan angka paling kiri dari baris rke-3 dari segitiga cermin. Sekarang, pertimbangkan g(n) = ceiling[f⁻¹(n)]. g(i), mengingat indeks i, mengembalikan baris di mana indeks saya ditemukan. Kemudian, f(g(n))kembalikan angka paling kiri dari baris di mana indeks n ditemukan. Begitu,h(n) = f(g(n)) - (n - f(g(n)-1)) + 1 inilah jawaban untuk masalah di atas.

Menyederhanakan, kita dapatkan h(n) = [g(n)]² - n + 1 = ceiling[(-1 + sqrt(1 + 8n))/2]² - n + 1 .

Dari tampilan rumus @ Arnauld, tampak bahwa:

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

ljeabmreosn
sumber
0

Pyt , 13 12 byte

←Đ2*√½+⌊²-~⁺

Pendekatan Port of Arnauld

mudkip201
sumber