Hasilkan himpunan permutasi prepend-append dalam urutan yang diurutkan secara leksikografis

14

Tentukan urutan panjang prepend-appendn untuk menjadi permutasi dari angka 1, 2, ..., nyang dapat dihasilkan oleh prosedur berikut:

  • Mulai dengan nomornya 1.

  • Untuk setiap angka dari 2hingga n, tempatkan nomor ini ke awal atau akhir urutan (baik tambahkan atau tambahkan , maka nama urutan).

Misalnya, ini adalah cara yang valid untuk menghasilkan urutan panjang tambahan 4 yang ditambahkan:

1
21     [beginning]
213    [end]
2134   [end]

Tugas Anda adalah untuk membangun program atau fungsi yang akan mengambil angka ndari 3menjadi 30sebagai input, dan mencetak atau mengembalikan semua urutan panjang tambahan yang ditambahkan dalam urutan nleksikografis (jika Anda mengeluarkan string dan bukan daftar, angka di atas 9 akan diwakili sebagai huruf a-u, untuk menjaga panjang string). Misalnya, ini adalah pesanan untuk n = 4:

1234  [RRR]
2134  [LRR]
3124  [RLR]
3214  [LLR]
4123  [RRL]
4213  [LRL]
4312  [RLL]
4321  [LLL]

Secara umum, ada 2 n-1 permutasi penambahan-append panjang n.

Anda tidak boleh menggunakan fungsi penyortiran bawaan dalam bahasa Anda dalam kode Anda. Program terpendek untuk melakukan ini dalam bahasa apa pun menang.

Joe Z.
sumber
Saya bukan penggemar persyaratan format output, khususnya konversi ke huruf a-u. Bisakah kita hanya menampilkan daftar angka?
xnor
3
Anda mungkin ingin menerima jawaban setelah beberapa waktu karena beberapa orang cenderung tidak menjawab pertanyaan jika jawaban itu sudah diterima.
Pengoptimal
1
Jadi Anda salah menerima jawaban ..
Pengoptimal
2
FryAmTheEggman memposting jawabannya 21 menit sebelum Anda mengedit jawaban Anda.
Joe Z.
2
@ Pengoptimal Saya tidak berpikir itu cara yang paling aneh - Jawaban FryAmTheEggman adalah 19 byte, panjang 21 menit sebelum milik Anda. Itu membuatnya menjadi jawaban terpendek yang diposting paling awal.
Joe Z.

Jawaban:

10

CJam, 22 20 19 17 byte

]]l~{)f+_1fm>|}/p

Perluasan kode :

]]                   "Put [[]] onto stack. What we will do with this array of array is";
                     "that in each iteration below, we will first append the next";
                     "number to all present arrays, then copy all the arrays and";
                     "move the last element to first in the copy";
  l~                 "Read input number. Lets call it N";
    {         }/     "Run this code block N times ranging from 0 to N - 1";
     )f+             "Since the number on stack starts from 0, add 1 to it and append";
                     "it to all arrays in the array of array beginning with [[]]";
        _1fm>        "Copy the array of array and move last element from all arrays";
                     "to their beginning";
             |       "Take set union of the two arrays, thus joining them and eliminating";
                     "duplicates. Since we started with and empty array and started adding";
                     "numbers from 1 instead of 2, [1] would have appeared twice if we had";
                     "simply done a concat";
                p    "Print the array of arrays";

Cara kerjanya :

Ini adalah versi kode debug:

]]l~ed{)edf+ed_ed1fm>ed|ed}/edp

Mari kita lihat cara kerjanya untuk input 3:

[[[]] 3]                                 "]]l~"            "Empty array of array and input";
[[[]] 1]                                 "{)"              "First iteration, increment 0";
[[[1]]]                                  "{)f+"            "Append it to all sub arrays";
[[[1]] [[1]]]                            "{)f+_"           "Copy the final array of array";
[[[1]] [[1]]]                            "{)f+_1fm>"       "shift last element of each";
                                                           "sub array to the beginning";
[[[1]]]                                  "{)f+_1fm>|}"     "Take set based union";
[[[1]] 2]                                "{)"              "2nd iteration. Repeat";
[[[1 2]]]                                "{)f+"
[[[1 2]] [[1 2]]]                        "{)f+_";
[[[1 2]] [[2 1]]]                        "{)f+_1fm>";
[[[1 2] [2 1]]]                          "{)f+_1fm>|}";
[[[1 2] [2 1]] 3]                        "{)";
[[[1 2 3] [2 1 3]]]                      "{)f+"
[[[1 2 3] [2 1 3]] [[1 2 3] [2 1 3]]]    "{)f+_";
[[[1 2 3] [2 1 3]] [[3 1 2] [3 2 1]]]    "{)f+_1fm>";
[[[1 2 3] [2 1 3] [3 1 2] [3 2 1]]]      "{)f+_1fm>|}";
[[[1 2 3] [2 1 3] [3 1 2] [3 2 1]]]      "{)f+_1fm>|}/";

