Chuỗi ma thuật có độ dài n


11

Chuỗi ma thuật là một chuỗi các số nguyên không âm x[0..n-1]sao cho có chính xác các x[i]trường hợpi

Chẳng hạn, 6,2,1,0,0,0,1,0,0,0 là một chuỗi ma thuật vì có 6 0, 2 1, v.v.

Viết hàm mà khi cho n, sẽ xuất ra tất cả các chuỗi ma thuật có độ dài n


Chương trình có thể tạo ra đầu ra chính xác cho giá trị cao nhất của n trong vòng 10 giây giành chiến thắng. (Tất cả các chương trình đều được chào đón)

Ví dụ: chương trình của Alice có thể xử lý tối đa n = 15 trong vòng 10 giây trong khi Bob có thể xử lý tối đa n = 20 trong cùng một lúc. Bob thắng.

Nền tảng: CPU Linux 2.7GHz @ 4


5
Chào mừng đến với PPCG! Đây là một thách thức lớn, nhưng bạn cần một tiêu chí chiến thắng. Ví dụ, bạn có thể nói rằng người chiến thắng là chương trình ngắn nhất.
Ypnypn

1
Có liên quan: Số tự mô tả
Sp3000

2
Xin đừng thay đổi tiêu chí chiến thắng sau khi câu trả lời đã được đăng. Ngoài ra, điều này tốt hơn nhiều so với một mã golf hơn là mã nhanh nhất, ít nhất là theo ý kiến ​​của tôi.
Alex A.

2
@xnor bạn có thể bắt đầu bằng cách tạo các phân vùng số nguyên của n và kiểm tra xem chúng có thể tự mô tả hay không.
Martin Ender

2
Những gì nhỏ nhất n>5với một giải pháp không phải là hình thức [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]? Tôi đã tìm n=20và không tìm thấy cái nào, và tự hỏi liệu tôi có đang mắc lỗi không.
xnor

Câu trả lời:


19

Con trăn, số 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 ()

Điều này sử dụng thực tế, mà tôi sẽ chứng minh, rằng chuỗi phép thuật duy nhất có độ dài nlà:

  • [1, 2, 1, 0][2, 0, 2, 0]chon=4
  • [2, 1, 2, 0, 0] cho n=5
  • [n-4, 2, 1, 0, 0, ..., 0, 0, 1, 0, 0, 0] cho n>=7

Vì vậy, cho n>=7, người ta chỉ cần trả lại một tuple lớn. Tôi có thể làm điều này tối đa n=10^8trên máy tính xách tay của mình, có khả năng bị giới hạn bởi bộ nhớ; bất kỳ và nó đóng băng lên. (Cảm ơn trichoplax cho ý tưởng sử dụng bộ dữ liệu thay vì danh sách.) Hoặc, nếu người ta có thể in một từ điển các mục nhập khác, {0:n-4, 1:2, 2:1, (n-4):1}thì người ta có thể làm điều này cho ginormous n.

Tôi chứng minh sự độc đáo cho n>=7; những cái khác có thể được kiểm tra bằng vũ lực hoặc casework.

Tổng các mục của llà tổng số của tất cả các số của danh sách, là độ dài của nó n. Danh sách này có các l[0]số 0 và n-l[0]các mục khác. Nhưng theo định nghĩa l[0]phải là khác không hoặc chúng ta có một mâu thuẫn, và mỗi mục nhập khác không ít nhất là 1. Điều này đã chiếm một tổng số trong l[0] + (n-l[0]-1)*1 = n-1tổng số n. Vì vậy, không tính l[0], có thể có nhiều nhất là 2 và không có mục nào lớn hơn 2.

Nhưng điều đó có nghĩa là các mục nhập khác không l[0], l[1], l[2], and l[l[0]], có giá trị lớn nhất l[0]và hoán vị 1,1,2, mang lại tổng số tối đa l[0]+4. Vì tổng này là n, ít nhất là 7, chúng tôi có l[0]>=3, và như vậy l[l[0]]=1. Bây giờ, có ít nhất một 1, có nghĩa là l[1]>=1, nhưng nếu l[1]==1đó là một cái khác 1, thì l[1]>=2, ngụ ý l[1]là đơn độc 2. Điều này cho l[2]=1, và tất cả các mục còn lại là 0, vì vậy l[0]=n-4, hoàn thành giải pháp.


Và ngôn ngữ là ...?
edc65

@ edc65 Trông giống con trăn. Nhưng tôi không chắc lắm.
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)

Việc tìm kiếm đầu tiên theo chiều rộng của các danh sách có thể, điền vào các mục từ phải sang trái, dừng tìm kiếm ở hậu tố nếu nó không hợp lý, điều này có thể xảy ra nếu:

  • Tổng các mục trong hậu tố vượt quá n(tổng của toàn bộ danh sách phải là n)
  • Tổng trọng số của i*l[i]hậu tố vượt quá n(tổng cho toàn bộ danh sách phải là n)
  • Bất kỳ số nào xuất hiện trong hậu tố nhiều lần mà hậu tố nói rằng nó nên
  • Số lượng các điểm chưa được lấp đầy còn lại quá nhỏ để chiếm tất cả các số cần xuất hiện nhiều lần hơn.

Tôi đã có các tiền tố được kiểm tra ban đầu từ trái sang phải, nhưng điều đó diễn ra chậm hơn.

Các đầu ra lên tới n=30là:

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]

Ngoại trừ ba danh sách đầu tiên [1, 2, 1, 0], [2, 0, 2, 0], [2, 1, 2, 0, 0], có chính xác một danh sách cho mỗi độ dài n>6và nó có dạng [n-4, 2, 1, ..., 0, 0, 1, 0, 0, 0]. Mô hình này vẫn tồn tại đến ít nhất n=50. Tôi nghi ngờ rằng nó giữ mãi mãi, trong trường hợp đó là tầm thường để tạo ra một số lượng lớn trong số này. Ngay cả khi không, sự hiểu biết toán học về các giải pháp khả thi sẽ giúp tăng tốc tìm kiếm rất nhiều.


@Ypnypn Tôi đặc biệt n=0. Tôi đã bỏ lỡ rằng chúng tôi sẽ trả lại kết quả cho một lần duy nhất n, không tính đến n. Điều này được tôi lên đến n=40.
xnor

0

Pyth - 15 byte

Sử dụng vũ lực bằng tất cả các chuỗi có thể của len nvà sau đó lọc.

f.A.eq/TkYT^UQQ

Sắp có lời giải thích đầy đủ.

Hãy thử nó ở đây trực tuyến .


2
FYI, OP đã thay đổi tiêu chí chiến thắng thành mã nhanh nhất.
Alex A.

2
Bất kể tiêu chí chiến thắng là gì, đây là một golf 3 byte: `fqm / TdQT ^ UQQ`
Jakube

0

K, 26 byte

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

Giống như cách tiếp cận của Maltysen, lực lượng vũ phu. Trung tâm của chương trình là một vị ngữ kiểm tra xem một vectơ đã cho có phải là "ma thuật" hay không:

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

Xây dựng một vectơ iota miễn là vectơ đầu vào ( !#x), đếm số lần xuất hiện của mỗi chữ số ( (+/x=)') và so sánh kết quả với vectơ đầu vào ( x~). Nếu có một trận đấu, bạn có một chuỗi ma thuật.

Thật không may, cú đâm đầu tiên này có vẻ khá chậm. Thử nghiệm bằng Kona trên máy tính xách tay của tôi mất khoảng 12 giây để xử lý n = 7. Tôi cần phải suy nghĩ thêm một chút.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.