Chuỗi khói Fractal


33

Giới thiệu

A229037 có cốt truyện khá hấp dẫn (ít nhất là trong vài điều khoản đầu tiên):

Có sự phỏng đoán, rằng nó thực sự có thể có một loại tài sản fractal.

Trình tự này được xây dựng như thế nào?

Xác định a(1) = 1, a(2) = 1sau đó cho từng n>2tìm thấy một số nguyên dương tối thiểu a(n)như vậy mà cho tất cả các chuỗi 3 hạn số học n,n+k,n+2kcủa các chỉ số, các giá trị tương ứng của chuỗi a(n),a(n+k),a(n+2k)không một chuỗi số học.

Thử thách

Cho một số nguyên dương nlà một đầu vào, đầu ra là người đầu tiên nthuật ngữ a(1), ... , a(n)của dãy này. (Với bất kỳ định dạng hợp lý nào. Các ký tự / chuỗi huấn luyện có thể không liên quan.)

Có những đoạn để tạo ra chuỗi này có sẵn, nhưng tôi nghĩ các cách tiếp cận khác có thể dễ chơi hơn / phù hợp hơn với một số ngôn ngữ nhất định.

Xin vui lòng cho chúng tôi biết làm thế nào progrm của bạn hoạt động. Nếu bạn gặp một thuật toán đặc biệt hiệu quả, bạn cũng có thể muốn đề cập đến điều đó, vì nó sẽ cho phép vẽ nhiều thuật ngữ của chuỗi trong thời gian ngắn hơn.

Một vài trường hợp thử nghiệm đầu tiên:

1, 1, 2, 1, 1, 2, 2, 4, 4, 1, 1, 2, 1, 1, 2, 2, 4, 4, 2, 4, 4, 5, 5, 8, 5, 5, 9, 1, 1, 2, 1, 1, 2, 2, 4, 4, 1, 1, 2, 1, 1, 2, 2, 4, 4, 2, 4, 4, 5, 5, 8, 5, 5, 9, 9, 4, 4, 5, 5, 10, 5, 5, 10, 2, 10, 13, 11, 10, 8, 11, 13, 10, 12, 10, 10, 12, 10, 11, 14, 20, 13

Thêm thử nghiệm:

  a(100)  =   4
  a(500)  =   5
 a(1000)  =  55
 a(5000)  =  15
a(10000)  = 585

Tất cả các điều khoản n=100000có sẵn tại đây: https://oeis.org/A229037/b229037.txt

Cảm ơn @ MartinBüttner vì sự giúp đỡ và khuyến khích.


2
Này, tôi đã thấy biểu đồ này ở đâu trước đây? :-D
Luis Mendo

