左への4つのステップ:バイパー。右への4つのステップ:崖。死ぬな!


28

前書き

バイパーと崖が3つではなく、わずか2ステップの距離にあるとします。

            o
           ---
Hsss!       |
 ';;' ___  /_\  ___  _
                      |

残念ながら、あなたはサディスティックな拷問の虜です。ターンごとに左または右に一歩踏み出す必要あります。そうしないと、彼らは即座にあなたを射殺します。事前にステップを計画することはできますが、最初のステップを踏んだ後は、計画を変更することはできません。(また、どろぼうもありません。彼らはあなたを撃ちます。)

突然、明るいアイデアが思い浮かびます...

あ!左右に交互にステップすることができます!右ステップ、左ステップ、右ステップ、左ステップなど...

ああああああ、それほど速くない。私が言ったように、拷問はサディスティックです。彼らはあなたがすべての一歩を踏み出すか、2番目の一歩を踏み出すか、3番目の一歩を踏み出すかなどを選択することができます。そのため、単純にシーケンスを選択すると、RLRLRL...から始まる2番目のステップを実行するように強制できますLL。ええとああ!あなたは毒蛇に噛まれました!闇があなたを襲い、他のすべては消え去ります...

実際には、あなたはまだ死んでいません。あなたはまだあなたの計画を考え出す必要があります。数分間それについて考えた後、あなたは運命にあることに気づきます。あなたの生存を保証する一連のステップを計画する方法はありません。あなたが思いつくことができる最高のものですRLLRLRRLLRR1 11の安全なステップとそれ以上。12番目のステップがの場合、Rトーチャーはすべてのステップを実行し、最後の3つのステップは崖からあなたを送り出します。12番目のステップがの場合、L拷問者は3番目ごとのステップ(LRLL)を実行させます。

あなたRは、あなたの終pick をできるだけ長く遅らせることを望んで、12番目のステップとして選びます。風があなたの耳に響き渡ると、あなたは自分自身に疑問に思います...

3つのステップがある場合はどうなりますか?


スポイラー警告!

あなたはまだ死ぬでしょう。結局のところ、歩数がいくつであっても、どの選択を行っても、致命的な運命を確実に満たすためにTorturerが選択できる一連のステップがあるという点があります。2ただし、毒蛇と崖が3歩離れている場合、合計で1160歩の安全な歩を歩むことができ、4歩離れている場合、少なくとも13,000歩の安全な歩があります!3

チャレンジ

単一の整数を指定すると、崖と毒蛇が4ステップ離れていると仮定して、安全なステップのn < 13000シーケンスを出力しnます。

ルール

  • 完全なプログラムまたは関数のいずれかです。
  • 入力は、STDINまたは同等のものを介して、または関数の引数として取得できます。
  • 出力は持っている必要があります二つの異なる文字(することができ+/-R/L1/0、など)。
  • 出力内の空白は関係ありません。
  • ソリューションのハードコーディングは許可されていません。それはこの挑戦を平凡にするでしょう。
  • プログラムは(理論上)十分な時間で終了するはずです。たとえばn=13000、1か月ほどかかりますが、1000年以上かかることはありません。つまり、総当たりはありません。(まあ、少なくともしようとし、それを避けるために。)
  • ライフボーナス:一連の2000安全な手順を提供します。これを行うと、拷問者はあなたの粘り強さ、忍耐力、そして先見の明に非常に感銘を受け、彼らはあなたを生きさせます。一度だけ。(このシーケンスを2進数として扱い、検証用に10進数を提供します。これは、回答に非常に長い時間がかかるため、すぐに終了する回答に報いることを目的としています。)
  • スコア:バイトボーナスの資格がない場合-0.75を掛けます。

生き残ります!


1 Numberphileのスターの1人であるJames Grimeによるこの問題と「解決策」の説明は、https//www.youtube.com/watch?v = pFHsrCNtJu4のYouTubeチャンネルにあります

2エルドスの矛盾問題として知られるこの80年の推測は、ごく最近テレンスタオによって証明されました。これについては、Quanta Magazineの非常に素晴らしい記事をご覧くださいhttps : //www.quantamagazine.org/20151001-tao-erdos-discrepancy-problem/

3出典:Bordo KonevとAlexei LisitsaによるErdos 不一致推測に対するSAT攻撃。ここから取り出さ:http://arxiv.org/pdf/1402.2184v2.pdf


1
では、のソリューションを作成するn=13000と、最初の2000の指示がボーナスを獲得しますか?無意味だと思うので、おそらくあなたは何か他のものを意味しましたか?
アナトリグ

@anatolyg:すべてのソリューションは、理論的n=13000には1年、おそらく10年以内に処理できるはずです。1か月待ちn=2000ますか?おそらくない。もしそうなら、とにかくボーナスに値する。
エレンディアスターマン

回答:


6

Java、915 * 0.75 = 686.25

