Hitung mundur dan kembali kemudian gandakan


24

Mari berhitung...

Hitung hingga 2 dan kembali ke 1
Hitung hingga 4 dan kembali ke 1
Hitung hingga 6 dan kembali ke 1
... ok Anda mendapatkannya ...

kumpulkan semuanya dan Anda akan mendapatkan urutan berikut

 {1,2,1,2,3,4,3,2,1,2,3,4,5,6,5,4,3,2,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1,2,3...}

Tantangan
Diberikan bilangan bulat n>0untuk 1-diindeks (atau n>=0untuk 0-diindeks), output istilah ke-n dari urutan ini

Uji kasus

Input->Output  

1->1  
68->6  
668->20  
6667->63  
10000->84

Aturan

program Anda harus dapat menghitung solusi hingga n = 10.000 dalam waktu kurang dari satu menit

Ini adalah , jadi kode terpendek dalam byte menang!


2
Siapa yang memutuskan apa yang membutuhkan waktu sebentar? Mesin Turing optimal waktu yang dibuat dari lego akan membutuhkan waktu yang sangat lama, sementara mesin Turing yang sama disimulasikan dalam, katakanlah, C, mungkin akan memakan waktu beberapa detik, atau menit, tergantung pada prosesor yang berjalan. Jadi, jika saya kirim kata deskripsi mesin Turing, apakah itu valid?
Arthur

2
@Arthur Saya pikir Anda bisa mengerti mengapa saya membuat batasan ini ... Saya tidak ingin algoritma mengambil "selamanya" untuk menemukan n = 10.000 dengan membuat daftar besar. Kebanyakan orang di sini memberikan jawaban yang brilian yang menemukan jutaan dalam hitungan detik.

4
@ BillSteihn Saya pikir pembatasan itu tidak perlu.
Erik the Outgolfer

2
@EriktheOutgolfer golf gode jawaban bisa rumit ... tanpa batasan, jawaban yang menghasilkan 10.000 tupel [1,2 ... 2n.2. 2] akan valid. Pembatasan hanya untuk jawaban seperti ini. t melihat di mana masalahnya. Saya hanya ingin jawaban Anda menemukan semua kasus uji dalam jumlah waktu yang wajar.

3
@ StraklSeth Konsensus umum di sini adalah bahwa ia harus bekerja secara teori, tidak harus dalam praktik.
Erik the Outgolfer

Jawaban:


16

JavaScript (ES7),  59 ... 44  43 byte

Disimpan 1 byte berkat Titus

Input yang diharapkan: 1-diindeks.

n=>(n-=(r=(~-n/2)**.5|0)*r*2)<++r*2?n:r*4-n

Awalnya terinspirasi oleh formula untuk A004738 , yang merupakan urutan yang sama. Tetapi akhirnya saya menulis ulang seluruhnya.

Uji kasus

Bagaimana?

Urutan dapat disusun sebagai segitiga, dengan bagian kiri dalam urutan menaik dan bagian kanan dalam urutan menurun.

Di bawah ini adalah 4 baris pertama, berisi 32 istilah pertama:

            1 | 2
        1 2 3 | 4 3 2
    1 2 3 4 5 | 6 5 4 3 2
1 2 3 4 5 6 7 | 8 7 6 5 4 3 2

Sekarang, mari kita perkenalkan beberapa variabel:

 row  | range   | ascending part              | descending part
 r    | x to y  | 1, 2, ..., i                | 4(r+1)-(i+1), 4(r+1)-(i+2), ...
------+---------+-----------------------------+-----------------------------------------
  0   |  1 -  2 |                           1 | 4-2
  1   |  3 -  8 |                   1   2   3 | 8-4  8-5  8-6
  2   |  9 - 18 |           1   2   3   4   5 | 12-6 12-7 12-8  12-9  12-10
  3   | 19 - 32 |   1   2   3   4   5   6   7 | 16-8 16-9 16-10 16-11 16-12 16-13 16-14

Kami mulai dengan 2 elemen di bagian atas dan menambahkan 4 elemen di setiap baris baru. Oleh karena itu, jumlah elemen pada baris 0-diindeks r dapat dinyatakan sebagai:

a(r) = 4r + 2

Posisi awal 1-diindeks x dari baris r diberikan oleh jumlah dari semua istilah sebelumnya dalam seri aritmatika ini ditambah satu, yang mengarah ke:

x(r) = r * (2 + a(r - 1)) / 2 + 1
     = r * (2 + 4(r - 1) + 2) / 2 + 1
     = 2r² + 1

Secara timbal balik, diberi posisi 1 diindeks n dalam urutan, baris yang sesuai dapat ditemukan dengan:

r(n) = floor(sqrt((n - 1) / 2))

atau sebagai kode JS:

r = (~-n / 2) ** 0.5 | 0

Setelah kita tahu r (n) , kita kurangi posisi awal x (r) dikurangi satu dari n :

n -= r * r * 2

Kita membandingkan n dengan (r) / 2 + 1 = 2r + 2 untuk mengetahui apakah kita berada di bagian naik atau di bagian menurun:

n < ++r * 2 ?

Jika ungkapan ini benar, kami mengembalikan n . Kalau tidak, kita mengembalikan 4 (r + 1) - n . Tetapi karena r sudah bertambah dalam pernyataan terakhir, ini disederhanakan sebagai:

n : r * 4 - n

1
Ok, saya pikir saya mengerti. Panjang masing-masing bagian naik-turun adalah 2,6,10,14 ... sehingga jumlahnya tumbuh dengan kuadrat dari jumlah baris, maka sqrt. Sangat bagus!
JollyJoker

7

Haskell , 37 byte

(!!)$do k<-[1,3..];[1..k]++[k+1,k..2]

Cobalah online!

Diindeks nol. Buat daftar dan indeks ke dalamnya. Terima kasih kepada Ørjan Johansen karena telah menghemat 2 byte!


Haskell , 38 byte

(!!)[min(k-r)r|k<-[0,4..],r<-[1..k-2]]

Cobalah online!

Diindeks nol. Buat daftar dan indeks ke dalamnya.


Haskell , 39 byte

n%k|n<k=1+min(k-n)n|j<-k+4=(n-k)%j
(%2)

Cobalah online!

Diindeks nol. Metode rekursif.



5

Sekam , 8 byte

!…ṁoe1DN

1-diindeks. Cobalah online!

Penjelasan

