Urutan Ajaib dari panjang n

11

Urutan ajaib adalah urutan bilangan bulat non-negatif x[0..n-1]sehingga ada beberapa x[i]contohi

Misalnya, 6,2,1,0,0,0,0,0,0,0,0 adalah urutan ajaib karena ada 6 0, 2 1, dan seterusnya.

Tulis fungsi yang bila diberikan n, menampilkan semua urutan ajaib panjang n


Program yang dapat menghasilkan output yang benar untuk nilai n tertinggi dalam 10 detik menang. (Namun, semua program dipersilahkan)

Misalnya, program Alice dapat menangani hingga n = 15 dalam 10 detik sementara Bob dapat menangani hingga n = 20 dalam waktu yang sama. Bob menang.

Platform: Linux 2.7GHz @ 4 CPU

Agnishom Chattopadhyay
sumber
5
Selamat datang di PPCG! Ini adalah tantangan besar, tetapi Anda membutuhkan kriteria kemenangan. Misalnya, Anda dapat mengatakan bahwa pemenangnya adalah program terpendek.
Ypnypn
1
Relevan: Nomor deskriptif-sendiri
Sp3000
2
Tolong jangan mengubah kriteria kemenangan setelah jawaban telah diposting. Juga, ini jauh lebih baik sebagai kode golf daripada kode tercepat, setidaknya menurut saya.
Alex A.
2
@ xnor Anda bisa mulai dengan membuat partisi integer dari n dan memeriksa apakah mereka bisa deskriptif sendiri.
Martin Ender
2
Apa yang terkecil n>5dengan solusi bukan dari bentuknya [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]? Saya sudah mencari n=20dan tidak menemukan satu, dan bertanya-tanya apakah saya membuat kesalahan.
xnor

Jawaban:

19

Python, n≈10 8

def magic_sequences(n):
    if n==4:
        return (1, 2, 1, 0),(2, 0, 2, 0) 
    elif n==5:
        return (2, 1, 2, 0, 0),
    elif n>=7:
        return (n-4,2,1)+(0,)*(n-7)+(1,0,0,0),
    else:
        return ()

Ini menggunakan fakta, yang akan saya buktikan, bahwa satu-satunya urutan panjang Sihir nadalah:

  • [1, 2, 1, 0]dan [2, 0, 2, 0]untukn=4
  • [2, 1, 2, 0, 0] untuk n=5
  • [n-4, 2, 1, 0, 0, ..., 0, 0, 1, 0, 0, 0] untuk n>=7

Jadi, untuk n>=7, seseorang hanya perlu mengembalikan tuple besar. Saya dapat melakukan ini hingga kira-kira n=10^8di laptop saya, yang kemungkinan dibatasi oleh memori; lagi dan membeku. (Berkat trichoplax untuk gagasan menggunakan tuple daripada daftar.) Atau, jika seseorang dapat mencetak kamus entri bukan nol {0:n-4, 1:2, 2:1, (n-4):1},, seseorang dapat melakukan ini untuk ginormous n.

Saya membuktikan keunikan untuk n>=7; yang lain dapat diperiksa dengan brute force atau casework.

Jumlah entri ladalah jumlah total semua angka dalam daftar, yang panjangnya n. Daftar ini memiliki l[0]nol, dan n-l[0]bukan nol entri. Tetapi menurut definisi l[0]harus bukan nol atau kita mendapatkan kontradiksi, dan masing-masing entri bukan nol lainnya setidaknya 1. Ini sudah merupakan jumlah dari l[0] + (n-l[0]-1)*1 = n-1jumlah keseluruhan n. Jadi tidak menghitung l[0], paling tidak ada satu 2 dan tidak ada entri lebih besar dari 2.

Tapi itu berarti satu-satunya entri bukan nol l[0], l[1], l[2], and l[l[0]], yang nilainya paling banyak l[0]dan permutasi 1,1,2, yang memberikan jumlah maksimum l[0]+4. Karena jumlah ini adalah n, yang setidaknya 7, kita miliki l[0]>=3, dan seterusnya l[l[0]]=1. Sekarang, setidaknya ada satu 1, yang artinya l[1]>=1, tetapi jika l[1]==1itu yang lain 1, maka l[1]>=2, yang menyiratkan l[1]adalah satu-satunya 2. Ini memberi l[2]=1, dan semua entri yang tersisa 0, jadi l[0]=n-4, yang menyelesaikan solusi.

Tidak
sumber
Dan bahasanya adalah ...?
edc65
@ edc65 Sepertinya python. Tapi saya tidak yakin.
Ismael Miguel
4

