回転クインを作成する


26

文字列の回転は、文字列を2つの部分に分割し、順序を逆にすることで行われます。たとえば"world! Hello,"、の回転です"Hello, world!"。別の、まだ有効なプログラムを形成するためにローテーションできるプログラムを作成することは可能です。Pythonでこの例を考えてみましょう。

print ")import sys; sys.stdout.write("

回転して形成できます

import sys; sys.stdout.write("print ")

それ自体が有効なpythonプログラムです。

あなたの挑戦は、それ自体の回転を出力するプログラムを書くことです。それは実行されると元のプログラムを出力します。ボーナスは、サイクル長が2を超えるエントリを指します。

これはコードゴルフで、正確なスコアリングは次のとおりです:(コードの長さ)/(サイクルの長さ-1)。

編集:私たちには勝者がいます(他の誰かがスコア4を破れない限り)!私はまだ、競合他社であるかどうかにかかわらず、他のソリューションを見ることに非常に興味があります。


2
いいね!(サイクルの長さ1)の重み付けによる安価な連結を除外しました。
ブースビー

3
これをBefungeで、文字通りの回転で試してみてください。
機械式カタツムリ

鶏肉と卵子を使用することも、この方法に適しています。
meawoppl 14年

回答:


21

APL(158文字、スコア= 4)

'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 

