Sayı üçgen çevirme


30

Olumlu tamsayıları bir üçgen halinde listelediğinizi söyleyin, ardından sağdan sola çevirin. Bir sayı verildiğinde, gönderildiği numarayı verin. Bu kendi kendine ters bir haritalamadır.

         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

Bu , bir dizinli A038722’nin n'ci öğesi :

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

Bu dizi artan tamsayılarla pozitif tamsayıların bitişik parçalarını tersine çevirir:

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

Test durumları:

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

Liderler Sıralaması:

Yanıtlar:



7

Jöle , 8 7 bayt

RṁR€UFi

1 byte tasarrufu için @ErikTheOutgolfer'a teşekkürler!

Çevrimiçi deneyin!

Nasıl çalışır

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 bayt

Fikir için Sp3000'e teşekkürler .C.

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

Çevrimiçi deneyin!

açıklama

Üçgen sayıları kullanarak bunu hesaplamanın daha kısa bir yolu olabileceğini düşünüyorum, ancak bunun yerleşik bir işlemin ilginç bir suistimali olduğunu düşündüm, bu yüzden farklı bir çözüm.

Temel fikir, Alice'in "paketini" ve "paketini açma" yerleşiklerini kullanmaktır. "Paket", veya Ziki tamsayı alır, bunları tek bir tamsayıya kasten teker teker eşler. "Paketi aç" veya Ybu önyüklemeyi tersine çevirir ve bir tamsayıyı ikiye dönüştürür. Normalde bu, bir tamsayı listesini veya tek bir büyük tamsayı ağacında saklamak ve daha sonra bireysel değerleri kurtarmak için kullanılabilir. Bununla birlikte, bu durumda, önyüklemenin doğasının bizim için çalışmasına izin vermek için işlevleri ters sırayla kullanabiliriz.

Bir tamsayının iki tamsayıya açılması temel olarak üç adımdan oluşur:

  1. " →" (sıfır dahil) basit bir "katlama" ile eşleştirin . Yani, negatif tamsayıları garip doğallara, negatif olmayan tamsayıları bile doğallara eşleyin.
  2. Harita ℕ → ℕ 2 kullanılarak, Cantor eşleştirme işlevini . Yani, doğallar sonsuz bir şebekenin köşegenleri boyunca yazılır ve biz endeksleri döndürürüz:

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

    Örneğin 8, eş ile eşleştirilecek (1, 2).

  3. Harita 2 → ℤ 2 , tek tek her tamsayı üzerinde 1. adımda tersinin kullanılması. Başka bir deyişle, garip doğal maddeler negatif tam sayılara eşleştirilir ve doğal bile negatif olmayan tam sayılara eşlenir.

İki tamsayı bir araya getirmek için, bu adımların her birini tersine çeviririz.

Artık, Cantor eşleştirme fonksiyonunun yapısının, ihtiyaç duyduğumuz üçgeni rahatça kodladığını görebiliyoruz (değerler tek tek olmasına rağmen). Bu köşegenleri ters çevirmek için tek yapmamız gereken, x ve y koordinatlarını ızgaraya değiştirmek.

Ne yazık ki, yukarıdaki üç adımın tümü tek bir yerleşik Y(veya Z) olarak birleştirildiğinden , ℤ → ℕ veya ℕ → ℤ eşlemelerini kendimiz yapmamız gerekiyor . Bununla birlikte, bunu yaparken tablodaki hataların giderilmesi için doğrudan + → ℤ veya ℤ → ℕ + eşlemelerini kullanarak birkaç bayt tasarrufu yapabiliriz . Yani burada tüm algoritma:

  1. Harita + → ℤ kullanılarak (n / 2) * (1) , n-1 . Bu eşleme, paket açma sırasında örtülü ℤ → ℕ eşleştirmeyi iptal edecek şekilde seçilir , ancak değeri 1'e düşürür.
  2. Sonucu iki tamsayı halinde açın.
  3. Onları değiştir.
  4. Değiştirilen değerleri tekrar tek bir tamsayıya yerleştirin.
  5. Harita ℤ → ℕ + kullanma | 2n | + (n≥0) . Yine, bu haritalama, paketleme sırasında ℕ → ℤ haritalama özelliğini iptal ettiği , değeri 1'e yükseltmesi haricinde seçilmiştir.