Python 3, n≈40

def plausible_suffix(l,N):
    if sum(l)>N:
        return False

    pairs = [(N-1-i,l[i]) for i in range(len(l))]

    if sum(i*x for i,x in pairs)>N:
        return False

    num_remaining = N - len(l)

    for index, desired_count in pairs:
        count = l.count(index)
        more_needed = desired_count - count
        if more_needed<0: 
            return False
        num_remaining -= more_needed
        if num_remaining<0:
            return False
    return True

plausible_func = plausible_suffix

def generate_magic(N):
    l=[0]
    while l:
        extend = False
        if plausible_func(l,N):
            if len(l)==N:
                yield l[::-1]
            else:
                extend = True
        if extend:
            l.append(0)
        else:
            while l[-1]>=N-2:
                l.pop(-1)
                if not l:raise StopIteration
            l[-1]+=1

n=40 #test parameter

if n>0:
    for x in generate_magic(n):
        print(n,x)

Lakukan pencarian pertama dari daftar yang mungkin, mengisi entri dari kanan ke kiri, menghentikan pencarian pada akhiran jika tidak masuk akal, yang dapat terjadi jika:

  • Jumlah entri dalam sufiks melebihi n(jumlah untuk seluruh daftar harus n)
  • Jumlah tertimbang i*l[i]dalam sufiks melebihi n(jumlah untuk seluruh daftar harus n)
  • Angka apa pun muncul di akhiran lebih dari yang sufiks katakan seharusnya
  • Jumlah tempat yang belum terisi yang tersisa terlalu kecil untuk memperhitungkan semua angka yang perlu lebih sering muncul.

Saya memiliki awalan yang diuji asli dari kiri ke kanan, tetapi itu berjalan lebih lambat.

Output hingga n=30adalah:

4 [1, 2, 1, 0]
4 [2, 0, 2, 0]
5 [2, 1, 2, 0, 0]
7 [3, 2, 1, 1, 0, 0, 0]
8 [4, 2, 1, 0, 1, 0, 0, 0]
9 [5, 2, 1, 0, 0, 1, 0, 0, 0]
10 [6, 2, 1, 0, 0, 0, 1, 0, 0, 0]
11 [7, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0]
12 [8, 2, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0]
13 [9, 2, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
14 [10, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
15 [11, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
16 [12, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
17 [13, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
18 [14, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
19 [15, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
20 [16, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
21 [17, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
22 [18, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
23 [19, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
24 [20, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
25 [21, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
26 [22, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
27 [23, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
28 [24, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
29 [25, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]
30 [26, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]

Kecuali untuk tiga daftar pertama [1, 2, 1, 0], [2, 0, 2, 0], [2, 1, 2, 0, 0], hanya ada satu daftar dari masing-masing panjang n>6, dan memiliki bentuk [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]. Pola ini setidaknya bertahan hingga setidaknya n=50. Saya menduga itu berlaku selamanya, dalam hal ini sepele untuk menghasilkan sejumlah besar ini. Bahkan jika tidak, pemahaman matematis tentang solusi yang mungkin akan sangat mempercepat pencarian.

Tidak
sumber
@Ypnypn Saya sudah khusus n=0. Saya merindukan bahwa kami mengembalikan hasilnya untuk satu n, bukan menghitung n. Ini membuat saya siap n=40.
xnor
0

Pyth - 15 byte

Menggunakan kekuatan kasar dengan semua urutan kemungkinan len ndan kemudian menyaring.

f.A.eq/TkYT^UQQ

Penjelasan lengkap segera hadir.

Coba di sini online .

Maltysen
sumber
2
FYI, OP mengubah kriteria pemenang menjadi kode tercepat.
Alex A.
2
Terlepas dari kriteria kemenangan, berikut golf 3 byte: `fqm / TdQT ^ UQQ`
Jakube
0

K, 26 byte

{f@&{x~(+/x=)'!#x}'f:!x#x}

Seperti pendekatan Maltysen, brute force. Inti dari program ini adalah predikat yang menguji apakah vektor yang diberikan adalah "sihir":

{x~(+/x=)'!#x}

Buat vektor iota selama vektor input ( !#x), hitung kemunculan setiap digit ( (+/x=)') dan bandingkan hasilnya dengan vektor input ( x~). Jika ada kecocokan, Anda memiliki urutan ajaib.

Sayangnya, tikaman pertama ini tampaknya cukup lambat. Menguji menggunakan Kona di laptop saya butuh sekitar 12 detik untuk menangani n = 7. Saya perlu memikirkan ini lebih banyak.

JohnE
sumber