ユニバーサル(ルール曲げ)コードゴルフソルバー


14

コードゴルフには常に、挑戦者が当然のことと思っていたり、考えたりルールに記載しなかったりした制約を破ることによって、多少なりともルールを曲げる答えが含まれます。これらの興味深い抜け穴の1つは、より良い結果を得るためにチャレンジが要求するより多く出力する可能性です。

これを極端なものにすると、目的の出力を印刷するユニバーサルコードゴルフソルバーを作成できます。古くなり、前後に他の多くのものが出力されることを気にしない場合。

出力する必要があるのは、可能なすべてのサブシーケンスを含むことが保証されているシーケンスだけです。このコードゴルフでは、これはEhrenfeucht-Mycielskiシーケンスになります

シーケンスは3ビット010で始まります。連続する各数字は、シーケンス内で最も早く出現するシーケンスの最長のサフィックスを見つけ、そのサフィックスの最新の以前の出現に続くビットを補完することによって形成されます。

ビットのすべての有限サブシーケンスは連続して発生し、シーケンス内では無限に頻繁に発生します

シーケンスの最初の数桁は次のとおりです。

010011010111000100001111 ...(OEISのシーケンスA038219)。

シーケンスの8ビットを1バイトに結合すると、画面またはファイルに出力でき、すべての可能な有限出力を含むASCII出力が得られます。プログラムはpiの一部、「絶対にあなたをあきらめない」の歌詞、いくつかの素敵なASCIIアート、独自のソースコード、および出力したいその他のすべてを出力します。

正確性をテストするために、シーケンスの最初の256バイトのハッシュを次に示します。

MD5: 5dc589a06e5ca0cd9280a364a456d7a4
SHA-1: 657722ceef206ad22881ceba370d32c0960e267f

16進表記のシーケンスの最初の8バイトは次のとおりです。

4D 71 0F 65 27 46 0B 7C

ルール:


そのシーケンスで先に現れた010の最長のサフィックスは0ですよね?そして、最新の以前の外観は2番目の0にすぎません。そして今まで、2番目の0に続くものはないため、補完できるものは何もありません。私は英語を母国語とする人ではありません-間違っているだけかもしれません。ウィキペディアの記事では同じ単語を使用していますが、シーケンスが長いため、「フォロワーのいる最新の」という名前を付けます。
ユーザー不明

8
知識のい:piは表示されません-すべての有限文字列のみが出力に含まれます。
キースランドール

別の質問があります:繰り返しが重複してもいいですか?たとえば111では、(1 [1)1]?
ユーザー不明

@KeithRandall:「決してあきらめない」と同様の作品を含まないことが保証されているシーケンスを好むでしょう。
ユーザー不明

2
もちろん、無限の文字列の不特定の場所に埋め込まれた「答え」の存在は、その答えを「出力」しているとは見なせないことに言及する価値があるかもしれません。また、この特定のシーケンスは選言シーケンスの一例にすぎません。このようなシーケンスは無限にあります。
解像度の

回答:


7

C、–110文字

このバージョンのプログラムは、線形ランタイムアルゴリズムを使用してシーケンスを生成します。プログラムの402文字から512を引くと、合計で110が負になります。

#define C v=calloc(7,8),v->p=p
#define G(F,K)u->F[d[K]]
#define S(F,T)G(f,T)=F,G(t,T)=T,G(n,T)=
struct{int p,f[2],t[2];void*n[2];}r,*u,*v,*w;char*d,c;p,b,h,i,j,k;
main(s){for(;d=++p-s?d:realloc(d,s*=2);){d[i=p]=b;c+=c+b;p%8||putchar(c);
for(u=&r;b=u->p,u->p=p,w=G(n,k=i);S(i,k)v=G(n,k),u=v)for(h=G(f,k),j=G(t,k);j>h;--i,--j)
if(d[i]-d[j]){S(i,k)C;u=v;S(h,j)w;S(0,i)C;b=w->p;goto x;}S(0,i)C;x:b=1-d[b+1];}}

問題ごとに、プログラムは無限ループで実行されるため、大量のメモリ割り当てが必要になりrealloc()、シーケンスの連続性を保つために使用すると、ヒープの断片化が発生する可能性があります。calloc(7,8)最初の行をに置き換えることにより、プログラムのメモリ使用量を改善できcalloc(1,sizeof*v)ます。これは、特に56が2倍の大きすぎる可能性がある32ビットマシンで特に役立ちます。

コードは読みにくく、おもしろい方法ではありません。そのことをおpoびします。率直に言って、未ゴルフバージョンでもそれほど明確ではありません。

#include <stdio.h>
#include <stdlib.h>

typedef struct branch branch;
typedef struct node node;

struct branch {
    int from, to;
    node *next;
};

struct node {
    int pos;
    branch br[2];
};

static node root = { 0 };

static unsigned char *data = NULL;
static int endpos = 0;
static int size = 1;

static node *mknode(void)
{
    node *n;

    n = calloc(1, sizeof *n);
    n->pos = endpos;
    return n;
}

static branch *getbranch(node *n, int p)
{
    return &n->br[data[p]];
}