import java.util.*;class E implements Comparable<E>{static
int n,m,t,u;byte[]a;int k=2,b,d;E(){a=new byte[5];a[1]=13;}E(E
x){a=Arrays.copyOf(x.a,n+1);k=x.k;d=x.d;b=x.b;}int
g(int x){return(a[x]+1)%3-1;}void s(int x,int y){a[x]=(byte)(a[x]/3*3+(y+3)%3);}void
S(int x,int y){a[x]=(byte)(a[x]%3+(y+3)*3);}E
w(int x){if(g(k)==-x)return null;E e=new E(this);e.s(k,x);e.S(e.k++,x);for(m=0;++m<k;)if(k%m<1){u=e.a[m]/3-3+x;if(u==(k<9?2:4)*x)return
null;e.S(m,u);if(u==3*x){e.b++;if(k+m<=n){if(e.g(k+m)==x)return
null;e.s(k+m,-x);}}}return e;}public int compareTo(E o){m=d-o.d+(b-o.b)/60+(o.k-k)/150;return
m==0?o.k-k:m;}public static void main(String[]a){n=Integer.valueOf(a[0]);Queue<E>q=new PriorityQueue<>();q.add(new
E());for(;;){E x=q.remove(),y;if(x.k>n){for(t=0;++t<x.k;)System.out.print((x.g(t)+1)/2);return;}t=x.g(x.k<9?1:x.k%9==0?x.k/9:x.k%9);y=x.w(t);if(y!=null)q.add(y);y=x.w(-t);if(y!=null){y.d++;q.add(y);}}}}

入力はコマンドライン引数として取得されます。

これは、ほとんどすべての可能性を試行します(唯一の制限は、最初の8ステップが-1..1内でのみ行われることです)。

私の(かなり高速な)コンピューターで1秒以内に2000から4000までの問題を解決します。大きい数値にはより多くのRAMが必要です。8GB以内で解決した最大の入力は5023で、約30秒かかりました。

ボーナスに必要な2000ステップのソリューションの10進数表現:

67629177464446960798008264442022667063957880432486338092706841703491740570274032860458934082821213021464065304260003487277917407152662394728833698812373924467640518368465012204980858438160127647802572983143425507448999967241207186701518207195015015739598846687434709056793597015487555707466358473564611432637890414593517116857771284711814076853125419306285869381974622557155019992727242896503018802441210966188045211779436703341152749688824296759097963388158731237092792251164105828728858516951458791084595247591674731645830905744761534078963607725435881491831508342871545788662307953494333833994658998

追加YbでそれにCJamバイナリに戻って変換します。

ヒューリスティックについて:最初に、私が使用しているパターンがあります。9ステップごとに最初の9を繰り返します(ただし、9 * x)ステップごとにx番目のステップを繰り返します。これは、私のPythonの回答でダウンロードして使用した(ハードコードされた)ソリューションに触発されました。

パターンから逸脱した回数と、「エッジ」に到達した回数(死から1ステップ)を追跡しています。ヒューリスティック関数は、基本的にこれらの2つの数値とこれまでに実行されたステップ数の重み付き組み合わせです。

ヒューリスティックをさらに微調整して速度を向上させることができます。また、ランダムファクターを追加する方法もいくつかあります。
実際、この問題に関連する乗法関数について読んだところ、大幅な改善が得られるようです(TODO:後で実装します)。

非ゴルフとコメント:

import java.util.*;

public class Erdos implements Comparable<Erdos> {
    static int n; // input (requested number of steps)
    static int m, t, u; // auxiliary variables

    byte[] a; // keeps each step and sum combined into 1 byte
    int k = 2; // number of steps + 1 (steps are 1-based)
    int edge; // number of times we got to an edge
    int diff; // number of differences from the expected pattern

    // start with one step
    Erdos() {
        a = new byte[5];
        set(1, 1);
        setSum(1, 1);
    }

    // copy constructor
    Erdos(Erdos x) {
        a = Arrays.copyOf(x.a, n + 1);
        k = x.k;
        diff = x.diff;
        edge = x.edge;
    }

    // get the x'th step (can be -1, 0 or 1)
    int get(int x) {
        return (a[x] + 1) % 3 - 1;
    }

    // set the x'th step
    void set(int x, int y) {
        a[x] = (byte) (a[x] / 3 * 3 + (y + 3) % 3);
    }

    // get the sum of every x'th step (should be within -3..3)
    int getSum(int x) {
        return a[x] / 3 - 3;
    }

    // set the sum of every x'th step
    void setSum(int x, int y) {
        a[x] = (byte) (a[x] % 3 + (y + 3) * 3);
    }