ここではDyalog APLを使用しています。式の最後と文字列の最後(の前''')に(0の後にスペースが続く)を追加することにより、サイクル数を1つ増やすことができます。サイクルの長さは(# 0's) + 1であり、式の長さは150 + 4*(cycle length))です。永遠にゼロを追加し続けると仮定すると、スコアはでLimit[(150 + 4*n)/(n - 1), n -> Infinity] = 4、ここnでサイクルの長さです。

サイクル長= 6の例を次に示します。

      '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 
 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0

      0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0
 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0

      0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0
 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0

      0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0
 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0

      0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0
 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1

      0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1
'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 0 0 0 0

192文字、スコア= 2

'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺ ⋄ a←⊃2⌷⍺ ⋄ ⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01'''{2≠⍴⍺:¯3⌽(2×1+⍴⍺)⍴(1+⍴⍺)⍴⍺⋄a←⊃2⌷⍺⋄⍵=0:¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a⋄(-4+⌊10⍟⊃⍺)⌽(2×1+⍴a)⍴(1+⍴a)⍴a}01

実装に応じて、文字列の前にある整数が大きすぎる場合に障害が発生する可能性があります。ただし、理論的に1は、文字列の最後(の前''')と1行全体の最後に2つの文字を追加することにより、サイクルを追加できます。

200文字、スコア= 1

'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}'''{a←{2=⍴⍵:⊃2⌷⍵⋄⍵}⍺⋄(⍺{⍵=9:⍬⋄⍕1+{2=⍴⍵:10×⊃⍵⋄0}⍺}⍵),(¯2⌽(2×1+⍴a)⍴(1+⍴a)⍴a),⍺{⍵=9:(⍕9),⍕⊃⍺⋄⍕⌊⍵÷10}⍵}91

私のAPL実装にはデフォルトで無制限の精度の整数がありません。そのため、整数が大きくなりすぎると整数になり、出力が間違ってしまいます。そのため、これは最も繊細ですが、理論的には(手作業または別のAPLインタープリターを使用して)スコア1が必要です。1式の最後にa を追加すると、別のサイクルが得られます。

概要(短いクインを使用)

おそらく一番理解しやすいと思うので、最初のバージョンの概要を説明します。ただし、そのバージョンに取り組む前に、APLで簡単なクインを検討します。

1⌽22⍴11⍴'''1⌽22⍴11⍴'''

一部のAPL式を理解する最良の方法の1つは、演算子/関数のカスケード全体で出力を確認することであることがわかりました。APLのすべての演算子と関数は右結合であり、同じ優先順位を持っています。そのため、右から左に次のとおりです。

  • '''1⌽22⍴11⍴''':これは単なる文字列リテラル(文字のリスト)です。''単一引用符をエスケープするAPLの方法です。出力:'1⌽22⍴11⍴'
  • 11⍴'''1⌽22⍴11⍴''':ここでは、文字列の長さを変更します()11。文字列の長さが11未満であるため、繰り返されます(つまり、5⍴'abc'を生成します'abcab')。出力:'1⌽22⍴11⍴''。そのため、最後に2つの引用符があります-どこかに到達しています!
  • 22⍴11⍴'''1⌽22⍴11⍴''':同様に、以前の出力をlengthに変更し22ます。出力:'1⌽22⍴11⍴'''1⌽22⍴11⍴''。もうすぐです-最初の単一引用符を最後に移動するだけです。
  • 1⌽22⍴11⍴'''1⌽22⍴11⍴''':ここでは、文字のリストをで回転()し1ます。これにより、文字列の最初の文字が最後に移動します。別の例として、を2⌽'abcdef'返します'cdefab'。出力:1⌽22⍴11⍴'''1⌽22⍴11⍴'''

回転するクイン

その短いクインは、回転クインの主な基盤です。さて、それを念頭に置いて、私たちの馬を見てみましょう:

'''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 

{ ... }名前のない関数を定義します。ここで作業を行います。APLの関数は、で示される右側の引数((中置記号)で示される)オプションの左側の引数を取ることに注意してください。この関数には、クイン文字列と、任意の数のサイクルを作成するのに役立つ何かの両方を供給します。自分自身(およびサイクルを追加したい人)を簡単にするために、クイン文字列を左引数にします。正しい引数は、サイクルのリストを置く場所です。スペースで区切られた2つ以上のアイテムがリストを作成するため、この例では、a 1とaで構成される2要素リストがあり0ます。

関数が以前のクインに似ていることがわかります。...⌽...⍴...⍴...以前と同じフォームを使用しています。だからそれは良いことです-少なくともそれだけは理解しています!のは、最後の後にすべてのものから始めて、楕円を深く掘り下げてみましょう⊃,/(~^/¨⍺=0)/⍺

  • 上記の例を見るとわかるように、文字列の先頭に右側から0を付け、繰り返しごとに1つずつ追加しています。しかし、私たちは今それらを気にしません。文字列が欲しいだけです!
  • 最初に、括弧内の内容を検討します。(ちなみに、他のほとんどの言語と同様にグループ化されています。)
    • ⍺=0この場合、と同じ形状のリストを返します。この場合、の各要素はに等しい場合はaに、それ以外の場合はaに置き換えられます。これは再帰的に実行されます。したがって、文字のリストのリストがある場合、個々の文字は0に対してテストされ、バイナリ値のリストのリストのリストが返されます。100
    • したがって、文字列だけで構成されている場合、0のリストが返されます。それ以外の場合、左側の引数にはいくつかの0が接頭辞として付けられているため(例:)0 0 0 'quinestring'、0で構成されるリストと別のリストである文字列です。次に、出力は次のようになり1 1 1 <sub-list of zeros>ます。
    • ^/¨⍺=0:論理関数AND()を使用して^//)を削減する派生関数を、の^各(¨)要素に適用し⍺=0ます。これは、ゼロのサブリストをフラット化して、キイン文字列を1つのバイナリ値と見なすことができるようにすることです。前の例を考慮すると、出力はになります1 1 1 0
    • ~:以前の各値をバイナリーではありません(例:を返す0 0 0 1)。
  • (~^/¨⍺=0)/⍺:の各要素について、左引数の対応する要素によって指定された回数だけ複製します(/)。これにより、0がすべて削除され、クイン文字列のみが残ります。
  • ⊃,/は、連結関数(,)で結果を減らすことにより、文字のフラット化されたリストを確実に取得するために必要な書類です。入力が既にフラット化されたリストである場合(つまり、メイン関数の左引数が文字列のみである場合)、そのリストを含む1要素のリストを取得します。他の場合、文字列のサブリストで構成されるリストがある場合、同じもの(サブリストを持つリスト)が返されます。次に、これをアンパックし()、リストの最初の要素(つまり、文字のサブリスト)のみを提供します。これは不要に思えるかもしれませんが、それ以外の場合は、1要素のリストを作り直そうとしています。

次に、かっこ内の最初の形状変更に指定された長さを確認します。

  • ⍺,⍵:正しい引数を最初の引数に連結します
  • ⊃,/⍺,⍵:前と同じ-リストをフラット化します。
  • +/0=⊃,/⍺,⍵:追加/+)関数を使用して()を減らし、リスト内のゼロの数を合計します。
  • 2×+/0=⊃,/⍺,⍵:その数に2を掛けます。
  • z←2×+/0=⊃,/⍺,⍵結果を変数に割り当てます()z。要約するとz、左と右の両方の引数で見つかったゼロの数の2倍になりました。
  • 77+z←2×+/0=⊃,/⍺,⍵:次に77、文字列の文字にを追加します1。後続のスペース以降のすべてを無視します。最初のクインの例のように、文字列の長さに1を追加して、別の単一引用符を取得します。
  • この再形成の出力は、この例では次のとおりです。 '{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''

次の形状変更の引数は単純で、短いクイン(最初の形状変更の長さの2倍)を反映しています。現在の出力は次のとおりです。

'{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 '''{(((3+z)×^/⍵)-5+2×+/+/¨⍺=0)⌽(2×77+z)⍴(77+z←2×+/0=⊃,/⍺,⍵)⍴⊃,/(~^/¨⍺=0)/⍺}1 0 ''

最後のステップでは、出力文字列を回転させる量を計算します:

  • 前の出力を見ればわかるように、2つの最終的な引用符を先頭に戻すために、それを逆方向(負の量)に回転させたいと思います。私たちがしたいので0、同様先頭に移動する(および他のスペース)を、我々は戻ってそれをさらに3つの文字を回転したいです。
  • +/+/¨⍺=0引数のゼロの数を合計します。最初の(右から)+/¨は各要素のカウント(つまり、サブリストまたは単なる整数)を+/合計し、2番目はその結果のリストの合計を提供します。
  • 5+2×+/+/¨⍺=0:2を掛けて(スペースも回転させるため)、5を加えます(前に思いついた結果)。
  • 次に、左の引数から前の値を減算して-、サイクルの最後に達した場合を処理します。
    • (3+z)×^/⍵:AND正しい引数内のすべての要素を一緒に使用して、終了(1)に到達したかどうかを確認し、それに乗算し3+zます。

これで完了です!


元気な質問を書いたとき、すごい、非常にクールな、私はこのような何かを期待していませんでした!私はAPLをまったく話せませんが、これがどのように機能するかについて概要を説明できる可能性はありますか?
ゴードンベイリー

もちろん!投稿するバージョンがさらに2つあり(理論的にはスコアが低い)、明日中に概要を追加します。
ディロンコウアー

非常に徹底的なドキュメントをありがとう、ここでいくつかの巧妙なトリックを使用しています。私は特にoperator(?)の使用が好きです。それを完全に消化する前に、全体を数回読む必要があると思います!
ゴードンベイリー

13

GolfScript、10046/9999≈1.0047(漸近スコア1)

OK、DCのAPLエントリをこれで破ってみます。

{\''+.,{(;\'.~1'}{'1'9999*@'.~']puts:puts}if}.~

上記のコードは実際のクインではありません — 10kBのワンライナーを投稿することはあまり良い考えではないと感じました。むしろ、上記のコードを1回実行すると、実際の10046文字のGolfScriptプログラムが生成されます。このプログラムは、質問で指定されたとおりに繰り返されると、9999回転し、最後に再び回転します。

サイクル(およびプログラム)の長さは、定数を変更することで調整できます9999。簡潔にするために、定数を次のように減らした場合の反復出力がどのようになるかを示します9

111111111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~
11111111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~1
1111111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~11
111111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~111
11111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~1111
1111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~11111
111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~111111
11{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~1111111
1{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~11111111
{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~111111111
111111111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~
11111111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~1
1111111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~11
111111{\''+.,{(;\'.~1'}{'1'9*@'.~']puts:puts}if}.~111
etc.

定数9999を大きくすると、プログラムの長さとサイクルの長さの比(マイナス1)が1になります。少なくとも漸近的にではなく、この解決策に勝てないと確信しています。;-)

どのように機能しますか?

基本的に、任意の数字リテラルがクインとして機能するため、GolfScriptはクインを書くのに非常に簡単な言語12345です12345。また、複数のクインを連結すると、通常、クインが生成されます。したがって、11111...111サイクリッククインの反復部分のような単純な数値を使用できます。

ただし、クインを実際に循環させるには、重要な「ペイロード」を実行する必要があります。私が考えることができる最も簡単なGolfScriptの馬は、次のとおりです。

{PAYLOAD'.~'}.~

したがって、私の計画では、そのようなクインに繰り返し数値定数を接頭辞として付け、数字から1桁を切り取り、プログラムの最後に移動するペイロードを使用することでした。プログラムがその前に数値定数ないことを検出した場合(その場合、スタック上のその下の値は入力がないと仮定して空の文字列になります)、代わりに固定長の数値定数を前に追加します自体。

ただし、もう1つしわがあります。「ラップアラウンド」するとき、ペイロードはそれ自体のの数値の出力も抑制する必要があります。通常、GolfScriptプログラムが終了すると、スタック上のすべての値が自動的に印刷されますが、これは問題です。

ただし、それを回避するための(不明な)文書化されていない方法があります:インタープリターは実際に定義済みの関数putsを呼び出して印刷を行うため、その関数をノーオペレーションとして再定義すると自動出力が抑制されます。もちろん、これはまたputs、印刷したいスタックの一部を印刷するために、最初に自分自身を呼び出す必要があることを意味します。

最終的なコードはかなり複雑に見えますが(GolfScriptの場合でも)、少なくとも機能します。ペイロードからいくつかの文字を削除することをまだ考えていなかった巧妙な方法があるかもしれないと思うが、このバージョンでは主に漸近スコアに焦点を合わせていた。


私は出力なしの改行は厳密に循環していないことを意味するという理由でputs{}:puts議論を見ることができたが、なしで私のために働くようです{print}:puts
ピーターテイラー

@Peter:]puts{}:putsはから{STUFF}.~111111111にラップアラウンドするために必要です111111111{STUFF}.~。そうしない1と、プログラムの最後のs の数が増え続けます。({}かかわらず、不要と思われる。明らかに、GolfScriptインタプリタは空のスタックから割り当てを可能にする。)
イルマリKaronen

DCは漸近スコアが1のソリューションも投稿しているように見えますが、非常に素晴らしいので、同点になる可能性があります。
ゴードンベイリー

-3

HTML、マイナス無限大(ほぼ)

-2

AA

-10

AAAAAAAAAA

など...誰かがそれが不正行為であると言った場合、私たちはそれについて議論することができますが、私は問題の穴を見つけました:)

だから私は誰もがコードがループを持たないことを理解していると思うので、最も長いループが0あり、プログラムの長さがn、スコア、n / (0 - 1)またはを考慮すると、大きな正の整数-nを持つプログラムを書くことができますnが、誰もがそれを理解するので役に立たないです。


7
申し訳ありませんが、サイクルの長さは0ではなく1です。したがって、スコアはn / 0であり、負でも小さくもありません。
ポールトーマン14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.