Tạo chuỗi Skolem


10

Trình tự Skolem

Một Skolem chuỗi là một chuỗi các 2nsố mà mỗi số igiữa 1nxảy ra chính xác gấp đôi, và khoảng cách giữa hai lần xuất hiện của ilà chính xác ibước. Dưới đây là một số ví dụ về trình tự Skolem:

1 1
1 1 4 2 3 2 4 3
16 13 15 12 14 4 7 3 11 4 3 9 10 7 13 12 16 15 14 11 9 8 10 2 6 2 5 1 1 8 6 5

Các trình tự sau đây không phải là trình tự Skolem:

1 2 1 2      (The distance between the 1's is 2, not 1)
3 1 1 3      (The number 2 is missing)
1 1 2 1 1 2  (There are four 1's)

Mục tiêu

Viết chương trình, hàm hoặc biểu thức để đếm số lượng tất cả các chuỗi Skolem có độ dài cho trước. Nói rõ hơn, đầu vào của bạn là một số nguyên nvà đầu ra của bạn là số lượng chuỗi Skolem có độ dài 2n. Trình tự này có một mục OEIS . Đối với n = 0, bạn có thể trở lại 0hoặc 1. Một vài giá trị đầu tiên, bắt đầu từ 0, là

0, 1, 0, 0, 6, 10, 0, 0, 504, 2656, 0, 0, 455936, 3040560, 0, 0, 1400156768

Quy tắc và tính điểm

Đây là mã golf. Định dạng đầu ra là lỏng lẻo trong lý do.


Chỉ tò mò, nhưng 0, 1, 0, 0, 6...câu hỏi của bạn là gì? Đó có phải là đoạn mã không, nếu vậy thì đó là ngôn ngữ gì?
PhiNotPi

2
Tại sao là mục đầu tiên trong đầu ra của bạn 0? Nếu bạn sẽ thừa nhận 0là một đầu vào hợp lệ thì đầu ra sẽ là 1.
Peter Taylor

1
Một số (bao gồm cả mã của tôi) tin rằng không có chuỗi trống nào. Nếu 1 làm bạn cảm thấy tốt hơn, hãy trả lại.
gian hàng

2
AFAIK trong mọi ngữ cảnh bạn giả sử có một và chỉ một chuỗi rỗng / đối tượng null / tập rỗng, v.v.
Bakuriu

1
@boothby, bạn vừa gọi Knuth là đồ ngốc phải không?
Peter Taylor

Câu trả lời:


8

GolfScript, 48 46 ký tự

:b,1,{)2\?){{.2$&!{.2$|@@}*.+.4b?<}do;;}+%}@/,

Phiên bản nhanh hơn ( thử trực tuyến ) - chạy nhanh hợp lý, ví dụ:n=8 mất khoảng hai giây. Và cách tiếp cận được lựa chọn thực sự có ít nhân vật.

Phiên bản này cũng hoạt động với bitmasks. Nó đưa mảng kết quả có thể từ 1 trở lên, nghĩa là n=3:

1: 000011        000110 001100 011000 110000
2: 010111 101011 101110        011101 110101 111010

Trong khi một số kết quả (như 000011) có hai phần tiếp theo có thể, thì các kết quả khác (ví dụ 001100) không có kết quả nào và bị xóa khỏi mảng kết quả.

Giải thích về mã:

:b           # save the input into variable b for later use
,            # make the list 0..b-1 (the outer loop)
1,           # puts the list [0] on top of the stack - initially the only possible
             # combination
{)           # {...}@/ does the outer loop counting from i=1 to b
  2\?)       # computes the smalles possible bit mask m=2^i+1 with two bits set 
             # and distance of those equal to i (i.e. i=1: 11, i=2: 101, ...)
  {          # the next loop starts with this bitmask (prepended to code via
             # concatination {...}+
             # the loop itself iterates the top of the stack, i.e. at this point 
             # the result array                 
             # stack here contains item of result array (e.g. 00000011)
             # and bitmask (e.g. 00000101)
    {        # the inner-most loop tries all masks with the current item in the result set
      .2$&!  # do item and result set share not single bit? then - {...}*
      {
        .2$| # then generate the new entry by or-ing those two
        @@   # push it down on the stack (i.e. put working items to top)
      }*
      .+     # shift the bit mask left by one
      .4b?<  # if still in the range loop further
    }do;;    # removes the remainders of the loop (i.e. item processed and mask)
  }+%        # stack now contains the new result array
}@/
,            # length of result array, i.e. the number of Skolem sequences

Chấp nhận nhanh hơn các giải pháp gắn.
gian hàng

6

Biểu thức J, 47 ký tự

 +/*/"1((=&{:+.2-#@])#;.2)\"1~.(i.!+:y)A.,~>:i.y

Thí dụ:

    y=:5
    +/*/"1((=&{:+.2-#@])#;.2)\"1~.(i.!+:y)A.,~>:i.y
10

Mất khoảng 30 giây cho y=:5máy của tôi.