!…ṁoe1DN  Implicit input (an integer).
       N  Positive integers: [1,2,3,4,...
  ṁo      Map and concatenate
      D   double: [2,4,6,8,...
    e1    then pair with 1: [1,2,1,4,1,6,1,8,...
 …        Fill gaps with ranges: [1,2,1,2,3,4,3,2,1,2,3,4,5,6,...
!         Index with input.

3

Perl 6 , 29 byte

{({|(1...$+=2...2)}...*)[$_]}

Cobalah online

Berbasis 0

Diperluas:

{  # bare block lambda with implicit parameter 「$_」

  (
    # generate an outer sequence

    {           # bare block lambda

      |(        # flatten into outer sequence

        # generate an inner sequence

        1       # start at 1

        ...     # go (upward) towards:

        $       # an anonymous state variable (new one for each outer sequence)
          += 2  # increment by 2

        ...     # go (downward) towards:

        2       # stop at 2 (1 will come from the next inner sequence)

      )
    }

    ...         # keep generating the outer sequence until:
    *           # never stop

  )[ $_ ]       # index into outer sequence
}

Urutan dalam 1...$+=2...2menghasilkan

(1, 2).Seq
(1, 2, 3, 4, 3, 2).Seq
(1, 2, 3, 4, 5, 6, 5, 4, 3, 2).Seq
(1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2).Seq
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2).Seq
...

Untuk menjadikannya berbasis 1, tambahkan 0,sebelum yang kedua {, atau tambahkan -1setelah$_


3

R, 64 byte

function(n)unlist(sapply(seq(2,n,2),function(x)c(2:x-1,x:2)))[n]

Fungsi yang mengambil argumen n. Ini menciptakan vektor 2:ndengan penambahan 2. Untuk masing-masing, vektor 1:(x-1)dan x:2dibuat. Total ini akan lebih lama dari n. Kita unlistitu, untuk mendapatkan vektor dan mengambil nentri -th.


Bisakah Anda lakukan 1:n*2bukan seq(2,n,2)? Ini akan lebih besar dari yang Anda butuhkan tetapi itu akan baik-baik saja! Juga saya tidak berpikir ini bekerja dengan seq(2,n,2)untuk n=1anyway!
Giuseppe

2

Python 2 , 56 byte

def f(x):n=int((x/2)**.5);print 2*n-abs(2*n*n+2*n+1-x)+2

Cobalah online!

Ini diindeks 0.

-1 byte terima kasih kepada @JustinMariner

Bagaimana ini Bekerja?

Kami perhatikan bahwa ngrup ke -1 terindeks ( 1, 2, ... 2n ..., 2, 1) muncul dari elemen bernomor 0 2(n-1)^2hingga 2n^2.

Untuk menemukan elemen pada indeks x, kita dapat menemukan nomor grup nyang xada. Dari itu, kita menghitung jarak dari pusat grup itu x. (Jarak ini abs(2*n**2+2*n+2-x)).

Namun, karena elemen berkurang jauh dari pusat grup, kami mengurangi jarak dari nilai maksimum grup.


Saya telah bermain golf bagian ini: print 2*n-abs(2*n*n+2*n+1-x)+2- 2*n*n+2*nbisa 2*n*-~ndan +2+2*ndapat diubah menjadi -~n*2, yang memungkinkan kita untuk memindahkannya ke awal yang menghemat byte ( 53 byte )
Mr. Xcoder


2

JavaScript, 39 byte

f=(n,t=2)=>n>t?f(n-t,t+4):n>t/2?t-n+2:n

2

Jelly , 10 , 9 byte

ḤŒḄṖµ€Fị@

Cobalah online!

Juga 1 diindeks, dan selesai cukup cepat.

Satu byte disimpan berkat @ErikTheOutgolfer!

Penjelasan:

Secara hipotesis, katakanlah input ( a) adalah 3.

    µ€      # (Implicit) On each number in range(a):
            #
Ḥ           # Double
            #   [2, 4, 6]
            #
 ŒḄ         # Convert to a range, and Bounce
            #   [[1, 2, 1], [1, 2, 3, 4, 3, 2, 1], [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]]
            #
   Ṗ        # Pop
            #   [[1, 2], [1, 2, 3, 4, 3, 2], [1, 2, 3, 4, 5, 6, 5, 4, 3, 2]]
            #
     F      # Flatten
            #   [1, 2, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 5, 6, 5, 4, 3, 2]
            #
      ị@    # Grab the item[a]
            #   1
            #

Kode Anda setara dengan Ḥ€ŒḄ€Ṗ€Fị@, sehingga Anda dapat menggunakan µ€untuk -1 (tiga monad atau lebih dengan di awal):ḤŒḄṖµ€Fị@
Erik the Outgolfer

Ini harus benar-benar menjadi ḤŒḄṖ<newline> ½ĊÇ€Fị@untuk 12 untuk memenuhi persyaratan 10.000 (menjalankan kode 9 byte secara lokal membutuhkan sekitar 2:20 pada i7 saya dan menggunakan 7GB)
Jonathan Allan

1

MATL , 15 byte

li:"@EZv4L)]vG)

Berbasis 1.

Cobalah online!

Kali ini untuk kasus uji terbesar di TIO, tetapi selesai dalam waktu pada komputer desktop saya (kompiler berjalan pada MATLAB R2017a). Untuk menampilkan waktu yang telah berlalu, tambahkan Z`di akhir kode.

>> matl 'li:"@EZv4L)]vG)Z`'
> 10000
84
15.8235379852476

Penjelasan

Kode menghasilkan lebih banyak istilah daripada yang diperlukan. Secara khusus, itu menghitung n"potongan" dari urutan, di mana masing-masing bagian adalah hitungan ke atas dan kembali ke 1.

l       % Push 1
i       % Push input, n
:       % Range [1 2 ...n]
"       % For each k in that range
  @E    %   Push 2*k
  Zv    %   Symmetric range: [1 2 ... 2*k-1 2*k 2*k-1 ... 2 1]
  4L)   %   Remove last entry: [1 2 ... 2*k-1 2*k 2*k-1 ... 2]
]       % End
v       % Concatenate all stack contents into a column vector
G)      % Get n-th entry. Implicitly display

bagus! Kadang-kadang TIO lambat ...

1
Nah, penyebab utama kelambatan di sini adalah algoritma (yang menghasilkan lebih banyak istilah daripada yang diperlukan). Juga, kompiler MATL tidak terlalu cepat
Luis Mendo

1

Sekam , 12 10 byte

!ṁ§¤+hḣṫİ0

Cobalah online!

1-diindeks, bekerja cukup cepat

Penjelasan

!ṁ§¤+hḣṫİ0
 ṁ      İ0    Map the following function over the even numbers and concatenate the results together
  §   ḣṫ      Get the ranges 1-n and n-1, then... 
   ¤+h         remove the last element from both of them and concatenate them together
!             Return the element of the resulting list at the given index

8 byte menggunakan
Zgarb

@ Zgarb itu ide yang bagus dan Anda mungkin harus mempostingnya sebagai jawaban Anda :)
Leo