12
Di chuyển đầu của bạn sang trái, phóng to một chút, bạn đi! (:
flawr

4
Một video numberphile vừa xuất hiện: youtube.com/watch?v=o8c4uYnnNnc
flawr

2
Tôi cá là mã của anh ta không gần bằng golf!
Luis Mendo

Câu trả lời:


12

Python 2, 95 byte

l=[];n=input()
exec"a=min(set(range(n))-{2*b-c for b,c in zip(l,l[1::2])});print-~a;l=[a]+l;"*n

Thủ thuật chính là tạo ra các số mà giá trị mới phải tránh. Giữ trình tự đảo ngược cho đến nay l, chúng ta hãy xem các yếu tố nào có thể tạo thành một tiến trình số học ba kỳ với giá trị chúng ta sắp thêm vào.

? 4 2 2 1 1 2 1 1   a b c
^ ^ ^               ? 4 2
^   ^   ^           ? 2 1
^     ^     ^       ? 2 2
^       ^       ^   ? 1 1

Các số khác là các thành viên được ghép nối lvà mỗi phần tử thứ hai của l, vì vậy zip(l,l[1::2]). Nếu cặp này là (b,c)tiến trình số học (a,b,c)xảy ra cho a=2*b-c. Sau khi tạo tập hợp acần tránh, mã sẽ lấy mức tối thiểu của phần bù, in nó và đưa nó vào danh sách. (Trên thực tế, việc tính toán được thực hiện với số lượng giảm 1 và được in cao hơn 1, để range(n)phục vụ như một vũ trụ của các ứng cử viên.)


8

Toán học, 95 byte

For[n_~s~k_=0;n=0,n<#,For[i=n,--i>0,s[2n-i,2f@n-f@i]=1];For[++n;i=1,n~s~i>0,++i];Print[f@n=i]]&

Chắc chắn không phải là cách tiếp cận golf nhất, nhưng điều này thực sự khá hiệu quả, so với các thuật toán tôi đã thử từ trang OEIS.

Trái ngược với việc kiểm tra tất cả các giá trị bị cấm đối với mỗi s (n) khi chúng tôi đến đó, tôi đang sử dụng phương pháp sàng dựa. Khi chúng tôi tìm thấy một giá trị mới s (n), chúng tôi sẽ kiểm tra ngay những giá trị này cấm đối với m> n . Sau đó, chúng tôi chỉ giải quyết s (n + 1) bằng cách tìm giá trị đầu tiên không bị cấm.

Điều này có thể được thực hiện thậm chí hiệu quả hơn bằng cách thay đổi điều kiện --i>0thành 2n-#<=--i>0. Trong trường hợp đó, chúng tôi tránh kiểm tra các giá trị bị cấm cho n lớn hơn đầu vào.

Đối với một phiên bản dễ đọc hơn, tôi đã bắt đầu với mã này, nơi lưu trữ các kết quả lên đến maxtrong một hàm f, và sau đó đánh nó vào hàm thuần một dòng trên:

 max = 1000;
 ClearAll[sieve, f];
 sieve[n_, k_] = False;
 For[n = 0, n < max,
  temp = f[n];
  For[i = n - 1, i > 0 && 2 n - i <= max, --i,
   sieve[2 n - i, 2 temp - f[i]] = True;
   ];
  ++n;
  i = 1;
  While[sieve[n, i], ++i];
  f@n = i;
  ]

3

Haskell, 90 , 89 , 84 , 83 byte

Có thể chơi golf nhiều hơn, nhưng đây vẫn là một nỗ lực đầu tiên đàng hoàng :

a n|n<1=0|n<3=1|1<2=[x|x<-[1..],and[x/=2*a(n-k)-a(n-k-k)||a(n-k-k)<1|k<-[1..n]]]!!0

Ung dung:

a n | n<1        = 0 
    | n<3        = 1
    | otherwise  = head (goods n)

goods n = [x | x <- [1..], isGood x n]

isGood x n = and [ x - a(n-k) /= a(n-k) - a(n-k-k) || a(n-k-k) == 0 | k <- [1..n] ]

Đây là một triển khai đơn giản trả về '0' cho giới hạn. Sau đó, với mỗi giá trị có thể, nó kiểm tra rằng với tất cả k <= n và trong giới hạn, [x, a (xk), a (x-2k)] không phải là một chuỗi số học.

Giới hạn trên về độ phức tạp thời gian (sử dụng thực tế từ trang OEIS rằng a (n) <= (n + 1) / 2:

t n <= sum[ sum[2*t(n-k) + 2*t(n-k-k) | k <- [1..n]] | x <- [1..(n+1)/2]]
    <= sum[ sum[4*t(n-1)              | k <- [1..n]] | x <- [1..(n+1)/2]]
    <= sum[     4*t(n-1)*n                         ] | x <- [1..(n+1)/2]]
    <=          4*t(n-1)*n*(n+1)/2
    ->
O(t(n)) == O(2^(n-2) * n! * (n+1)!)

Tôi không chắc ràng mức độ ràng buộc này tốt như thế nào vì tính toán các giá trị 1k đầu tiên của 't' và sử dụng mô hình tuyến tính trên nhật ký của các giá trị đã cho appx. O (22 ^ n), với giá trị p <10 ^ (- 1291), trong trường hợp có vấn đề.

Ở mức độ triển khai, biên dịch với '-O2', phải mất ~ 35 phút để tính 20 giá trị đầu tiên.


1
Sự phức tạp thời gian cho chương trình của bạn là gì?
flawr

@flawr Đã thêm một số phân tích phức tạp về thời gian vào bài đăng
Michael Klein

3

Brachylog , 33 31 byte

;Ė{~b.hℕ₁≜∧.¬{ġh₃hᵐs₂ᶠ-ᵐ=}∧}ⁱ⁽↔

Hãy thử trực tuyến!

Trong trường hợp có vấn đề: Golf 2 byte có thể nhờ một tính năng tôi yêu cầu sau khi thực hiện thử thách này.

Giải trình

Chúng tôi lặp đi lặp lại tạo chuỗi như một danh sách theo thứ tự ngược lại, ví dụ [2,2,1,1,2,1,1], và đảo ngược nó ở cuối.

Có một vài vị ngữ lồng nhau ở đây. Hãy nhìn chúng từ trong ra ngoài. Cái đầu tiên ġh₃hᵐs₂ᶠ-ᵐ=, lấy một chuỗi con ứng cử viên a(n),a(n-1),...,a(0)và xác định xem đó có phải a(n),a(n-k),a(n-2k)là một chuỗi số học cho một số không k.

ġ            Group the list into equal-length sublists (with the possible exception of
             the last sublist, which might be shorter)
 h₃          Get the first 3 sublists from that list
   hᵐ        and get the head of each of those 3 sublists
             We now have a list containing a(n),a(n-k),a(n-2k) for some k
     s₂ᶠ     Find all 2-element sublists of that list: [a(n),a(n-k)] and [a(n-k),a(n-2k)]
        -ᵐ   Find the difference of each pair
          =  Assert that the two pairwise differences are equal

Ví dụ: với đầu vào là [1,2,1,1,2,1,1]:

ġ has possible outputs of
    [[1],[2],[1],[1],[2],[1],[1]]
    [[1,2],[1,1],[2,1],[1]]
    [[1,2,1],[1,2,1],[1]]
    [[1,2,1,1],[2,1,1]]
    [[1,2,1,1,2],[1,1]]
    [[1,2,1,1,2,1],[1]]
    [[1,2,1,1,2,1,1]]
h₃ has possible outputs of
    [[1],[2],[1]]
    [[1,2],[1,1],[2,1]]
    [[1,2,1],[1,2,1],[1]]
hᵐ has possible outputs of
    [1,2,1]
    [1,1,2]
    [1,1,1]
s₂ᶠ has possible outputs of
    [[1,2],[2,1]]
    [[1,1],[1,2]]
    [[1,1],[1,1]]
-ᵐ has possible outputs of
    [-1,1]
    [0,-1]
    [0,0]
= is satisfied by the last of these, so the predicate succeeds.

Vị từ tiếp theo hướng ra ngoài, ~b.hℕ₁≜∧.¬{...}∧nhập một chuỗi con a(n-1),a(n-2),...,a(0)và xuất ra chuỗi con tiếp theo lớn hơn a(n),a(n-1),a(n-2),...,a(0).

~b.hℕ₁≜∧.¬{...}∧
~b.                 The input is the result of beheading the output; i.e., the output is
                    the input with some value prepended
  .h                The head of the output
    ℕ₁              is a natural number >= 1
      ≜             Force a choice as to which number (I'm not sure why this is necessary,
                    but the code doesn't work without it)
        ∧           Also,
         .          the output
          ¬{...}    does not satisfy the nested predicate (see above)
                    I.e. there is no k such that a(n),a(n-k),a(n-2k) is an arithmetic sequence
                ∧   Break unification with the output

Cuối cùng, vị từ chính ;Ė{...}ⁱ⁽↔lấy một số đầu vào và xuất ra nhiều số hạng của chuỗi.

;Ė{...}ⁱ⁽↔
;           Pair the input number with
 Ė          the empty list
  {...}ⁱ⁽   Using the first element of the pair as the iteration count and the second
            element as the initial value, iterate the nested predicate (see above)
         ↔  Reverse, putting the sequence in the proper order

3

Ruby , 71 byte

->n,*a{a.fill(0,n){|s|([*1..n]-(1..s/2).map{|o|2*a[s-o]-a[s-2*o]})[0]}}

Hãy thử trực tuyến!

Tạo tất cả các giá trị bị cấm, sau đó lấy phần bù của mảng đó trong (1..n) và lấy giá trị đầu tiên của kết quả. Điều đó có nghĩa là tôi cho rằnga[n] <= n với tất cả n, điều này dễ dàng được chứng minh bằng cách sử dụng cảm ứng (nếu các điều khoản n / 2 đầu tiên đều nhỏ hơn n / 2, thì không thể có một tiến trình số học dẫn đến n).

Thủ thuật cú pháp ở đây cũng khá thú vị: *ađược sử dụng để khởi tạo một loạt các đối số bổ sung (sẽ bị bỏ qua nếu chúng ta vượt qua bất kỳ), và sau đóa.fill đổi mảng đối số và hoàn toàn trả về nó.


1
-1 byte: thay vì a[s-o]a[s-2*o], bạn có thể sử dụng a[s-=1]a[s-o]
GB

3

APL (Dyalog Extended) , 37 byte SBCS

Rất cám ơn Adám đã giúp đỡ viết và đánh golf câu trả lời này trong The APL Orchard , một nơi tuyệt vời để học ngôn ngữ APL. Hãy thử trực tuyến!

Chỉnh sửa: -6 byte nhờ Adám

⌽{⍵,⍨⊃(⍳1+≢⍵)~-¯2⊥⍵[2×⍀⍥⍳⌊2÷⍨≢⍵]}⍣⎕,⍬

Giải trình

{⍵,⍨⊃(⍳1+≢⍵)~-¯2⊥⍵[2×⍀⍥⍳⌊2÷⍨≢⍵]}   is our right argument, the sequence S

                        2÷⍨≢⍵    We start by calculating X = len(S2
                                 Get a range [1, X]
                   2×⍀⍥           With that we can get S[:X] and S[:X×2:2]
                                  or S up to halfway and every 2nd element of S
             2⊥⍵[           ]   And with that we can get 2*S[:X] - S[:X×2:2]
                                  Which is C=2*B-A of a progression A B C
     (⍳1+≢⍵)~                     We remove these Cs from our possible a(n)s
                                  I use range [1, len(S)+1]
                                 Get the first result, which is the minimum
 ⍵,⍨                              And then prepend that to S


⌽{...}⍣⎕,⍬

 {...}⍣⎕    We iterate an "input"  times
        ,⍬  with an empty list  as the initial S
           and reversing S at the end as we have built it backwards

APL (Dyalog Unicode) , 43 39 38 byte SBCS

Đây là một giải pháp nhanh hơn nhưng ít golf hơn có thể tính toán ⍺(10000)trong vài giây.

⌽{⍵,⍨⊃(⍳1+≢⍵)~-⌿⍵[1 2 1∘.×⍳⌊2÷⍨≢⍵]}⍣⎕,⍬

Hãy thử trực tuyến!


2

MATLAB, 156 147 byte

Cuối cùng tôi cũng đã chơi golf này một chút:

N=input('');s=[0;0];for n=1:N,x=s(n,~~s(n,:));try,a(n)=find(~ismember(1:max(x)+1,x),1);catch,a(n)=1;end,s(n+1:2*n-1,end+1)=2*a(n)-a(n-1:-1:1);end,a

Ung dung:

N=input('');                                   % read N from stdin

s=[0;0];
for n=1:N,
    x=s(n,~~s(n,:));                           % x=nonzeros(s(n,:));
    try,
        a(n)=find(~ismember(1:max(x)+1,x),1);  % smallest OK number
    catch,
        a(n)=1;                                % case of blank page for n
    end,

    s(n+1:2*n-1,end+1)=2*a(n)-a(n-1:-1:1);     % determined new forbidden values
end,
a                                              % print ans=...

Đầu vào được đọc từ STDIN và việc in được thực hiện tự động ans=và các công cụ được nối thêm. Tôi hy vọng điều này đủ điều kiện là đầu ra "hợp lý".

Đây cũng là một giải pháp rây-based: biến s(i,:)giữ theo dõi của những giá trị chuỗi được cấm cho a(i). Các try-catchkhối là cần thiết để điều trị các trường hợp (full zero nghĩa) trống sma trận: trong trường hợp này giá trị thấp nhất của 1đã được cho phép.

Tuy nhiên, bộ nhớ cần (hoặc thời gian chạy?) Trở nên khá lộn xộn ở trên N=2000. Vì vậy, đây là một giải pháp không cạnh tranh, hiệu quả hơn:

%pre-alloc
s = zeros([N,fix(N*0.07+20)]); %strict upper bound, needs adjusting later
i = zeros(1,N);

a = 1;
for n = 2:N,
    x = s(n,1:i(n));
    if isempty(x),
        a(n) = 1;
    else
        a(n) = find(~ismember(1:max(x)+1,x),1);
    end,

    j = n+1:min(2*n-1,N);
    i(j) = i(j)+1;
    s(N,max(i(j))) = 0;   %adjust matrix size if necessary
    b = a(n-1:-1:1);
    s(sub2ind([N,size(s,2)+1],j,i(j))) = 2*a(n)-b(1:length(j));
end

Trong triển khai này, sma trận một lần nữa chứa các giá trị bị cấm, nhưng theo cách được sắp xếp hợp lý, không có bất kỳ khối 0 nào (có trong phiên bản cạnh tranh). Vectơ chỉ số itheo dõi số lượng vectơ bị cấm trong s. Thoạt nhìn, các tế bào sẽ rất tuyệt để theo dõi thông tin được lưu trữ s, nhưng chúng sẽ chậm và chúng tôi không thể lập chỉ mục một loạt chúng cùng một lúc.

Một tính năng khó chịu của MATLAB là trong khi bạn có thể nói M(1,end+1)=3;và tự động mở rộng ma trận, bạn không thể làm tương tự với lập chỉ mục tuyến tính. Nó có ý nghĩa (làm thế nào MATLAB biết kích thước mảng kết quả, trong khung mà nó sẽ diễn giải các chỉ số tuyến tính?), Nhưng nó vẫn làm tôi ngạc nhiên. Đây là lý do cho dòng thừa s(N,max(i(j))) = 0;: điều này sẽ mở rộngs ma trận cho chúng tôi bất cứ khi nào cần thiết. Đoán kích thước bắt đầuN*0.07+20 xuất phát từ sự phù hợp tuyến tính với một vài yếu tố đầu tiên.

Để kiểm tra thời gian chạy, tôi cũng đã kiểm tra một phiên bản mã được sửa đổi một chút, nơi tôi đã khởi tạo sma trận để có kích thước N/2. Đối với các 1e5yếu tố đầu tiên, đây dường như là một phỏng đoán rất hào phóng, vì vậy tôi đã loại bỏ bước mở rộng sđược đề cập trong đoạn trước. Những điều này cùng ngụ ý rằng mã sẽ nhanh hơn, nhưng cũng không mạnh mẽ ở mức rất caoN (vì tôi không biết chuỗi này trông như thế nào ở đó).

Vì vậy, đây là một vài thời gian, so sánh

  • v1: phiên bản golf cạnh tranh,
  • v2: phiên bản kích thước thấp, bằng chứng lừa đảo và
  • v3: phiên bản kích thước bắt đầu hào phóng, có thể thất bại cho phiên bản N lớn.

Tôi đã đo những thứ này trên R2012b, tận dụng tối đa 5 lần chạy bên trong một định nghĩa hàm được đặt tên với tic/toc.

  1. N=100:
    • v1: 0.011342 s
    • v2: 0.015218 s
    • v3: 0.015076 s
  2. N=500:
    • v1: 0.101647 s
    • v2: 0.085277 s
    • v3: 0.081606 s
  3. N=1000:
    • v1: 0.641910 s
    • v2: 0.187911 s
    • v3: 0.183565 s
  4. N=2000:
    • v1: 5.010327 s
    • v2: 0.452892 s
    • v3: 0.430547 s
  5. N=5000:
    • v1: Không áp dụng (không chờ đợi)
    • v2: 2.021213 s
    • v3: 1.572958 s
  6. N=10000:
    • v1: không có
    • v2: 6.248483 s
    • v3: 5.812838 s

Có vẻ như v3phiên bản này đáng kể, nhưng không quá nhanh. Tôi không biết liệu một yếu tố không chắc chắn (rất lớn N) có xứng đáng với sự gia tăng nhỏ trong thời gian chạy hay không.


M=1;M(end+1)=2;làm việc hoàn toàn tốt cho tôi?
flawr

@flawr sẽ làm việc cho vô hướng và vectơ. M=rand(2); M(end+1)=2Thay vào đó hãy thử :)
Andras Deak

À bây giờ tôi thấy =)
flawr

2

Thạch , 24 19 byte

Đây là câu trả lời Jelly đầu tiên của tôi trong một thời gian khá dài. Vui mừng được trở lại.

Đây là một cổng của câu trả lời APL của tôi , bản thân nó là một bản chuyển thể của nhiều thuật toán được sử dụng ở đây. Sự khác biệt chính là đây là 0 chỉ mục.

Chỉnh sửa: -5 byte nhờ Jonathan Allan.

Hãy thử trực tuyến!

Ḋm2ɓṁḤ_
ŻJḟÇṂ;
1Ç¡U

Giải trình

Ḋm2ɓṁḤ_  First link. Takes our current sequence S as our left argument.

         We are trying to calculate, of an arithmetic progression A B C, 
           the C using the formula, C = 2*B - A
Ḋ        Remove the first element of S.
 m2      Get every element at indices 0, 2, 4, ...
           This is equivalent to getting every second element of S, a list of As.
   ɓ     Starts a dyad with reversed arguments.
           The arguments here are S and As.
    ṁ    This molds S in the shape of As, giving us a list of Bs.
     Ḥ   We double the Bs.
      _  And subtract As from 2 * Bs.

ŻJḟÇṂ;  Second link. Takes S as our left argument.

Ż       Append a 0 to S.
 J      Range [1, len(z)]. This gets range [1, len(S) + 1].
  ḟÇ    Filter out the results of the previous link, our Cs.
    Ṃ   Take the minimum of Cs.
     ;  And concatenate it with the rest of the sequence so far.

1Ç¡U  Third link. Where we feed our input, n.

1     A list with the element 1.
 Ç¡   Run the previous link n times.
   U  Reverse everything at the end.

sẽ làm tốt như œ-lưu một byte
Jonathan Allan

Khá chắc chắn rằng bạn có thể lập chỉ mục bằng không (theo mỗi chuỗi ) và do đó thay thế “”bằng việc 1xuất ra một đại diện Jelly của danh sách từ một chương trình đầy đủ, tiết kiệm thêm một.
Jonathan Allan

Œœị@2có thể được đánh golf để Ḋm2cứu hai.
Jonathan Allan

L‘Rcó thể được đánh golf để ŻJtiết kiệm một.
Jonathan Allan

@Jonathan ALLan Năm byte toàn bộ! Cảm ơn!
Sherlock9

1

ES6, 114 byte

n=>[...r=Array(n)].map((x,i,s)=>{for(y=1;x&&x[y];y++);r[i]=y;for(j=i;++j<n;s[j][y+y-r[i+i-j]]=1)s[j]=s[j]||[]}&&r

Trả về một mảng gồm n phần tử đầu tiên của chuỗi, vì vậy các chỉ số là 1 trong phiên bản không được ghi bên dưới. Tôi đã sử dụng phương pháp sàng. Phiên bản này chậm lại sau khoảng n = 2000; một phiên bản trước đó đã tránh đọc phần đầu của mảng, điều đó có nghĩa là nó không bị chậm lại cho đến khoảng n = 2500. Một phiên bản cũ hơn đã sử dụng mảng sàng như một danh sách các giá trị bị cấm chứ không phải là một mảng boolean trong đó các giá trị bị cấm; điều này có thể đạt khoảng n = 5000 mà không đổ mồ hôi. Phiên bản gốc của tôi đã cố gắng sử dụng bitmasks nhưng điều đó hóa ra không có ích (và cũng quá dài ở mức 198 byte).

Phiên bản không quá chậm như vậy:

function smoke(n) {
    result = [];
    sieve = [];
    for (i = 1; i <= n; i++) {
        value = 1;
        if (sieve[i]) {
            while (sieve[i][value]) {
                value++;
            }
        }
        result[i] = value;
        for (j = 1; j < i && i + j <= n; j++) {
            if (!sieve[i + j]) sieve[i + j] = [];
            sieve[i + j][value + value - result[i - j]] = true;
        }
    }
    return result;
}
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.