Buat satu urutan

12

Urutan bilangan bulat adalah urutan satu jika perbedaan antara dua angka berurutan dalam urutan ini adalah -1 atau 1 dan elemen pertamanya adalah 0.

Lebih tepatnya: a1, a2, ..., an adalah satu urutan jika:

For any k (1 ≤  k < n): |a[k] - a[k+1]|=1, 
a[1]=0

Memasukkan

  • n - jumlah elemen dalam urutan
  • s - jumlah elemen dalam urutan

Keluaran

  • satu set urutan / daftar / array / etc panjang ndengan jumlah elemen s, jika memungkinkan
  • set / list / array / etc kosong jika tidak memungkinkan

Contohnya

Untuk input 8 4, output bisa [0 1 2 1 0 -1 0 1]atau [0 -1 0 1 0 1 2 1]. Mungkin ada kemungkinan lain.

Untuk input 3 5, output kosong [], karena tidak dapat dilakukan.

Aturan

Ini adalah kode golf, jawaban terpendek dalam byte yang menang. Pengajuan harus berupa program atau fungsi. Input / output dapat diberikan dengan salah satu cara standar .

mengetik
sumber
Ngomong-ngomong, saya punya bukti bahwa semua bilangan terwakili sebagai satu urutan panjang l adalah semua bilangan di antara (l-1)*l/2dan -(l-1)*l/2yang memiliki paritas yang sama dengan (l-1)*l/2.
haskeller bangga
ini dapat digunakan untuk membuat algoritma yang efisien (O (n)) untuk membuat satu urutan yang diinginkan
bangga haskeller

Jawaban:

7

CJam, 56 47 44 34 byte

Banyak ruang untuk perbaikan di sini, tetapi inilah upaya pertama untuk ini:

L0aa{{[~_(]_)2++}%}l~:N;(*{:+N=}=p

Penghargaan kepada Dennis untuk cara yang efisien dalam melakukan { ... }%bagian itu.

Mencetak representasi array jika memungkinkan, jika tidak ""

Cobalah online di sini

Pengoptimal
sumber
Saya bingung: Bagian {}%dari kode Anda tidak seperti milik saya (yang hanya kode @ PeterTaylor, mengganti titik-titik dengan garis bawah). Jika saya menyumbangkan sesuatu untuk kode Anda, itu {}=operator ...
Dennis
Saya awalnya punya _{_W=)+}%\{_W=(+}%+yang pertama membuat dua salinan, tambahkan 1 ke yang pertama, kurangi 1 dari yang lain. Contoh Anda membuat saya mencari cara melakukannya dalam satu { ... }%blok. Mengenai itu { ... }=, saya sudah mengurangi sebanyak itu dalam eksperimen saya, meskipun belum diposting.
Pengoptimal
Saya mengerti dari pertanyaan bahwa input yang diberikan 3 5output seharusnya []dan tidak""
Peter Taylor
1
@PeterTaylor "set / list / array / etc kosong jika tidak memungkinkan" - Jadi saya pikir saya harus membuatnya jelas ...
Pengoptimal
Plus, []pdi CJam hanya keluaran ke "". Jadi begitulah bahasa mewakili array kosong.
Pengoptimal
6

JavaScript (E6) 79 82

F=(n,t,
  d=n+n*~-n/4-t/2,
  l=1,
  q=[for(x of Array(n))d<n--?++l:(d+=~n,--l)]
)=>d?[]:q

Tidak perlu kekerasan atau enumerasi semua tuple.

Lihat urutan panjang n sebagai n -1 langkah, setiap langkah menjadi kenaikan atau penurunan.
Catatan, Anda hanya bisa menukar kenaikan dengan penurunan, jumlah bervariasi 2, sehingga untuk panjang tertentu jumlahnya selalu genap atau selalu ganjil.
Setelah semua kenaikan, urutannya adalah 0, 1, 2, 3, ..., n-1 dan kita tahu jumlahnya adalah (n-1) * n / 2
Mengubah langkah terakhir, jumlah berubah 2, sehingga langkah terakhir berbobot 2.
Mengubah langkah berikutnya ke langkah terakhir, jumlah berubah dengan 4, jadi langkah terakhir berbobot 4. Itu karena langkah berturut-turut dibangun berdasarkan jumlah parsial sejauh ini.
Mengubah langkah sebelumnya, jumlah berubah dengan 6, jadi langkah terakhir beratnya 6 (bukan 8, itu bukan angka biner).
...
Mengubah langkah pertama berbobot (n-1) * 2

Algoritma

Find the max sum (all increments)  
Find the difference with the target sum (if it's not even, no solution)  
Seq[0] is 0  
For each step  
  Compare current difference with the step weight
  if is less 
     we have an increment here, seq[i] = seq[i-1]+1 
  else 
     we have a decrement here, seq[i] = seq[i-1]-1.  
     Subtract we current weight from the current diff.
If remaining diff == 0, solution is Seq[]. Else no solution

Kode tidak dikunci

F=(len,target)=>{
  max=(len-1)*len/2
  delta = max-target
  seq = [last=0]
  sum = 0
  weight=(len-1)*2
  while (--len > 0)
  {
    if (delta >= weight)
    {
      --last
      delta -= weight;
    }
    else
    {
      ++last
    }  
    sum += last
    seq.push(last);
    weight -= 2;
  }  
  if (delta) return [];
  console.log(sum) // to verify

  return seq
}

Uji di Firefox / konsol FireBug

F(8,4)

Keluaran

[0, -1, 0, -1, 0, 1, 2, 3]
edc65
sumber
5

GolfScript ( 41 39 byte)

[][1,]@~:^;({{.-1=(+.)))+}%}*{{+}*^=}?`

Demo online

Terima kasih kepada Dennis untuk 41-> 39.

Peter Taylor
sumber
Anda dapat mempersingkat ,0=menjadi ?. Port langsung ke CJam akan menjadi 5 byte lebih pendek:L1,al~:S;({{_W=(+_)))+}%}*{:+S=}=p
Dennis
@ Dennis oooh, itu cara mudah untuk mendapatkan dua blok {}%. Keberatan jika saya menggunakannya?
Pengoptimal
@ Pengoptimal: Saya tidak, tapi itu bukan pekerjaan saya.
Dennis
Saya sedang berbicara tentang { ... }%blok. Dalam kode saya, saya punya dua, mencoba menguranginya menjadi 1. Seperti halnya algoritma nyata, saya pikir Peter dan saya memposting algoritma yang sama hampir pada waktu yang sama.
Pengoptimal
3

Mathematica, 73 byte

f=FirstCase[{0}~Join~Accumulate@#&/@Tuples[{-1,1},#-1],l_/;Tr@l==#2,{}]&;

Solusi brute force sederhana.

Saya menghasilkan semua pilihan langkah. Lalu saya mengubahnya menjadi daftar terakumulasi untuk mendapatkan urutan satu. Dan kemudian saya mencari yang pertama yang jumlahnya sama dengan parameter kedua. Jika tidak ada, nilai standarnya adalah {}.

Martin Ender
sumber
Mathematica hanya menyinari matematika / kombinasi masalah terkait, bukan? ;)
Pengoptimal
@Optimizer Saya yakin CJam akan mengalahkannya. ;) Sebenarnya algoritma yang sama ini seharusnya tidak sulit dilakukan di CJam.
Martin Ender
1
Ini pasti akan mengalahkannya, tetapi hanya karena nama metode pendek. Algoritma tidak akan lurus ke depan.
Pengoptimal
@Optimizer, ya? Saya pikir ini lebih mudah dengan loop dan filter sederhana daripada komposisi fungsi ini.
Peter Taylor
3

Haskell, 56 byte

n%s=[x|x<-scanl(+)0`map`mapM(\_->[1,-1])[2..n],s==sum x]

Penjelasan:

  • Buat daftar dengan permutasi 1,-1dan panjang n-1: replicateM n-1[-1,1]
    Contoh: replicateM 2 [-1,1]==[[-1,-1],[-1,1],[1,-1],[1,1]]
  • Bangun satu-urutan dari itu. scanlmemiliki kinerja yang buruk, tetapi melakukan pekerjaan yang benar di sini.
  • Saring semua kemungkinan satu-urutan dengan panjang di nmana jumlahnyas
Johannes Kuhn
sumber
1
perbaikan sederhana adalah mengubah fungsi infix. inilah petunjuk untuk peningkatan yang lebih tidak intuitif: mengimpor Control.Monadhanya untuk menggunakan replicateMyang sudah terlalu lama. apa fungsi monadik lain yang dapat Anda gunakan untuk mensimulasikan replicateM?
haskeller bangga
omong-omong, Anda harus mengembalikan hanya satu solusi, jadi Anda harus menambahkan head$ke solusi Anda.
haskeller bangga
headtidak kembali []untuk [] :: [[a]]- dan saya benci kesalahan.
Johannes Kuhn
1
karena beberapa waktu telah berlalu, saya akan memberi tahu Anda apa yang saya maksud. Anda bisa menggunakan mapM(\x->[1,-1])[2..n]alih-alih sequencedan replicate.
haskeller bangga
Menarik. Itu bahkan lebih pendek: P
Johannes Kuhn
2

Python, 138

from itertools import*
def f(n,s):
 for i in[list(accumulate(x))for x in product([-1,1],repeat=n-1)]:
  if sum(i)==s:return[0]+i
 return[]
monopole
sumber
0

CJam, 65 58 54 byte

Nyaris lebih pendek dari solusi Mathematica saya, tapi itu sebagian besar kesalahan saya karena masih tidak menggunakan CJam dengan benar:

0]]l~:S;({{_1+\W+}%}*{0\{+_}%);}%_{:+S=}#_@\i=\0>\[]?p

Secara harfiah algoritma yang sama: dapatkan semua n-1-dari {1, -1}. Temukan yang pertama yang akumulasinya sama dengan s, prepend a 0. Cetak array kosong jika tidak ada yang ditemukan.

Martin Ender
sumber
0

CJam, 40

Pendekatan lain dalam CJam.

ri,W%)\_:+ri-\{2*:T1$>1{T-W}?2$+\}/])!*p
jimmy23013
sumber
0

Ruby (136)

def one_sequences(n)
  n.to_s.chars.map(&:to_i).each_cons(2).to_a.select{|x|x[0] == 0 && (x[1] == 1 || x[1]
  == -1)}.count
end
Johnson
sumber
0

J, 47 karakter

Periksa setiap urutan seperti banyak jawaban lainnya. Akan mencoba membuat solusi O (n) yang lebih pendek.

   f=.4 :'(<:@#}.])(|:#~y=+/)+/\0,|:<:2*#:i.2^<:x'

   8 f 4
0 1 2 1 0 1 0 _1

   3 f 5
[nothing]
randomra
sumber
0

APL 38

{⊃(↓a⌿⍨⍺=+/a←+\0,⍉1↓¯1*(⍵⍴2)⊤⍳2*⍵),⊂⍬}

Contoh:

     4 {⊃(↓a⌿⍨⍺=+/a←+\0,⍉1↓¯1*(⍵⍴2)⊤⍳2*⍵),⊂⍬}8
0 1 2 1 0 1 0 ¯1

Yang ini seperti yang lainnya hanya memaksa dengan kasar melalui setiap kombinasi untuk menemukan yang cocok, jika tidak ditemukan tidak menghasilkan apa-apa. Sebenarnya ia mencoba beberapa kombinasi lebih dari satu kali untuk membuat kode lebih pendek.

Moris Zucca
sumber