1

Retina , 62 byte

.+
$*
^((^.|\2..)*)\1.
6$*1$2$2;1
(?=.+;(.+))\1(.+).*;\2.*
$.2

Cobalah online! Tautan termasuk kasus uji. Input diindeks 1. Tahap pertama hanya konversi desimal ke unary. Tahap kedua menemukan angka kuadrat tertinggi hanya skurang dari setengahnya n; $1adalah , sementara $2ini 2s-1. Ini menghitung dua nilai, pertama jumlah angka dalam run up / down saat ini, yaitu 4(s+1) = 4s+4 = 2$2+6, dan kedua posisi dalam run itu, yaitu n-2s² = n-(2$1+1)+1 = n-$&+1, yang hanya membutuhkan 1make up untuk 1digunakan untuk menegakkan ketimpangan yang ketat. Tahap akhir kemudian dihitung dari posisi itu untuk awal dan akhir lari dan mengambil hasil yang lebih rendah dan mengubahnya menjadi desimal.



1

Perl 5 , 43 + 1 (-p) = 44 byte

$_=($n=2*int sqrt$_/2)+2-abs$n/2*$n+$n+1-$_

Cobalah online!

Saya sedang mengerjakan rumus untuk menghitung elemen ke-n secara langsung. Lalu saya melihat bahwa @ fireflame241 telah melakukan pekerjaan itu, dan saya memasukkannya ke Perl.

# Perl 5 , 50 + 1 (-n) = 51 byte

push@r,1..++$",reverse 2..++$"while@r<$_;say$r[$_]

Cobalah online!

Hasil diindeks 0.


1

Haskell , 115 81 byte

y%x=snd(span(<x)$scanl(+)y[y+1,y+3..])!!0
g 1=1
g x|1%x>2%x=1+g(x-1)|1>0=g(x-1)-1

Cobalah online!

Ada beberapa keajaiban yang terjadi di sini. Mungkin bisa lebih pendek jika saya menggunakan pendekatan normal.

Penjelasan

Pertama kita mendefinisikan %. %adalah fungsi yang mengambil dua variabel x, dan y. Itu membangun daftar scanl(+)y[y+1,y+3..]dan menemukan elemen pertama dari daftar itu lebih besar dari x. scanl(+)hanya melakukan jumlah berulang, untuk mendapatkan angka segitiga yang akan kita lakukan scanl(+)0[1..], untuk mendapatkan angka kuadrat yang akan kita lakukan scanl(+)0[1,3..]. Dua daftar khususnya yang akan kita buat adalah scanl(+)2[3,5..]dan scanl(+)1[2,4..]ini adalah titik belok dari pola.

Sekarang kita mendefinisikan fungsi utama gyang mengambil x. Jika xkita kembali 1karena itulah nilai pertama. Kalau tidak, kita periksa dua titik belok berikutnya, jika belok turun lebih besar 1%x>2xkita kembalikan penerusnya g$x-1kalau tidak kita kembalikan pendahulunya g$x-1.

