CJam(精度50016828 / 100000000、6バイト)
{+1&!}
(CJammer以外のALGOLスタイルの擬似コード:)return ((x + y) & 1) == 0
。
これは、私が試した他の20個の単純なヒューリスティックのいずれよりも優れたパフォーマンスを発揮します。次の2つの最高の組み合わせとの組み合わせよりも優れています。
スコアは、マトリックスの計算されたセクションが正しいと想定しています。独立した検証を歓迎します。計算されたパリティビットをhttp://cheddarmonk.org/codegolf/PPCG95604-parity.bz2でホストしています(8MBのダウンロード、50MBのテキストファイルへの抽出:マトリックスは主対角線に関して対称であるため、それぞれを含めました)メインの対角線から始まる線なので、完全な正方形を得るにはオフセット、転置、ビット単位のORを行う必要があります)。
計算に使用したコードはJavaです。定義はかなり簡単に使用されますが、ランレングスが範囲をエンコードするデータ構造を設定しているため、次の許可された値にすばやくスキップできます。さらに最適化することも可能ですが、適度に古いデスクトップで約2時間、1.5 GBのヒープ領域で実行されます。
import java.util.*;
public class PPCG95604Analysis
{
static final int N = 30000;
public static void main(String[] args) {
Indicator[] cols = new Indicator[N];
Indicator[] diag = new Indicator[N];
for (int i = 0; i < N; i++) {
cols[i] = new Indicator();
diag[i] = new Indicator();
}
int maxVal = 0;
for (int y = 0; y < N; y++) {
Indicator row = new Indicator(cols[y]);
for (int x = y; x < N; x++) {
Indicator col = cols[x];
Indicator dia = diag[x - y];
Indicator.Result rr = row.firstCandidate();
Indicator.Result rc = col.firstCandidate();
Indicator.Result rd = dia.firstCandidate();
while (true) {
int max = Math.max(Math.max(rr.candidateValue(), rc.candidateValue()), rd.candidateValue());
if (rr.candidateValue() == max && rc.candidateValue() == max && rd.candidateValue() == max) break;
if (rr.candidateValue() != max) rr = rr.firstCandidateGreaterThan(max - 1);
if (rc.candidateValue() != max) rc = rc.firstCandidateGreaterThan(max - 1);
if (rd.candidateValue() != max) rd = rd.firstCandidateGreaterThan(max - 1);
}
if (y >= 20000 && x >= 20000) System.out.format("%d", rr.candidateValue() & 1);
maxVal = Math.max(maxVal, rr.candidateValue());
rr.markUsed();
rc.markUsed();
rd.markUsed();
}
if (y >= 20000) System.out.println();
}
}
static class Indicator
{
private final int INFINITY = (short)0xffff;
private final int MEMBOUND = 10000;
private short[] runLengths = new short[MEMBOUND];
public Indicator() { runLengths[1] = INFINITY; }
public Indicator(Indicator clone) { System.arraycopy(clone.runLengths, 0, runLengths, 0, MEMBOUND); }
public Result firstCandidate() {
// We have a run of used values, followed by a run of unused ones.
return new Result(1, 0xffff & runLengths[0], 0xffff & runLengths[0]);
}
class Result
{
private final int runIdx;
private final int runStart;
private final int candidateValue;
Result(int runIdx, int runStart, int candidateValue) {
this.runIdx = runIdx;
this.runStart = runStart;
this.candidateValue = candidateValue;
}
public int candidateValue() {
return candidateValue;
}
public Result firstCandidateGreaterThan(int x) {
if (x < candidateValue) throw new IndexOutOfBoundsException();
int idx = runIdx;
int start = runStart;
while (true) {
int end = start + (0xffff & runLengths[idx]) - 1;
if (end > x) return new Result(idx, start, x + 1);
// Run of excluded
start += 0xffff & runLengths[idx];
idx++;
// Run of included
start += 0xffff & runLengths[idx];
idx++;
if (start > x) return new Result(idx, start, start);
}
}
public void markUsed() {
if (candidateValue == runStart) {
// Transfer one from the start of the run to the previous run
runLengths[runIdx - 1]++;
if (runLengths[runIdx] != INFINITY) runLengths[runIdx]--;
// May need to merge runs
if (runLengths[runIdx] == 0) {
runLengths[runIdx - 1] += runLengths[runIdx + 1];
for (int idx = runIdx; idx < MEMBOUND - 2; idx++) {
runLengths[idx] = runLengths[idx + 2];
if (runLengths[idx] == INFINITY) break;
}
}
return;
}
if (candidateValue == runStart + (0xffff & runLengths[runIdx]) - 1) {
// Transfer one from the end of the run to the following run.
if (runLengths[runIdx + 1] != INFINITY) runLengths[runIdx + 1]++;
if (runLengths[runIdx] != INFINITY) runLengths[runIdx]--;
// We never need to merge runs, because if we did we'd have hit the previous case instead
return;
}
// Need to split the run. From
// runIdx: a+1+b
// to
// runIdx: a
// runIdx+1: 1
// runIdx+2: b
// runIdx+3: previous val at runIdx+1
for (int idx = MEMBOUND - 1; idx > runIdx + 2; idx--) {
runLengths[idx] = runLengths[idx - 2];
}
runLengths[runIdx + 2] = runLengths[runIdx] == INFINITY ? INFINITY : (short)((0xffff & runLengths[runIdx]) + runStart - 1 - candidateValue);
runLengths[runIdx + 1] = 1;
runLengths[runIdx] = (short)(candidateValue - runStart);
}
}
}
}
01.R
ランダムにtrueまたはfalseを出力する05AB1Eです。0をtrue、1をfalseとすると、私のプログラムは理論的には50%の確率で正しいでしょう。これは有効なエントリですか?