この生成されたバイナリマトリックスに特定の値を出力します


14

次のようにして、無限行列Mをon N^2 -> {0, 1}(ここでNはからでは1なく0)で定義するとします:

  • M(1, 1)= 0

  • すべてのためにx > 1M(x, 1)= 1場合はx、プライム、とある0そう。

  • ごとにy > 1M(1, y)=のyth番目の用語Thue-Morse sequence

  • すべてのためにx, y > 1M(x, y)= M(x, y-1) + M(x-1, y) mod 2

16x16このマトリックスの左上のセクションは次のようになります(x行とy列):

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

あなたの仕事は、このマトリックスの任意のエントリの値を可能な限り正確に評価するプログラムを構築することです。

プログラムは、2つの整数xy入力として受け取り、任意の形式で入力し、またはを返します。M(x, y)これは0または1です。

コードは任意の言語で記述できますが、ソースコードサイズが64キロバイト(65,536バイト)または合計メモリ使用量が2 MB(2,097,152バイト)を超えてはなりません。プログラムは空のメモリで開始する必要があり(つまり、他の場所からデータをロードできない)、入力ごとに独立して実行する必要があります(つまり、複数の実行で共通データを格納できない場合があります)。また、プログラム8192x8192は、妥当な時間内に左上の正方形のすべてのエントリを評価できる必要があります。

左上の8192 x 8192正方形のほとんどのエントリを正しく評価するプログラムが勝者となり、短いコードがタイブレーカーとして機能します。


おそらく、テストケースをもう少しエレガントなものに更新するので、質問を再度編集するまでテストを続けます。
ジョーZ. 14年

@mbuettnerはい、そうです。
ジョーZ. 14年

1
「精度」のための新しいタグがどのように必要かはわかりません。これは単なる[コードチャレンジ]です。最初にメタを介して新しいチャレンジジャンルのアイデアを実行してください([コードトローリング]から学んだことが1つあります)。
ドアノブ

^注意した。そのタグを削除します。
ジョーZ. 14年

1
@TheDoctor珍しくありません。受け入れられた答えは時間とともに変化します。
ジョーZ. 14年

回答:


9

J- 42 38文字

非常に高速で、100%正確で、メモリの制約内に十分収まります。

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

戦略は次のとおりです。この行列の連続する対角線を計算し、ペアワイズXORを実行して移動し、現在のThue-Morseビットとプライムビットを末尾に追加します。次に、対角線に到達すると、必要な数字を対角線から引き出します。

爆発による説明:

(                                 )&<:  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)

この動詞の使用法はx m y、質問で指定されているM(x、y)で、where mは動詞です。

   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

キーストロークを節約するために、さらに素数ビットまたはThue-Morseビットが必要かどうかを判断しようとしないため、対角線全体を計算して必要なビットを取得します。ただし、8192 m 8192私の控えめなラップトップでは0.07秒未満で約100 KiBで動作します。


6

Mathematica – 100%の精度、 223 193 189バイト

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])&

読みやすいバージョンは次のとおりです。

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]
   );

私は基本的に定数の対角線に沿って事前計算しx+yます。

特徴:

  • 正確です。
  • で実行されO(x*y)ます。
  • f[8192,8192]約400秒かかります。改善の余地があると思います(RotateLeft内部ループを置き換えることができるかもしれません)。
  • max(x,y)メモリ内の中間結果までの配列を1つだけ使用します。そのため、アルゴリズム自体(およびMathematicaが使用するものは何でも)に約32k(32ビット整数を想定)以上を使用する必要はありません。実際、Mathematicaはシステム上で31Mを単独で使用しますが、これは問題なく機能します。

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

さて、あなたはそれを得たように見えます。P:私はしかし、将来的に困難なものを作ることになります
ジョー・Z.

ええと、変更の1つで、ランタイムのパフォーマンスを台無しにしてしまったに違いありません。内側のループはまだO(x*y)回数と呼ばれますが、総実行時間はそれより速く増加します。何が起こっているのかよくわかりません。Mathematicaの第一人者が私を啓発できるなら、ループ内のどの操作がそうO(1)ではないかは非常に役立ちます!:)(まあ、そうPrimeQTotal@IntegerDigitsはありませんが、私は最初からそこにいました、そして彼らはそれぞれO(y)O(x)時間だけを呼びました)
マーティン・エンダー14年

3

Matlab:100%の精度、120文字、不合理な実行時間

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

使用するには:

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

1
ここで質問です。実際にこのプログラムを実行してテストできますか?
ジョーZ.

あなたが実行できない場合M(8192, 8192)、私はそれを取ることができません。
ジョーZ. 14年

@JoeZ Mコードです。MatlabまたはOctaveで実行できます。
intx13 14年

@JoeZ M(8192、8192)を正確に計算します。チャレンジは完了する時間については何も言わなかった;)
intx13 14年

1
@JoeZは、M(20,20)が待ちきれないほど時間がかかるようです。しかし、ちょっと、それは「正確」です!:P
intx13 14年

2

Python、192文字

100%の精度、私のマシンで10秒以内にM(8192,8192)を計算します。

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バイト-100%-1MB-いつでも終了するとは思わない

m 16 16withに-O2は約10秒かかりますが、とにかく書いたように、この問題にもかかわらず表示できます。

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]

おそらく、良いHaskellerがそれを最適化できるでしょうか?

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

アルゴリズム自体に欠陥があると思います。とにかく、これをゴルフするためにできることはたくさんあります。ほとんどの場合、余分な括弧がありf p|p=not|0<1=idますが、より良いはずです。また、morse = False : concat $ iterate [True] (\a -> a ++ map not a)怠lazを増やすために使用してみてください。パフォーマンスにどのように影響するのだろうか。
誇りに思っているhaskeller

また、あなたはゴルフができTrue0<1Falseには0>1
誇りに思っているhaskeller

0

Perl、137

「勝つ」ためではありません:-)、しかし、ここにはまだPerlがなく、コードはとにかく書かれているので、ここにあります。

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}

呼び出された場合print f(8192,8192)、数秒かかります。メモリに単一行の行列(8192個の整数(スカラー)の配列)を格納します。約3.5 MBのPerlプロセス全体です。私は配列の代わりに文字列を使って(正規表現またはsubstrを使用して)それをやろうとしましたが、メモリが少なく、さらにゴルフをすることができますが、はるかに遅くなります。

インデント:

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

ハスケル、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

これは実行時間が速い(5.7秒で -O3)。メモリはまだチェックされていませんが、線形であるはずです。

これは、前に示した対角アルゴリズムを使用しています。

速度に関する限り、重要なことは、対角アルゴリズム-O3、および|foldr seq(0>1)s=0<1リストのみを厳密にするガードです。他のすべてはかなり非効率的に実装されます-除算のためにすべての小さい数をチェックすることによってプライムチェックが行われ、モールスシーケンスの要素は絶えず再計算されます。しかし、それでも十分に高速です:-)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.