In một giá trị cụ thể trong ma trận nhị phân được tạo này


14

Giả sử chúng ta xác định một ma trận vô hạn M, bật N^2 -> {0, 1}(nơi Nbắt đầu từ 1thay vì 0) theo cách này:

  • M(1, 1)= 0.

  • Với mọi x > 1, M(x, 1)= 1nếu xlà số nguyên tố, và 0nếu không.

  • Với mọi y > 1, M(1, y)= số hạng ythứ trong Thue-Morse sequence.

  • Với mọi x, y > 1, M(x, y)= M(x, y-1) + M(x-1, y) mod 2.

Phần trên cùng bên trái 16x16của ma trận này trông giống như (với xcác hàng và ylà các cột):

0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0
1 0 1 1 0 0 0 1 0 0 0 1 1 0 1 1
1 1 0 1 1 1 1 0 0 0 0 1 0 0 1 0
0 1 1 0 1 0 1 1 1 1 1 0 0 0 1 1
1 0 1 1 0 0 1 0 1 0 1 1 1 1 0 1
0 0 1 0 0 0 1 1 0 0 1 0 1 0 0 1
1 1 0 0 0 0 1 0 0 0 1 1 0 0 0 1
0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 1
0 1 0 1 0 1 1 1 1 1 0 0 0 0 0 1
0 1 1 0 0 1 0 1 0 1 1 1 1 1 1 0
1 0 1 1 1 0 0 1 1 0 1 0 1 0 1 1
0 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1
1 1 0 0 1 0 1 1 0 1 1 1 0 1 1 0
0 1 1 1 0 0 1 0 0 1 0 1 1 0 1 1
0 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1
0 1 1 0 1 0 0 0 0 1 0 0 1 0 0 1

Nhiệm vụ của bạn là xây dựng một chương trình sẽ đánh giá giá trị của một mục tùy ý trong ma trận này càng chính xác càng tốt.

Chương trình của bạn sẽ lấy hai số nguyên xylàm đầu vào, dưới bất kỳ hình thức nào bạn chọn và trả về M(x, y), sẽ là một 0hoặc 1.

Mã của bạn có thể được viết bằng bất kỳ ngôn ngữ nào, nhưng không được vượt quá 64 kilobyte (65.536 byte) kích thước mã nguồn hoặc 2 MB (2.097.152 byte) trong tổng mức sử dụng bộ nhớ. Chương trình của bạn phải bắt đầu với bộ nhớ trống (nghĩa là nó không thể tải dữ liệu từ nơi khác) và chạy độc lập cho mỗi đầu vào (nghĩa là nó có thể không lưu trữ dữ liệu chung cho nhiều lần chạy). Chương trình của bạn cũng phải có khả năng đánh giá tất cả các mục trong 8192x8192ô vuông trên cùng bên trái trong một khoảng thời gian hợp lý.

Chương trình đánh giá hầu hết các mục chính xác trong 8192 x 8192ô vuông trên cùng bên trái sẽ là người chiến thắng, với mã ngắn hơn đóng vai trò là người phá vỡ.


Có lẽ tôi sẽ cập nhật trường hợp thử nghiệm lên một cái gì đó thanh lịch hơn một chút, vì vậy hãy tiếp tục với thử nghiệm cho đến khi tôi chỉnh sửa lại câu hỏi.
Joe Z.

@mbuettner Vâng, đúng vậy.
Joe Z.

1
Tôi không thấy cách chúng tôi cần một thẻ mới cho "độ chính xác". Đây chỉ là một [thử thách mã]. Vui lòng chạy các ý tưởng thể loại thử thách mới thông qua meta trước tiên (có một điều chúng tôi đã học được từ [trolling mã]).
Doorknob

^ Lưu ý. Tôi sẽ xóa thẻ đó.
Joe Z.

1
@TheDoctor Nó không quá hiếm. Câu trả lời được chấp nhận thay đổi theo thời gian.
Joe Z.

Câu trả lời:


9

J - 42 38 char

Khá nhanh, chính xác 100% và nằm trong giới hạn bộ nhớ.