static void setbranch(node *n, int from, int to, node *next)
{
    n->br[data[to]].next = next;
    n->br[data[to]].from = from;
    n->br[data[to]].to = to;
}

int main(void)
{
    node *u, *v, *w;
    int follower, from, i, i0, j;
    int out, b;

    out = b = 0;
    for (;;) {
        ++endpos;
        if (endpos == size) {
            size *= 2;
            data = realloc(data, size);
        }
        data[endpos] = b;
        out = (out << 1) | b;
        if (endpos % 8 == 0) {
            putchar(out);
            out = 0;
        }

        i = endpos;
        u = &root;
        for (;;) {
            follower = u->pos + 1;
            u->pos = endpos;
            w = getbranch(u, i)->next;
            if (!w)
                break;
            i0 = i;
            from = getbranch(u, i0)->from;
            for (j = getbranch(u, i0)->to ; j > from ; --j) {
                if (data[i] != data[j]) {
                    /* divide branch */
                    v = mknode();
                    setbranch(u, i, i0, v);
                    u = v;
                    setbranch(u, from, j, w);
                    setbranch(u, 0, i, mknode());
                    follower = w->pos + 1;
                    goto bitfound;
                }
                --i;
            }
            v = getbranch(u, i0)->next;
            setbranch(u, i, i0, v);
            u = v;
        }
        /* extend branch */
        setbranch(u, 0, i, mknode());

      bitfound:
        b = 1 - data[follower];
    }
}

(上記の未使用のコードは、問題の説明で参照されているように、Golzegorz HermanとMichael Soltysによって記述されたコードに基づいており、Soltysのホームページからも参照できます。)

初期バージョンのバグを報告してくれた@schnaaderと@resに感謝します。


いいね!-512ボーナスで望んだことです。
シュナーダー

これがシステムによってクラッシュを引き起こす理由は何ですか?ゴルフ、ゴルフ、およびmalloc修正されたすべてのバージョンは、約10000バイト後に出力を停止し、メモリの割り当てを継続し、最大prog > out.dat700 KBのメモリ使用量で即座にクラッシュします。printf("\n%i\n", size);後に挿入するreallocと、最大の出力はになり4ます。システム:Windows 7 Prof. 64ビット、4 GB RAM、GCC 4.6.1
シュナーダー

(+1)Ubuntu12.04 / gccでは、両方のプログラムがコンパイルされて正しい出力が生成されることがわかります... Win7 / mingw / gccでは、両方のプログラムがコンパイルされますが、セグメンテーションフォールトが生成されます... Win7 / lccでは未ゴルフバージョンは動作しますが、ゴルフバージョンはセグメンテーションフォールトを生成します。
解像度

1
初期化されていないデータを使用しているように思えます。案の定、Windowsマシンにはアクセスできませんが、valgrindは問題を示しています。元のリファレンス実装からもこのバグを再現したようです。幸いなことに、これは簡単な修正です。報告してくれてありがとう!
パンボックス

素晴らしい、今魅力のように動作します。
シュナーダー

6

ルビー、109 104 101 94文字

s=?0
loop{s=(s[/(.*).*\1/][/.#{$1}/]<?1??1:?0)+s
s.size&7<1&&$><<[s.reverse.to_i(2)].pack(?C)}

サフィックス検索に正規表現を使用したRubyでの実装。メモリ不足になるまで非常に長い時間がかかるため、ユーザーがプログラムを終了する必要があります。

編集:私はちょうどシーケンスで始めるのに十分であることに気づきました0

編集2: resの提案は2文字を節約しますが、他のいくつかは前に1バイトをカットする必要がないためpackです。


を使用s=(s[/(.*).*\1/][/.#{$1}/]<?1??1:?0)+sすると、さらに2文字が保存されます。
解像度

@resこれは確かに機能します。ありがとうございました。
ハワード

括弧を取り除け?Cますか?
ファンドモニカの訴訟

4

Perl、95文字

私は実際に最初にこれの半分まともなバージョンを持っていました。その後、ゴルフをするにつれて、各バージョンが遅くなりました。ますます遅くなります。

$|=$_="010";
y///c%8||print pack"B*",/(.{8})$/while/(.+)$(?(?{m|.*$^N(.)|})(?{$_.=1-$^N})|(?!))/

$|=厳密に言うと、最初の3文字()は必要ありませんが、それがないと、通常、出力が表示される前にスクリプトが完全な4096バイトの生成を完了するのを待つ必要があります。それには数時間かかります。たぶん何世紀も。よく分かりません。このプログラムのパフォーマンスは時間の経過とともに低下することを述べましたか?そのため、それらをカウントに含めることを余儀なくされました。

一方、このスクリプトには、私が作成した中で最もuい正規表現の1つがあるため、私はそれを誇りに思っています。


1
パフォーマンスについては心配しないでください。アルゴリズムは最適化なしのO(N ^ 3)です。私が書いた私の簡単なDelphiプログラムは、256バイトでは約30秒かかりましたが、1024バイトでは約1時間かかりました。もちろん、RegExとスペースの最適化により悪化する可能性があります:)
シュナーダー

最初のPerlスクリプトは256バイトで10秒かかりました。このバージョンには90秒かかります。(それは線形の減速ではないようです。)
ブレッドボックス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.