Cobalah online di sini

Pengoptimal
sumber
6

Haskell, 47 byte

f 1=[[1]]
f n=(\x->map(++[n])x++map(n:)x)$f$n-1
alephalpha
sumber
1
Beralih ke daftar pemahaman menghemat beberapa byte: f n=[[n:x,x++[n]]|x<-f$n-1]>>=id(menggunakan fungsi concat kode-pegolf >>=id).
nimi
1
@nimi tapi itu salah urutan
bangga haskeller
@proudhaskeller: Ya ampun, tidak membaca spec cukup hati-hati. Saya mencoba untuk memperbaikinya dan menemukan empat cara yang sedikit berbeda dengan panjang yang sama dengan versi @ alephalpha, jadi saya tidak dapat menawarkan peningkatan. f n=[x++[n]|x<-f$n-1]++[n:x|x<-f$n-1], f n=map(++[n])(f$n-1)++[n:x|x<-f$n-1], f n=map(++[n])(f$n-1)++map(n:)(f$n-1),f n=(++[n])#n++(n:)#n;p#i=map p$f$i-1
Nimi
5

Python 2, 68

f=lambda n:[[1]]*(n<2)or[x*b+[n]+x*-b for b in[1,-1]for x in f(n-1)]

Menghasilkan daftar daftar angka.

Solusi rekursif. Untuk n==1, keluaran [[1]]. Jika tidak, tambahkan nke awal atau akhir semua (n-1)-permutasi. Prepending membuat permutasi lebih lambat dari penambahan, sehingga permutasi tetap diurutkan.

"Boolean" bmengkodekan apakah akan meletakkan [n]pada awal atau akhir. Sebenarnya, kami memindahkan sisa daftar xdalam ekspresi x*b+[n]+x*-b. Dimasukkan bsebagai -1atau 1mari kita gunakan flip dengan meniadakan, karena daftar dikalikan dengan -1adalah daftar kosong.

Tidak
sumber
4

Pyth, 19

usCm,+dH+HdGr2hQ]]1

Cobalah online di sini

Ini adalah program lengkap yang mengambil input dari stdin.

Ini bekerja dengan cara yang mirip dengan solusi xnor, tetapi menghasilkan nilai-nilai yang sedikit rusak, sehingga harus disusun ulang. Apa yang terjadi di setiap tingkat adalah bahwa setiap daftar nilai sebelumnya memiliki nilai baru yang ditambahkan ke akhir dan ke awal dan ini masing-masing dibungkus dalam 2-tuple yang dibungkus bersama dalam daftar. Misalnya, langkah pertama melakukan ini:

[[1]]
[([1,2], [2,1])]

Kemudian, daftar tupel ini di-zip (dan kemudian dijumlahkan untuk menghapus daftar terluar). Dalam kasus pertama ini hanya memberikan nilai yang terbuka dari atas, karena hanya ada satu nilai dalam daftar.

Langkah-langkah menampilkan 2-> 3:

([1,2], [2,1])
[([1,2,3],[3,1,2]),([2,1,3],[3,2,1])]
([1,2,3],[2,1,3],[3,1,2],[3,2,1])
FryAmTheEggman
sumber
2

Mathematica, 57 54 49 byte

f@1={{1}};f@n_:=#@n/@f[n-1]&/@Append~Join~Prepend

Contoh:

f[4]

{{1, 2, 3, 4}, {2, 1, 3, 4}, {3, 1, 2, 4}, {3, 2, 1, 4}, {4, 1, 2, 3} , {4, 2, 1, 3}, {4, 3, 1, 2}, {4, 3, 2, 1}}

alephalpha
sumber
2