thuật toán càng chậm càng tốt:

  • ~.(i.!+:y)A.,~>:i.ytạo ra mọi hoán vị 1 2 .. y 1 2 .. yvà loại bỏ các mục trùng lặp
  • ((=&{:+.2-#@])#;.2)\"1 tính toán:
    • (...)\"1 cho mọi tiền tố của mỗi hàng:
      • #;.2 đếm các yếu tố trước mỗi lần xuất hiện của yếu tố cuối cùng
      • #@] đếm số lượng đếm (tức là số lần xuất hiện của phần tử cuối cùng)
      • =&{: xác định "đẳng thức" "của" "phần tử cuối" của danh sách đếm và của danh sách gốc.
      • +.là một OR hợp lý. =&{:+.2-#@]đọc "các phần tử cuối cùng [của danh sách đếm và danh sách gốc] bằng nhau hoặc chỉ có một phần tử [trong danh sách đếm] chứ không phải hai".
  • */"1 bội số (logic AND) trên các hàng của bảng điều kiện, xác định hoán vị nào là chuỗi Skolem.
  • +/ tổng hợp những cái và số không với nhau.

6

GolfScript (46 ký tự)

:&1,\,{0,2@)?)2&*{2${1$^}%@+\2*}*;+}/{4&?(=},,

Đây là một biểu thức lấy đầu vào trên ngăn xếp. Để biến nó thành một chương trình đầy đủ có đầu vào trên stdin, hãy thêm vào~

Nó khá kém hiệu quả - hầu hết các khoản tiết kiệm tôi đã kiếm được khi chơi golf từ 56 ký tự không được phép là bằng cách mở rộng phạm vi các vòng theo cách không đưa ra kết quả không chính xác nhưng tính toán lãng phí.

Cách tiếp cận là mặt nạ bitwise của các sản phẩm Cartesian. Ví dụ (sử dụng nhị phân cho mặt nạ) cho n=4mã không được mã hóa sẽ tính toán xor của từng phần tử trong sản phẩm của Cartesian [00000011 00000110 ... 11000000] x [00000101 00001010 ... 10100000] x ... x [00010001 ... 10001000]. Bất kỳ kết quả nào với 8 bit chỉ có thể đạt được bằng các mặt nạ không chồng lấp.

Để tối ưu hóa kích thước thay vì tốc độ, mã tích lũy một phần sản phẩm ( S1 u S1xS2 u S1xS2xS3 ...) và làm cho mỗi sản phẩm trở 2nthành các yếu tố thay vì chỉ 2n-1-ithực sự có thể đóng góp vào chuỗi hợp lệ.

Tốc độ

Phiên bản chơi gôn chạy n=5trong 10 giây trên máy tính của tôi và hơn 5 phút cho n=6. Phiên bản không có bản gốc sẽ tính toán n=5trong chưa đầy một giây và n=6trong khoảng 1 phút. Với bộ lọc đơn giản về kết quả trung gian, nó có thể tính toán n=8trong 30 giây. Tôi đã đánh gôn tới 66 ký tự (như một chương trình - 65 ký tự như một biểu thức) trong khi giữ các vòng lặp hạn chế nhất có thể và lọc các va chạm trung gian:

~:&1,\,{0,\).2\?)2&*@-{.{[\].~^.@~+<{;}*}+3$%@+\2*}*;\;}/{4&?(=},,

Chỉ trích. Chỉ khi tôi nghĩ rằng giải pháp 48char J của tôi là đủ tốt để được đăng.
John Dvorak

Chỉ trích. Cà vạt 47 ký tự của chúng tôi đã không tồn tại rất lâu. +1
John Dvorak

5

GolfScript, 49 ký tự

~:/..+?:d(,{d+/base(;:w;/,{.w?)w>1$?=},,/=},,/1=+

Mong đợi số ntrên STDIN. Đây là môn đánh gôn - đừng thử mã nlớn hơn 5.


Ouch, không lớn hơn 5?
gian hàng

@boothby Đó là nỗ lực đầu tiên, trực tiếp. Chúng ta thường phải lấy tốc độ quyết định so với kích thước - và mã golf là về kích thước. Đó là lý do tại sao tôi cũng đã thêm phiên bản nhanh - ban đầu dài hơn nhiều nhưng bây giờ thậm chí còn ngắn hơn.
Howard

0

Hiền nhân, 70

Cái này ngắn hơn một chút so với bản gốc của tôi.

sum(1for i in DLXCPP([(i-1,j,i+j)for i in[1..n]for j in[n..3*n-i-1]]))

Làm thế nào nó hoạt động:

Đưa ra một ma trận 0/1, vấn đề bao phủ chính xác cho ma trận đó là tìm một tập hợp con của các hàng có tổng (dưới dạng số nguyên) cho vectơ tất cả. Ví dụ,

11001
10100
01001
00011
00010

có một giải pháp

10100
01001
00010

Cách tiếp cận yêu thích của tôi đối với các vấn đề là đưa chúng vào một vấn đề chính xác. Trình tự Skolem có hiệu quả tạo điều kiện này. Tôi thực hiện một vấn đề bao phủ chính xác trong đó các giải pháp đang trong tình trạng khó khăn với các chuỗi Skolem có độ dài 2n. Ví dụ, một hàng của vấn đề n=6

  a   |  b  
001000|001001000000 # S[b] = S[b+a+1] = a

trong đó 1 ở vị trí a < ncó nghĩa là biểu tượng ađược sử dụng. Các vị trí còn lại tương ứng với các vị trí thực tế trong chuỗi. Một bìa chính xác tương ứng với mỗi biểu tượng được sử dụng chính xác một lần và mỗi vị trí được điền chính xác một lần. Bằng cách xây dựng, bất kỳ biểu tượng ktrong một vị trí làk không gian xa đối tác của nó.

Trong Sage, DLXCPPlà một triển khai "liên kết nhảy" - nó giải quyết vấn đề che phủ chính xác theo cách đặc biệt duyên dáng. Đó là một trong những thuật toán yêu thích của tôi từ trước đến giờ, và ngay trên bề mặt trong Sage làm cho phép liệt kê tổ hợp trở thành một niềm vui.


Wow, nhảy liên kết. Sử dụng len(list(...))sẽ tiết kiệm được 4 ký tự.
Ray

@Ray Máy tính của tôi đơn giản sẽ chết nếu tôi tính len(list(...))cho n = 16. Và nó hoàn toàn giết chết thời gian chạy.
gian hàng

Điều đó đúng, bởi vì chuyển đổi một trình tạo thành một danh sách tốn nhiều bộ nhớ.
Ray
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.