([{+2&(~:/@#:@#@],~:/\,(p:>:)&#)0:)&<:

Chiến lược như sau: chúng tôi sẽ tính toán các siêu âm liên tiếp của ma trận này, thực hiện XOR theo cặp để di chuyển dọc và thêm các bit Thue-Morse hiện tại và các bit nguyên tố vào cuối. Sau đó chúng tôi kéo chữ số cần thiết ra khỏi antidia chéo khi chúng tôi đến đó.

Giải thích bằng vụ nổ:

(                                 )&<:  NB. decrement each of x and y
     &(                        )        NB. apply the following function...
   +                                    NB. ... (x-1)+(y-1) times...
                                0:      NB. ... starting with a zero:
    2             ~:/\                  NB.   pairwise XOR on the argument
                      ,(p:>:)&#         NB.   append prime bit (is 1+length prime?)
       ~:/@#:@#@],                      NB.   prepend TM bit (XOR of binary)
 [{                                     NB. take the x-th bit (at index x-1)

Cách sử dụng của động từ này là x m ydành cho M (x, y) như được chỉ định trong câu hỏi, mđộng từ ở đâu.

   5 ([{+2&(~:/@#:@#@],~:/\,(p:>:)&#)0:)&<: 8
0
   m =: ([{+2&(~:/@#:@#@],~:/\,(p:>:)&#)0:)&<:
   1+i.16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   m/~ 1+i.16
0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0
1 0 1 1 0 0 0 1 0 0 0 1 1 0 1 1
1 1 0 1 1 1 1 0 0 0 0 1 0 0 1 0
0 1 1 0 1 0 1 1 1 1 1 0 0 0 1 1
1 0 1 1 0 0 1 0 1 0 1 1 1 1 0 1
0 0 1 0 0 0 1 1 0 0 1 0 1 0 0 1
1 1 0 0 0 0 1 0 0 0 1 1 0 0 0 1
0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 1
0 1 0 1 0 1 1 1 1 1 0 0 0 0 0 1
0 1 1 0 0 1 0 1 0 1 1 1 1 1 1 0
1 0 1 1 1 0 0 1 1 0 1 0 1 0 1 1
0 0 1 0 1 1 1 0 1 1 0 0 1 1 0 1
1 1 0 0 1 0 1 1 0 1 1 1 0 1 1 0
0 1 1 1 0 0 1 0 0 1 0 1 1 0 1 1
0 1 0 1 1 1 0 0 0 1 1 0 1 1 0 1
0 1 1 0 1 0 0 0 0 1 0 0 1 0 0 1

Để lưu tổ hợp phím, chúng tôi không cố gắng nói nếu chúng tôi vẫn cần thêm các bit chính hoặc Thue-Morse, vì vậy chúng tôi tính toán toàn bộ antidia chéo để có được bit mà chúng tôi muốn. Tuy nhiên, 8192 m 8192vẫn chạy trong chưa đầy 0,07 giây và khoảng 100 KiB trên máy tính xách tay khiêm tốn của tôi.


6

Mathicala - Độ chính xác 100%, 223 193 189 byte

f=(r=Array[0&,Max@##];For[s=2,s<=#+#2,++s,For[i=Max[1,s-#2],i<=Min[s-1,#],++i,j=s-i;r[[j]]=Which[i==1,PrimeQ@j,j==1,OddQ@Total@IntegerDigits[i-1,2],0<1,Xor@@r[[j-1;;j]]]]];If[r[[#2]],1,0])&

Đây là một phiên bản dễ đọc:

f[x_,y_] := (
   r = Array[0 &, Max[x,y]];
   For[s = 2, s <= x + y, ++s,
    For[
     i = Max[1, s - y],
     i <= Min[s - 1, x],
     ++i,

     j = s - i;
     r[[j]] = Which[
       i == 1,
       PrimeQ@j,
       j == 1,
       OddQ@Total@IntegerDigits[i - 1, 2],
       0 < 1,
       r[[j - 1]]~Xor~r[[j]]
       ]
     ]
    ];
   If[r[[y]], 1, 0]
   );

Về cơ bản, tôi tính toán trước các đường chéo không đổi x+y.

Đặc trưng:

  • Nó chính xác.
  • Nó chạy vào O(x*y).
  • f[8192,8192]mất khoảng 400 giây. Tôi cho rằng có chỗ để cải thiện (có RotateLeftthể thay thế vòng lặp bên trong).
  • Nó chỉ sử dụng một mảng tối đa max(x,y)kết quả trung gian trong bộ nhớ. Vì vậy, không cần thiết phải sử dụng nhiều hơn khoảng 32k (giả sử số nguyên 32 bit) cho chính thuật toán (cộng với, bất cứ điều gì Mathicala sử dụng). Trên thực tế, Mathicala tự sử dụng 31M trên hệ thống của tôi, nhưng điều này hoạt động mà không gặp vấn đề gì:

    MemoryConstrained[f[8192, 8192], 2^21]
    

Chà, có vẻ như bạn đã nhận nó. Tuy nhiên, tôi sẽ làm những thứ khó hơn trong tương lai: P
Joe Z.

Hừm, trong một trong những thay đổi tôi phải làm hỏng hiệu năng thời gian chạy. Vòng lặp bên trong vẫn được gọi là O(x*y)thời gian, nhưng tổng thời gian thực hiện tăng nhanh hơn thế. Tôi không chắc chắn những gì đang xảy ra. Nếu một số Mathicala Guru có thể khai sáng cho tôi, thì thao tác trong vòng lặp không phải O(1)là điều rất hữu ích! :) (tốt, PrimeQTotal@IntegerDigitskhông, nhưng tôi đã có chúng ở đó ngay từ đầu, và chúng chỉ được gọi O(y)O(x)lần lượt tương ứng)
Martin Ender

3

Matlab: độ chính xác 100%, 120 ký tự, thời gian thực hiện không hợp lý

function z=M(x,y)
if y==1 z=(x>1)*isprime(x);elseif x==1 z=mod(sum(dec2bin(y-1)-48),2);else z=xor(M(x,y-1),M(x-1,y));end

Để sử dụng:

> M(4,4)
ans =
      0
> M(1, 9)
ans =
      1

1
Bây giờ đây là câu hỏi, bạn thực sự có thể chạy chương trình này và kiểm tra nó không?
Joe Z.

Nếu bạn không thể chạy M(8192, 8192), tôi không thể lấy nó.
Joe Z.

@JoeZ Đó là mã M, bạn có thể chạy nó trong Matlab hoặc Octave.
intx13

@JoeZ Nó sẽ tính toán chính xác M (8192, 8192). Thử thách không nói lên điều gì về thời gian hoàn thành;)
intx13

1
@JoeZ, có vẻ như M (20,20) mất nhiều thời gian hơn tôi sẵn sàng chờ đợi. Nhưng này, nó "chính xác"! : P
intx13

2

Con trăn, 192 ký tự

Độ chính xác 100%, tính toán M (8192,8192) trong ~ 10 giây trên máy của tôi.

R=range
def M(X,Y):
 X+=1;c=[1]*X;r=[0]
 while len(r)<Y:r+=[i^1 for i in r]
 for i in R(2,X):
  if c[i]:
   for j in R(i+i,X,i):c[j]=0
  r[0]=c[i]
  for i in R(1,Y):r[i]^=r[i-1]
 return r[Y-1]

0

Haskell - 261 byte - 100% - 1MB - Tôi không nghĩ rằng nó sẽ kết thúc sớm bất cứ lúc nào

Mất khoảng 10 giây m 16 16với -O2, nhưng như tôi đã viết nó bằng mọi cách tôi có thể hiển thị nó bất chấp vấn đề này:

m x y=if n x y then 1 else 0 where n x 1=b x;n 1 y=(a!!13)!!(y-1);n x y=(n x (y-1))`f`(n(x-1)y)
f True False=True
f False True=True
f _ _=False
a=[False]:map step a where step a=a++map not a
b x=x`elem`takeWhile(<=x)e
e=c [2..]where c(p:s)=p:c[x|x<-s,x`mod`p>0]

Có lẽ một số Haskeller tốt có thể tối ưu hóa nó?

m' x y = if m x y then 1 else 0
    where
        m x 1 = isPrime x
        m 1 y = morse' y
        m x y = (m x (y-1)) `xor` (m (x-1) y)

xor True False = True
xor False True = True
xor _ _ = False

morse' x = (morse !! 13) !! (x-1)
morse = [False] : map step morse where step a = a ++ map not a

isPrime x = x `elem` takeWhile (<=x) primes
primes :: [Integer]
primes = sieve [2..] where sieve (p:xs) = p : sieve [x|x <- xs, x `mod` p > 0]

main = putStrLn $ show $ m' 16 16

tôi nghĩ rằng thuật toán chính nó là thiếu sót. Dù sao, có rất nhiều điều bạn có thể làm để chơi golf này. chủ yếu là dấu ngoặc đơn phụ, nhưng cũng f p|p=not|0<1=idnên tốt hơn. Ngoài ra, hãy thử sử dụng morse = False : concat $ iterate [True] (\a -> a ++ map not a)để tăng sự lười biếng. Tôi tự hỏi làm thế nào nó sẽ ảnh hưởng đến hiệu suất.
tự hào

Ngoài ra, bạn có thể chơi golf Trueđến 0<1Falseđi 0>1.
tự hào

0

Perl, 137

Không phải là 'giành chiến thắng' :-), nhưng vì chưa có Perl ở đây và mã được viết bằng mọi cách, đây là.

sub f{($n,$m)=@_;@a=0;@a=(@a,map{0+!$_}@a)while@a<$n;for$k(2..$m){$p=0;O:{$k%$_?1:last O for 2..sqrt$k;$p=1}$p=$a[$_]^=$p for 1..$n-1}$p}

Mất vài giây nếu được gọi print f(8192,8192), lưu trữ một dòng ma trận trong bộ nhớ (mảng 8192 số nguyên (vô hướng)), khoảng 3,5 Mb toàn bộ quá trình Perl. Tôi đã cố gắng làm điều đó với chuỗi thay vì mảng (bằng regexps hoặc truy cập bằng đế), chiếm ít bộ nhớ hơn và có thể được chơi gôn hơn, nhưng chạy chậm hơn nhiều.

Thụt lề:

sub f{
    ($n,$m)=@_;
    @a=0;                                  # @a will be current line.
    @a=(@a,map{0+!$_}@a)while@a<$n;        # Fill it with Thue-Morse sequence.
    for$k(2..$m){                          # Repeat until required line number.
        $p=0;                              # Find out if current line number 
        O:{                                # is a prime.
            $k%$_?1:last O for 2..sqrt$k;
            $p=1                           # Store result (0 or 1) in $p.
        }
        $p=$a[$_]^=$p for 1..$n-1          # XOR previous value in current position
    }                                      # with $p and store in $p.
    $p                                     # Return $p.
}

0

Haskell, 223

g n=div(filter(>=n)(iterate(*2)1)!!0)2
1%1=0>1
1%n=not$1%(n-g n)
n%1=and[rem n x>0|x<-[2..n-1]]
a%b=g[0<1]where g s|foldr seq(0>1)s=0<1|n==a+b=s!!(b-1)|0<1=g$n%1:zipWith x s(tail s)++[1%n]where n=length s+1
x p|p=not|0<1=id

cái này có thời gian chạy nhanh (5,7 giây với -O3). bộ nhớ chưa được kiểm tra, mặc dù nó phải là tuyến tính.

cái này sử dụng thuật toán đường chéo nhìn thấy ở đây trước đây.

liên quan đến tốc độ, điều duy nhất quan trọng là thuật toán đường chéo -O3|foldr seq(0>1)s=0<1bảo vệ, làm cho danh sách nghiêm ngặt. mọi thứ khác được triển khai khá kém hiệu quả - kiểm tra chính được thực hiện bằng cách kiểm tra tất cả các số nhỏ hơn để phân chia, các phần tử của chuỗi Morse được tính toán lại liên tục. nhưng nó vẫn đủ nhanh :-).

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.