    // try to add a step with value x (1 or -1)
    Erdos grow(int x) {
        if (get(k) == -x) // predetermined step doesn't match
            return null;
        Erdos e = new Erdos(this);
        e.set(k, x);
        e.setSum(e.k++, x);
        for (m = 0; ++m < k;)
            if (k % m < 1) { // check all divisors of k
                u = e.getSum(m) + x; // updated sum
                if (u == (k < 9 ? 2 : 4) * x) // use limit 2 for the first 8 steps, 4 for the rest
                    return null; // dead
                e.setSum(m, u);
                if (u == 3 * x) { // we're at an edge
                    e.edge++;
                    if (k + m <= n) { // predetermine future step - should be going back
                        if (e.get(k + m) == x) // conflict
                            return null;
                        e.set(k + m, -x);
                    }
                }
            }
        return e;
    }

    public int compareTo(Erdos o) { // heuristic function
        m = diff - o.diff + (edge - o.edge) / 60 + (o.k - k) / 150;
        return m == 0 ? o.k - k : m;
    }

    public static void main(String[] a) {
        n = Integer.valueOf(a[0]);
        Queue<Erdos> q = new PriorityQueue<>();
        q.add(new Erdos());
        for (;;) {
            Erdos x = q.remove(), y;
            if (x.k > n) { // we made it
                for (t = 0; ++t < x.k;)
                    System.out.print((x.get(t) + 1) / 2);
                return;
            }
            t = x.get(x.k < 9 ? 1 : x.k % 9 == 0 ? x.k / 9 : x.k % 9); // next step based on the pattern
            y = x.grow(t);
            if (y != null)
                q.add(y);
            y = x.grow(-t);
            if (y != null) {
                y.diff++;
                q.add(y);
            }
        }
    }
}

「後で」年間の待機
CalculatorFeline

1

Python 2、236バイト

n=input();r=len;u=[("",[0]*(n//4))]
while n>r(u[-1][0]):
 y,t=u.pop()
 for c in 0,1:
  s=t[:];u+=(y+"LR"[c],s),
  for i in range(r(s)):
   if-~r(y)//-~i*-~i==-~r(y):s[i]+=2*c-1;
   if abs(s[i])>3:u.pop();break;
print(u[-1][0])

ブルートフォース風の方法では、n = 223の場合は数秒しかかかりませんが、n> = 224の場合はさらに長くなります。

説明: 文字列とリストのペア(s、u)のリストを追跡します。リストuは、文字列のi番目のすべてのステップを実行した後、u [i]が現在の位置になるようなものです。リスト内の各文字列に対して、「L」または「R」を追加してから、交差するリスト内の値を変更してください。(つまり、結果の文字列の長さが10の場合、移動した方向に応じて、位置1、2、5、および10から1を加算または減算します)。3または-3を超える場合は、新しいペアを捨てます。それ以外の場合は、リストに保持します。一番長い文字列は最後に保持されます。長さnの文字列を取得したら、それを返します。


なぜpython 2/3なのか?
Rɪᴋᴇʀ

どちらでも同じように動作します。それらの1つを指定する必要がありますか?
摩擦摩擦メロン

おそらくあなたがすべきです。私はそれ//がPython 2で利用可能であることを知らなかったので、ちょうど疑問に思っていました。
R

-2

Python 2、729バイト

n=0
for x in"eJytVU2LwyAQPWzTvZjjspcsxFYTBdNuQSEF+///1jp+p5o0hYVSBl9nfOObNz1MlAgqzMcEEwQkDyIkFpDYCW0UnChbyZJiK2sfhDcYmu9hT0GdIPQvLduAmoCvvqEssvq84CVCpLzrNcOOspLhY6/KswB6FmoSxGPBcWts7lsMp/0q83da1hgC6k7GoqBir1ruAFIVvWIdTi++oGIAyZw8mkuG03uDDc+rEsSWTmFBwbLgtTF8hl1e/lpCigR7+pM5V9lIqVJBjStzKNRRQDp6UOrvwga6VFrGcWz6YHwLNYWUYeZfWO/DQTq7i4dAxixeszmtFEw7Cr5v9R3lRVF55TDzY6QRrSfzF9NLE7lAZ+vLnGgYLZ/FlCuoRcOugeFduHTqRWmyh1J91XpIndIbEk8jifL8hs8qQ8vjAVoGqhK5Tm/O5svpXd82QH4Azq05kYnhj93PzLbcTisFzXWfDqIC5zsq3jU7UUhSh1R3L4+i4HCXKlrGyywSBttPr2zpL4gCDPtk2HPN5tgZFomzSDPfGAlASus+e4KlLcjS0vPQ0f5/mR/r1s4PcxsgMLRSMp617AveCuup2OCAPBT6yltWrPO9azsbp6fphR87Lc7VzcbEt5F4Ydg/NzhXTA==".decode("base64").decode("zip"):n=n*64+ord(x)
print bin(n)[2:input()+2]

「すぐに終わった回答に報酬を与える」という考えであれば、これはボーナスにも該当すると思います。

ただし、これはハードコーディングされた回答であり、チャレンジの精神ではありません(ただし、私が書いたときに明示的に禁止されているわけではありません)。


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