Ok tapi mengapa itu berhasil?

Pertama-tama "Whats dengan cara kita menemukan simpul?". Penting untuk mencatat jarak antara simpul berurutan dari jenis yang sama. Anda akan melihat bahwa perbedaannya bertambah 2 setiap kali. Ini masuk akal karena basis segitiga menjadi lebih lebar 2 setiap kali. Kita dapat membuat daftar perbedaan konstan menggunakan daftar literal seperti itu [2,4..]dan kita gunakan scanl(+)untuk mengubah daftar ini menjadi daftar simpul kami, berdasarkan lokasi simpul pertama dan perbedaan pertama.

Jadi sekarang kita memiliki cara untuk menemukan simpul ke atas dan ke bawah kita dapat menggunakan informasi itu untuk mendapatkan nilai. Kita mengatakan bahwa nilai pertama adalah 1kalau tidak kita harus mengambil penerus atau pendahulunya. Jika simpul berikutnya adalah yang ke atas kita ingin mengambil pendahulunya, kalau tidak kita mengambil penerus.

Haskell , 56 51 46 byte

Inilah solusi saya yang lebih baik dengan lebih sedikit matematika dan lebih sedikit byte.

d x|e<-[1..x-1]=e++map(x+1-)e
(([1..]>>=d)!!0)

Cobalah online!


1

Pyke , 14 byte

SF}SDtO_+)sQt@

Coba di sini!

S              -    range(1, input)
 F}SDtO_+)     -   for i in ^:
  }            -      ^ * 2
   S           -     range(1, ^)
        +      -    ^ + v
     tO_       -     ^[1:-1:-1]
          s    -  sum(^)
           Qt@ - ^[input-1]

1

C # (.NET Core) , 120 byte

Penjelasan: cukup sederhana, loop bersarang pertama naik ke maks kami, yang kedua naik kembali ke 2. Pengulangan untuk setiap kelipatan 2.

x=>{var a=0;for(int i=2,j=0;j<x;i+=2){for(var b=1;b<=i&j<x;b++,j++){a=b;}for(var c=i-1;c>1&j<x;c--,j++){a=c;}}return a;}

Cobalah online!


1

Ruby , 78 75 byte

Disimpan 1 byte berkat Langkah Hen

Disimpan 1 byte berkat Tn. Xcoder

->n{a=0;b=2;c=1;n.times{if a==b then c=0;b+=2;end;c=1if a<2;a+=c<1?-1:1};a}

Cobalah online!

Semoga saya bisa mendapatkan beberapa tips untuk menarik bytecount lebih banyak. Saya mencoba mengambil pendekatan sederhana.


Selamat datang di PPCG! c=1 ifdapat bermain golf untukc=1if
Stephen

76 byte:->n{a=0;b=2;c=1;n.times{if a==b then c=0;b+=2;end;c=1if a==1;a+=c<1?-1:1};a}
Mr. Xcoder

1

Java (OpenJDK 8) , 53 byte

n->{int i=2;for(;n>i;i+=4)n-=i;return n>i/2?i-n+2:n;}

Cobalah online!

-2 byte terima kasih kepada Nevay.

1-diindeks.

TL; DR Kami membagi urutan menjadi potongan-potongan yang mudah, menemukan potongan ndalam, kemudian menemukan nthposisi dalam potongan.

Di sini, kita dapat membagi urutan seperti [[1,2],[1,2,3,4,3,2],[1,2,3,4,5,6,5,4,3,2],...], yang memberi kita ukuran potongan 4i-2. Dimulai dengan i=2, kita kurangi idari n, pada dasarnya bergerak ke atas sepotong pada suatu waktu. Setelah kami puas n<=i, kami tahu nsekarang posisi nilai yang benar di chunk saat ini.

Kami kemudian mendapatkan nilai dengan membandingkan nuntuk i, ukuran chunk tersebut. Titik tengah setiap potongan sama dengan i/2+1; jika nkurang dari ini, kami cukup kembali n. Jika nlebih besar, kami kembali i-n+2.