Bunun dışında programa bakabiliriz:

/o
\i@/...

Bu sadece tamsayı giriş ve çıkışa sahip doğrusal aritmetik programları için bir çerçevedir.

.    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 bayt

Conor O'Brien sayesinde 3 bayt kurtarıldı .

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

Bu, bellek sınırlamaları nedeniyle büyük girişler için işe yaramaz.

Çevrimiçi deneyin!

açıklama

Girişi düşünün n = 4. Kod önce matrisi oluşturur

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

Sonra tarafından (daha sonra karşısındaki aşağı) kolon-majör sırayla sıfırdan farklı girdileri değiştirir 1, 2, 3...:

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

Sonra matrisi dikey olarak çevirir:

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

Son olarak, nbu durumda, sütun ana düzeninde sıfır olmayan değeri alır 6.


1
@ rahnema1 Bu edahi! Diğer çok iyi önerilerinizle birlikte kesinlikle bir cevap olarak göndermelisiniz. Gelince ans =, ben 's geçerli olup olmadığına emin değilim
Luis Mendo

4

Haskell , 31 bayt

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

Çevrimiçi deneyin!

Bu cevap sadece formülü kullanır. Buradaki en ilginç cevap bu, ancak aynı zamanda en golfçü de oluyor.

Haskell , 38 36 34 bayt

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

Çevrimiçi deneyin!

(!0) endişe duyduğumuz noktadan bağımsız fonksiyondur.

açıklama

Bu cevaptan çok memnun olduğumu söyleyerek başlayayım.

Buradaki temel fikir, girdilerimizden daha küçük olan en büyük üçgen sayıyı kaldırırsak, onu tersine çevirip üçgen sayıyı geri ekleyebiliriz. Böylece bir operatör tanımlarız !, !düzenli girdilerimizi alır x, fakat aynı zamanda fazladan bir sayı alır y. yBüyüyen üçgen sayısının büyüklüğünü takip eder. Eğer x>ybiz Recurse istiyoruz, azaltmak xtarafından yve arttırmak ytek. Bu yüzden hesaplar (x-y)!(y+1)ve ekleriz y+1. Eğer x<=ybizim temel davayı ulaşmış, ters xdönmek üçgenin satırındaki 'ın yerleşimi 1-x.

Haskell , 54 bayt

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

Çevrimiçi deneyin!

(!!)$0:(>>=)[1..]f puansız bir işlevdir

açıklama

Biz ise ilgileniyoruz ilk şey f, fgötüren bir fonksiyondur xve döner xters içinde inci üçgenin inci satırı. Bunu ilk önce x-1nd üçgen sayıyı hesaplayarak ve ona atayarak yapar u. u<-div(x^2-x)2. Sonra listeye geri döndük [u+x,u+x-1..u+1]. u+xbu xüçgensel sayıdır ve satırdaki ilk sayı, u+x-1ondan daha azdır ve satırdaki ikinci sayı u+1, son üçgen sayıdan bir veya daha fazla olduğu için satırdaki son sayıdır.

Bir zamanlar üçgenin düzleşmesi olan fbir liste oluştururuz (>>=)[1..]f. Cepheye sıfır ekleriz, 0:böylece cevaplarımız birer birer mahsup edilemez ve onu indeksleme işlevimize sunarız (!!).

Haskell , 56 bayt

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

Çevrimiçi deneyin!

Bu, 2 bayt daha uzun ama bence biraz daha şık.


3

C (gcc) , 48 bayt

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

Çevrimiçi deneyin!

Muhtemelen yetersiz, ama bununla çok mutluyum. Gerçeği kullanır

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

(Formülü doğru yazdıysam, budur.)


Geri dönüşü aramıyorsunuz, ancak geri dönüş değeri kullanılıyor. Bu tanımsız davranış.
2501

@ 2501 Program çalıştığı sürece izin verilir. Ve bir fonksiyonun ilk argümanına yazmak, bir değer döndürmeye eşdeğerdir.
Conor O'Brien,