J, 26 byte

   0|:<:((,,.,~)1+#)@[&0,.@1:

   (0|:<:((,,.,~)1+#)@[&0,.@1:) 3
1 2 3
2 1 3
3 1 2
3 2 1

Peningkatan 1 byte berkat FUZxxl .

randomra
sumber
Pengganti ,.untuk ,"1satu karakter.
FUZxxl
1

Pyth, 34 33 31 29

Pada dasarnya terjemahan dari xnor 's Python jawaban . Saya masih tidak hebat dengan Pyth, jadi saran perbaikan dipersilahkan.

Menentukan fungsi yuntuk mengembalikan daftar daftar bilangan bulat.

L?]]1<b2smm++*kdb*k_dy-b1,1_1

Pembaruan: Disimpan 2 byte berkat FryAmTheEggman .

Penjelasan:

L                                  define a function y with argument b that returns
 ?*]]1<b2                          [[1]] if b < 2 else
         s                         sum(
          m                        map(lambda d:
           m                       map(lambda k:
            ++*kdb*k_d             k*d + [b] + k*-d
                      y-b1         , y(b - 1))
                          ,1_1)    , (1, -1))
PurkkaKoodari
sumber
Beberapa hal penting: -b1bisa tb, [1_1)bisa ,1_1(namun Anda bisa saja menjatuhkan braket tutup karena Anda hanya perlu menghitung byte yang diperlukan untuk membuat fungsi, meskipun Anda tidak akan dapat memanggilnya tanpa menutupnya), dan Anda tidak perlu membungkus bdaftar karena pyth secara otomatis mengkonversi ke daftar saat menambahkan daftar ke int.
FryAmTheEggman
Saya datang dengan cara untuk menghemat beberapa byte dengan secara manual melakukan peta kedua [1,-1]. Saya dapat menyimpan byte ke hardcode sesuatu yang pendek, terutama ketika Anda menyederhanakan logika. Saya mendapatkanL?]]1<b2sCm,+db+bdytb
FryAmTheEggman
@FryAmTheEggman Anda mungkin sebenarnya ingin menambahkan itu sebagai jawaban Anda sendiri. Itu luar biasa.
PurkkaKoodari
OK, saya ingin mencoba untuk mengalahkan CJam sebelum memposting tetapi saya kira trik zipnya cukup menarik sehingga pantas diposkan. Semoga beruntung dengan Pyth;)
FryAmTheEggman
1

Pure Bash, 103

Lebih lama dari yang saya harapkan:

a=1..1
for i in {2..9} {a..u};{
((++c<$1))||break
a={${a// /,}}
a=`eval echo $a$i $i$a`
}
echo ${a%%.*}
Trauma Digital
sumber
1

JavaScript (ES6) 73 80

Implementasi JavaScript dari solusi bagus @ Optimizer.

Rekursif (73):

R=(n,i=1,r=[[1]])=>++i>n?r:r.map(e=>r.push([i,...e])+e.push(i))&&R(n,i,r)

Iteratif (74):

F=n=>(i=>{for(r=[[1]];++i<=n;)r.map(e=>r.push([i,...e])+e.push(i))})(1)||r

Uji di Firefox / konsol FireBug

R(4)

[[1, 2, 3, 4], [2, 1, 3, 4], [3, 1, 2, 4], [3, 2, 1, 4], [4, 1, 2, 3] , [4, 2, 1, 3], [4, 3, 1, 2], [4, 3, 2, 1]]

edc65
sumber
0

Solusi Java saya:

public static void main(String[] args) {
    listPrependAppend(4);
}

private static void listPrependAppend(int n) {
    int total = (int) Math.pow(2, n - 1);
    int ps;
    boolean append;
    String sequence;
    String pattern;

    for (int num = 0; num < total; num++) {
        sequence = "";
        pattern = "";
        append = false;
        ps = num;
        for (int pos = 1; pos < n + 1; pos++) {
            sequence = append ? (pos + sequence) : (sequence + pos);
            append = (ps & 0x01) == 0x01;
            ps = ps >> 1;
            if (pos < n) {
                pattern += append ? "L" : "R";
            }
        }
        System.out.format("%s\t[%s]%n", sequence, pattern);
    }
}
Brett Ryan
sumber
Oh sial, sekarang setelah melihat jawaban lain saya melihat apa yang Anda maksudkan tentang jawaban terpendek.
Brett Ryan
2
Meskipun solusi Anda terhormat, singkat, dan disajikan dengan baik, Anda benar bahwa itu bukan kandidat yang tepat untuk masalah yang dihadapi.
Joe Z.
1
@ BrettRyan Anda dapat membuat kode Anda lebih pendek dengan menghapus spasi yang tidak perlu dan menggunakan nama variabel satu-char. Anda juga dapat menggantinya falsedengan sesuatu seperti 5<4.
ProgramFOX
1
Terima kasih kawan Itu adalah upaya pertama saya untuk berpartisipasi dalam tantangan kode. Saya hanya mencari beberapa tantangan pemrograman dan tidak menyadari targetnya adalah untuk mendapatkan solusi terpendek. :) Terima kasih telah mengizinkan saya berpartisipasi.
Brett Ryan