Contoh

n = 16, i = 2

Is n > i? Yes, n = n - 2 = 14, i = i + 4 = 6
Is n > i? Yes, n = n - 6 = 8, i = i + 4 = 10
Is n > i? No, stop looping.
10 / 2 + 1 = 6
Is n > 6? Yes, return i - n + 2 = 8 - 6 + 2 = 4

Anda tidak perlu +1, return n>i/2?i-n+2:nsudah cukup.
Nevay

Hah. Terima kasih, pembagian integer.
Xanderhall

1

Python 2 , 5! byte (120 byte: P)

r=range
a=[]
for i in r(2,998,2): 
	for j in r(1,i+1): a.append(j)
	for j in r(i-1,1,-1): a.append(j)
print a[input()-1]

Cobalah online!

Langsung saja, buat daftar lalu ambil elemen input'th


Terima kasih, siapapun yang memilih! Sekarang saya punya 50 perwakilan sehingga saya bisa berkomentar! oleskan intens
Husnain Raza

0

Python 3 , 184 156 byte

l,n,r=list,next,range
h=lambda x:l(r(1,x))+l(r(x-2,1,-1))
def g():
	x=3
	while True:yield from h(x);x+=2
def f(i):
	x=g()
	for _ in r(i-1):n(x)
	return n(x)

Cobalah online!

golf dengan generator Python untuk evaluasi "malas"


0

QBIC , 47 byte

g=q{p=p+1~p=:|_Xg\g=g+q~g=1or g>=r|r=r+1┘q=q*-1

Penjelasan

g=q         var g is the current value of the sequence; set to 1 at the start
{           DO infinitely
p=p+1       raise the step counter (var p)
~p=:|_Xg    IF p equals the input term a (read from cmd line) THEN QUIT, printing g
\           ELSE
g=g+q       raise (or decrement) g by q (q is 1 at the start of QBIC)
~g=1        IF g is at the lower bound of a subsequence
    or g>=r OR g is at the upper bound (r start as 2 in QBIC)
|r=r+1      THEN increment r (this happens once on lower bound, and once on upper, 
            total of 2 raise per subsequence)
┘q=q*-1     and switch q from 1 to -1

0

Röda , 54 byte

f n{seq 1,n|{|i|seq 1,2*i;seq 2*i-1,2}_|head n+2|tail}

Cobalah online!

Telepon dengan: try f(n)

Fungsi ini mengembalikan jawaban dengan cepat, tetapi setelah itu melakukan beberapa perhitungan yang tidak perlu dan akhirnya kehabisan memori.

Karena fungsi mengembalikan jawaban aktual sesaat setelah dipanggil (jelas di bawah satu menit), saya pikir jawaban ini valid.

(Dalam fungsi Röda dapat mengembalikan nilai sebelum keluar karena paralelisme.)


0

C # (.NET Core) , 99 95 86 byte

n=>{int i=1,t=2,d=0;for(;n>1;){i+=1-2*d;if(i==t){d++;t+=2;}if(i==1)d--;n--;}return i;}

Cobalah online!

Fungsi Lambda yang mengambil dan mengembalikan integer. Satu loop yang menangani menghitung naik dan turun.


0

PHP, 65 +1 byte

for($x=$d=$z=1;--$argn;)$d=($x+=$d)>1?$x>$z?-1:$d:!!$z+=2;echo$x;

Jalankan sebagai pipa dengan -Ratau coba online (atau batalkan komentar salah satu versi lain).

Port JavaScript rekursif tsh membutuhkan waktu 66 byte:

function f($n,$t=2){return$t<2*$n?$t<$n?f($n-$t,$t+4):$t-$n+2:$n;}

Port solusi Arnauld membutuhkan 62 + 1:

$n=$argn;echo($n-=($r=(~-$n/2)**.5|0)*$r*2)<++$r*2?$n:$r*4-$n;

Port golf dari Xanderhall's Java memiliki kode terpendek sejauh ini (55 + 1 byte):

for($n=$argn;$n+2>$i+=4;)$n-=$i-2;echo$n*2>$i?$i-$n:$n;

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.