Ve bir fonksiyonun ilk argümanına yazmak, bir değer döndürmeye eşdeğerdir. C dilinde böyle bir şey yoktur. Standart bile açıkça, döndürmeyen değeri döndürmeyen bir işlevden kullanmanın tanımsız davranış olduğunu söylüyor.
2501

1
@ 2501 C belirtimi için C ortamını (gcc) karıştırıyor gibi görünüyorsunuz. Evet, C dili / belirtimi tanımsız olarak adlandırıyor, ancak böyle gerçekleştiriliyor. Bu yüzden "eşdeğer" derken, kesinlikle C'nin gcc ve diğer birçok derleyici tarafından uygulanmasından bahsediyorum. PPCG'de "mükemmel" bir kod yazmıyoruz - çoğu kod golf oynamak için şartnameye aykırı. Dediğim gibi, çalıştığı sürece geçerli bir cevap.
Conor O'Brien,

@ 2501 Sizi meta sitesinde, özellikle de bu konuyla ilgili bazı makaleler okumanızı tavsiye ediyorum .
Conor O'Brien,

2

05AB1E , 30 bayt

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

Çevrimiçi deneyin!


"Ne? Unicode'suz bir 05AB1E cevabı?" Demek üzereydim. ama sonra ASCII olmayan karakter onu mahveder ...: P Nice ilk cevap olsa da, Programming Puzzles ve Code Golf'a hoş geldiniz!
clismique

@ Qwerp-Derp Çok teşekkürler! Bu dili öğrenmeye yeni başladım, bu yüzden cevabımın o kadar kötü olmasına şaşırmadım.
Eduardo Hoefel

2

Kabuğu , 6 bayt

!ṁ↔´CN

Çevrimiçi deneyin!

açıklama

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

(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

fEşleştirmeyi gerçekleştiren bir işlevi tanımlar . Çevrimiçi deneyin!

Ungolfed

Girdi numarasına eşit veya ondan daha küçük olan en küçük üçgen sayıyı ve sayımızın olduğu üçgenin sırasını bulduk. Bunlardan sayının çevrilmiş halini hesaplayabiliriz.

  • Eğer mevcut üçgen sayı N'den az ise, üçgenin bir sonraki satırına kadar tekrar edin. (Matematiği kolaylaştırmak için en üst satırı 2. satır olarak kabul ediyoruz.)
  • Aksi takdirde, N'nin çevrilmiş versiyonu (TN) + (TR) +2'dir.

Ana işlev, flipsadece _flipüst satırdan başlayarak yardımcı işlevi çağırır .

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

·LD£í˜¹<è

Çevrimiçi deneyin!

açıklama

·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

Dizi düzleştirmesi maalesef daha büyük listeleri çok iyi ele almıyor.
1 byte pahasına Yapabileceğimiz · T2Z + ïn¹-> matematiksel formül kullanılarak floor(sqrt(2*n)+1/2)^2 - n + 1bulunabilir OEIS .


1

Toplu iş, 70 bayt

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

Üçgen sayının indeksini en az olduğu kadar büyük bulmak için bir döngü kullanır n.




0

APL (Dyalog), 27 bayt

Aynı bytecountta iki çözümüm var.

Bir tren:

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

Çevrimiçi deneyin!

Ve bir dfn:

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

Çevrimiçi deneyin!

Bu çözümlerin her ikisi de önce döndürülmüş üçgeni yaratır ve daha sonra argüman ( 1-based) tarafından belirtilen dizinde öğeyi çıkartır.


0

J, 25 bayt

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

Bir açıklama olarak düşünün f(n) = n(n+1)/2. f(r), satır verildiğinde , yansıtılmış üçgenin inci satırının ren solundaki sayıyı döndürür . Şimdi düşünün . , dizine verilen i'nin bulunduğu dizine döner. Ardından, n dizininin bulunduğu satırın en solundaki sayıyı döndürür. Yani, yukarıdaki sorunun cevabı.rg(n) = ceiling[f⁻¹(n)]g(i)if(g(n))h(n) = f(g(n)) - (n - f(g(n)-1)) + 1

Basitleştirilmiş, anlıyoruz h(n) = [g(n)]² - n + 1 = ceiling[(-1 + sqrt(1 + 8n))/2]² - n + 1.

@ Arnauld'un formülünün görünümünden, şöyle görünüyor:

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


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.