読み取り不可、3183 3001バイト
これは、クリスマスのお祝いの合間に、オン、オフの作業をするための楽しい挑戦でした。投稿していただきありがとうございます!仕様には多くのif条件を必要とする例外と特別なケースがいっぱいであるため、これをゴルフで楽しむことは興味深いものでした。また、今回は10進数に変換したり、10進数から変換したりする必要はありませんでしたが、各数値の最大桁数と各桁の最大値を決定するための「最大」ソート関数が必要でした。
これの最初のバージョンは4844バイトでした。これは、私がどれだけゴルフをしたかを知るためのものです。
プログラムは、入力を整数のコンマ区切りリストとして予期します。スペースや改行なし。これらを使用すると、未定義の動作が発生します。
'"" "" "" "" "'" "'" "'" "'" "'" "" '"" "" ""' "" "'" "'" "'" "'" "' "" '""' "" "" "'" "'" "'" "" "" "'" "'" "'" "'" "'" "'" "'" "" '""' "" '""' "" "" "'" "'" "'" "'" "'" "'" "'" "'" "'" "'" "'" "'" "'" " '"" '""' "" "" "'" "'" "'" "" ""' "" '""' "" '""' "" '""' "" "" "" '" "" "" "" "" "" "" "'" "'" "'" "'" "'" "" "" "" ""' "" "'" "'" "" "" ' "" "" "" "" "" '""' "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "" """ "" "" "" "" "" "'" "" "" "" "" "" "'" "'" "" "" "" ""' "" "" "" "" " '"" "'" "" "" '""' "" "" "" "" "'" "'" "'" ""' "" "" "" "" "" "" "" "' "" "" "" "" "'" "'" "" '"" "" "" "'" "'" "'" "'" "'" "'" "'" "" '""" "" "" "" "" "" "" '"" "" ""' "" '"" "" "" "" "" "" "" "" "" ""' "" '"" "" "" "" "" ""' "" '""' "" "'" "" "" "" "" "" "" "" "'" "'" "'" "" " '"" "" ""' "" '""' "" '"" "'" "" "" "" "'" "" "" ""' "" '""' "" '""" "" "" "" "" "" "" "'" ""' "" "" "" "" "" "" "" "" "" "'" "" "" "" " "" "" "" "" "" "" "" "" "" "" "" "" "" '""' "" '"" "" "" "" "" "" "" "" " '"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""' "" "'" """ "" "" "" "'" ""' "" '"" "" "" "'" "" "" "" "" "" "" "'" "'" "'" " '"" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "'" "'" "" "" "" '"" "" "" "" "" "'" "" "" "" "" "" "" "" "" "'" """ "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" ""' "" "'" "" "" "" "" "" "" "" "" "" "" "" ""' "" '""' "" ' "" '""' "" "" "'" ""' "" "" "'" "" "" ""' "" "" "" '""' "" "'" "'""" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "" "" "" "'" '""' "" '' " "'" "'" "" "" "'" "" "" "'" "" "" '""' "" '"" "" "" "" ""' "" "" "" '' "" "" "" "" "" "" "" "" "" "" "" '"" "'" "" "" "" "" "" "" "" "" """'" "" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" "" "" "'" "" "" "" " "'" "" "" "" "" "" ""' "" '""' "" '""' "" "" "" "" "" "'" "" "" "" " '"" "" "" "'" "'" "'" "'" "" ""' "" '""' "" "'" "" "" "" ""' "" """" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" "" "" ""' "" "" "" " "'" "'" "" "" '"" "'" "" "" "'" "'" "'" "'" "" "" "'"' "" "" "" "" '' "" '"" "" "" "" "" "" "" "" "" "" "'" "" "" "" "'" "'" "'" "" """" "" "" "" "'" "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" " "" "" '"" "" "" "" "'" "'" "" "" ""' "" "" "" "" "" "" "" "" '""' "" '' "" "" "" "" "" "" "" "'" ""' "" "'" "" "" "" ""' "" '""' "" '"" """" "" "" "" "" '""' "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" "" "" "" "" '"" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" '"" "'" "" "" "" "" '"" "" "" "'" "" "" "" '"" "'" "" "" "" "" '""'"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "" ""' " "" "" "" "" "'" "'" "'" "'" "" "" "'" "" "" "" "" "" "" ""' "" "'" "" "" "" "" '""' "" '""' "" '"" "'" "" "'" "" "" "" ""' "" "" "" "" "'""' "" "" "'" "" "" "" "" "" "" "'" "'" "'" "" "" "" "" "" "" "" "" "" "'" "'" "" "" "'" "" "" "" "" "" "" "'" "" "" "" "" "" "" "'" "" "" "" " '"" "" "" "'" "'" "" "" "" "" "" "" "" ""' "" "" "" "'" "'" "'" "'""'" "'" "" "" "" '""' "" '"" "'" "" '"" "" "" ""' "" '"" "" "" "" "" "'" "" "" "" "" "" "'" "" "" "" "" "'" "" "" "" "" "'" "" '"" "" "" ""' "" "" "" "" "" "" "" "'" "'" "" "" "" '"" "" "" "" "" "" "" "" "" ""'""' "" '"" "'" "'" "" "" ""' "" '""' "" "'" ""' "" "" '"" "" "" "" " "'" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "'" " "'" ""' "" "" "" '"" "" ""' "" '""' "" "" "" "" "" "" "" "" "" "'""'" "'" "" "" "" '"" "" "" "" "" "" "'" "" "" "" "" '""' "" "" "'" "" " "" "" '"" "" "'" "" '"" "" ""' "" "" "" "" "" "" "" "" "'" "" "" "'" " "" "" "'" "'" "" '"" "" "" "" "" ""' "" "" "" "" "" "" "" "" "'" """" "" "" "" "" "" "" '"" "" "" "" "" "" "" "" "" "" "" ""' "" '""' "" "" '"" "'" "" '"" "'" "" "" "" "" '"" "" "'" "" "" "" '"" "" ""' "" '"" "" '""' "" "" "" "'" "'" "" '"" "" "" "'" "'" "'" "'" "'" "" '"" "'""" "" "" "" "" "" "" "'" "'" "'" "'" "" "" "" "" "" "" '"" "" "" "' '" "" "" "" "" "" "" "" "'" "" "" "" "'" "" "" "" "" "" "" "" "'" "" "" "" "'" "" "" "" "" ""' "" "" "" "" "" "" "" "" "" "" "" "" '"" "'" '"" "" "" "" "" '""' "" '"" "" "'" "'" "" "" "" "" "" ""' "" "" "" "' "" "'" "" "" "" "" "" "" "" "" "" ""' "" "" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" '"" "" "" ""' "" "" "" "" "" "" "" "" '"" "" ""'"" "" "" "" "" "'" "" "" "" "'" "" "" "" '"" "" "" "" "" "" "" "
説明
特定の入力を処理する方法を示すことで、プログラムがどのように機能するかを説明します202,100,1
。
最初に、後で必要になるいくつかの値を作成します。ほとんどの場合、出力する文字のASCIIコードです。
あなたが見る、わかるように'8'
して'.'
、すでに利用可能です。'|'
ただし、実際は14ではなく124です。whileループを使用して、スロット#1の一時値を2倍して124を取得します(whileループは56-1 = 55で実行されるため、14 + 55×2です)。繰り返し)。124のような大きな整数リテラルは本当に長いため、これによりバイト数が節約されます。次の図では、プログラムが使用するすべての変数の場所を示しています。
次に、すべての文字を入力し、セル#12からテープに保存します(pはこのための実行ポインターです)。同時に、最も長い数字の長さ(桁数)を知りたいです。これを達成するために、セル#-1から左に向かって単項で実行中の合計を保持します(実行ポインターとしてqを使用します)。最初の入力番号(202
)の後、テープは次のようになります。
数字が4ずれていることに気付くでしょう。最初に入力したとき、それらはASCII値であるため、48で「オフ」になり、カンマは44です。各文字に対して、46をコピーします。R、次にwhileループでそれを引く(45を減算する)、その後、私たちはそれを認識するために、条件を使用できるように、我々は、カンマ(、私たちのセパレータ)が0であるので、それを行う1を追加します。'.'
また、セル#11を0のままにしていることにお気づきでしょう。最初の数字の境界を認識するために必要です。
次の文字はコンマになるため、#15に0を格納しますが、もちろん今回はqを進めません。代わりに、qを0に戻し、既に配置した1を「上書き」し始めます。
残りのすべての文字が処理された後、次のようになります。
ご覧のように、qで書かれた1 は、最も長い数値の長さを(単項で)示しています。
ここで、whileループを使用してqを一番左に移動し、そこに別のポインターを配置してr2を呼び出します。r2の目的は後で明らかになります。
この時点で、これから使用する用語を明確にします。
- 数、私はカンマで区切られた入力番号のいずれかを意味します。この例では、202、100、1です。
- 桁、私は数字の特定の1で一桁を意味します。最初の数字は3桁です。
- 場所によって、私は1の場所、10の場所、100の場所などを意味します。したがって、「現在の場所の数字」と言い、現在の場所が1の場所である場合、それらの数字は2、0、および1です注文。
さて、通常のプログラミングに戻りましょう。プログラムの残り全体は、セル#0に到達するまでqを前方に移動する大きなループです。途中の各セルは1つの場所を表し、1つの場所は右端にあり、qは最上位から始まります。この例では、数百の場所です。
我々は、細胞増加することによって進めるのq(、である点をQ *)。
私たちは現在、数百の場所で「ステージ2」にいます。この段階では、数百の桁の中で最大の桁が何であるかを調べます。これには同じ単項カウンティングトリックを使用しますが、今回はポインターがrと呼ばれ、ポインターr2が次の番号に進むたびにリセットする必要がある開始位置をマークします。
最初の数字から始めましょう。まず、pを11(すべての数字のハードコーディングされた開始位置)に設定します。次に、whileループを使用して数値の末尾を見つけ、そこにp2を設定して位置をマークします。同時に、q2を0に設定します。
q2が変数を指しているという事実に気を取られないでください。セル番号0であるという理由だけでセル#0を検出できるため、空白セルのパディングはありません。
次に、* pがゼロになるまでpとq2を一緒にデクリメントして、現在の数を調べます。それぞれの場所で、* q2の値は何をする必要があるかを示しています。1は「何もしない」という意味なので、続けます。最終的に、セル#-3の2に遭遇します。* q2が1に等しくないたびに、q2は常にqに等しくなります。
すでに述べたように、ステージ2は「この場所で最大の桁を決定する」ことです。したがって、rをr2に設定し、whileループを使用して* pをデクリメントし、rを左に移動してテープを1で埋め、次に別のwhileループを使用してrを右に戻し、* pを再度インクリメントして値を復元します。whileループは、使用する値よりも1回少ない反復で実行されることに注意してください。このため、書き込まれる1の数は数字の値よりも4つ多くではなく3つ多くなり、* pに戻される最終値はさらに2つ多くなります。したがって、これにより* pが実質的に2 減少します。
その後、pをp2の値に設定し、それをすべて繰り返します。再度、q2を0 に設定し、pを右に移動して数値の末尾を見つけ、pとq2を一緒にデクリメントしてこの数値の桁を調べます。もう一度、セル#-3の2に遭遇し、* rの残りの1を書き込みます。
3番目の数値の場合、100の位がないために何もしません(したがってq2はqに到達しません)が、最大桁の値の計算に影響を与えないため、それは問題ありません。
また、ここではラベルなしの矢印でマークしたセル*(r − 4)を1に設定します(すでに1になっている場合でも)。まだ理由をお話しするつもりはありませんが、おそらくあなたはすでに推測していますか?
次の* qの増分により、ステージ3に進みます。これは、「現在の場所のすべての桁から最大桁を減算する」ことです。前と同様に、pを11に、q2を0 にリセットしてから、前の段階で行ったようにすべての数値を調べます。この時間を除いて、* Q 3の代わりに、2度に= q2は満たしているのqとpは百の位であるが、我々が使用中デクリメントへのループ* Pの左側のブロック内の1があるとして、多くの倍* R2(5この例では)rを使用して実行中のポインターとして。実際にそれをもう一度デクリメントして、最大桁が-2になるようにします。理由は後で明らかになります。
すべての数値を処理した後、ステージ3の終わりになりました。ここでは、2つの特異なことを実行します。
- 最初に、* qからrブロック(プラス1)のサイズも減算しますが、r2ポインターを使用して、左側に残します。* qはこの方法で負になります。この場合、rブロックには5つの1があるため、* qは-3になります。
- 次に、変数をゼロ以外の値に設定して、現在出力ステージに入っていることを示します。(技術的には、* qが負であるという事実はすでに出力段階を示していますが、これは確認するのが難しすぎるため、余分な変数です。)
あなたは今、我々は数字を経由しておくことを理解する(非1の値で示される現在の場所を見つける* Qがそれぞれ数以内)、およびの値に応じて何かをする* Q。私たちは、ことがわかり* qは最初の3、その後、(=計算最大桁値)2にインクリメント(この場所で、すべての桁から最大桁の値を減算)し、我々はそれを否定するために、それから減算されます。そこから、1に達するまで上昇し続け、「何もしない」ことを意味する値を復元します。その時点で、次の場所に進みます。
現在、* qが負の場合、出力しています。* qは正確に正しい値であるため、1に達する前に正しい数の文字の行を出力します。最大桁が2の場合、3行を出力する必要があります。* qの各値で何が起こるか見てみましょう:
- * q = −2:
- 最初の数値では、* pは-2であり、これは
'.'
(ドット)または':'
(コロン)を出力する必要があることを示します。qを見ることでどちらを決定します:-1の場合は1の場所にあるので、a ':'
('8'
+2 として計算)を出力し、そうでない場合はa を出力し'.'
ます。
- 2番目の数値の場合、* pは-3です。−2以外
'|'
の値は、(パイプ)を出力してから値をインクリメントすることを意味します。このようにして、正しい場所で-2に到達し、その数字の残りについて'.'
s / ':'
s を出力します。
- いずれの場合も、数値を処理する前に変数pdを0 に設定し、pd(=“ printed”)をゼロ以外の値に設定して、文字を印刷したことを示します。
- 3番目の番号には、数百の桁がないため、処理は行われません。この場合、数値を処理した後もpdは0のままであり、aを出力する必要があることを示しています
'|'
(ただし、outがゼロ以外の場合は、ステージ2または3にいるためです)。
- すべての数値を処理した後、outがゼロ以外の場合、改行を出力します。ステージ2または3で改行を出力しないように、out変数が必要なことに注意してください。
- * q = -1:前と同じですが、最初の2つの数値の両方で * pが-2であるため、両方がaを出力します
'.'
(3番目の出力は'|'
以前のようにaを出力します)。
- * Q = 0:とき * qは 0で、この手段は、「私たちはものの場所にいる場合の行そうでない場合は、出力を何もしない
'|'
のにかかわらず、 * P」。このようにして、数字間のパディングを取得します。
次にqをインクリメントして次の場所である10の場所に移動し、そこで* qをインクリメントします。ステージ2の開始時には、テープは次のようになります。
次に、前と同じようにステージ2を実行します。これは、この場所のすべての数字から2を事実上減算し、最大桁を示す* r2の単項数を残します。前の単項数はそのままにして、テープを左に拡張し続けます。「クリーンアップ」するために余分なコードが必要になるだけです。完了して* qをインクリメントすると、ステージ3の開始時にテープは次のようになります。
実際、これは嘘です。以前、*(r − 4)を1 に設定したと言ったのを思い出してください。では、その理由を説明します。このような場合は、最大桁が実際に0であるため、この場所のすべての桁は0です。上記のラベルのない矢印で示される*(r − 4)を1に設定すると、単項数が1だけ拡張されます。ただし、この特別な場合のみ。このように、最大桁が1であるかのようにふりをします。これは、1行余分に出力することを意味します。
ステージ3(現在の場所のすべての桁から最大桁を引く)の後、* qを負にする追加のステップを含めて、テープは次のようになります。前回、* pブロックで最大桁が-2で表されていましたが、今回は実際はすべてゼロであるため、すべてが-3ですが、最大桁が1であるかのように見せかけています。
ここで、* qが1に向かって進むにつれて何が起こるかを見てみましょう。
- とき* Q = -1、* Pの値が全てです-3、我々は出力を意味している
'|'
のと増分それらを。
- とき* Q = 0、我々出力
'|'
なぜなら、我々は常に何をすべきかというのとき* Q = 0、にかかわらず* P。
したがって、パイプの2つの行を取得します。
最後に、* qを自分の場所に移動します。これ':'
は、実際の数字が1以外の場合はs を出力する必要があるが、1の場合はs を出力する必要があるため、興味深いものになり'8'
ます。プログラムがどのように進行するかを見てみましょう。まず、ステージ2を開始するために* qをインクリメントします。
ステージ2(「最大桁値の計算」)の後、次のようにします。
ステージ3(「現在の場所のすべての桁から最大桁値を引く」)の後、テープは次のようになります。
では、* qの各反復を順番に見ていきましょう。
- * q = −2:
- 最初の数:すでに-2なので、aを出力します
':'
(q = -1 '.'
なのでaではなく)。
- 2番目の数値:-4で、a
'|'
を出力し、増分します。
- 3番目の数値:-3で、aを出力し
'|'
ます。ただし、今回は、インクリメントする代わりに、特別なケースがトリガーされます。唯一我々は最後の場所を(出力ている場合、Q = -1)、と我々は(そのために二最後の行にいる* Q = -2)、及び数字は、実際には1である(* P = -3) 、その後、代わり-2にそれをインクリメントで、我々はそれを設定-1。つまり、特別な値として-1を使用して、次の反復での'8'
代わりに出力する必要があることを示します':'
。
- * q = −1:
- 最初の数:すでに-2であるため、aを出力し
':'
ます。
- 2番目の数値:-3で、aを出力し
'|'
ます。* qが-2でなくなったため、特別な条件はトリガーされません。したがって、インクリメント。
- 3番目の数値:-1で、出力
'8'
。
- * q = 0:通常、
'|'
ここにsのパディング行を出力しますが、1の場所( q = -1)にいる特別な場合には、それをスキップします。
この後、qは0にインクリメントされ、大きなwhileループが終了します。
これで、入力のような202,100,1
仕組みがわかりました。ただし、まだカバーしていない特別なケースがもう1つあります。最後の場所を処理しているときに、* pが-3の場合1
、次の反復がを出力するように(-2にインクリメントする代わりに)-1に設定したことを覚えているかもしれません'8'
。これが機能するのは、* pが-3 である反復があり、それをインクリメントするか、-1に設定するかを決定するためです。1 桁の数字がすべて 0または1の場合、このような反復はありません。そのような場合、1のすべての* p値は-2 から始まります。-1に設定することを決定する機会はありません-3からインクリメントするのではなく。このため、ステージ3には別の特別なケーシング条件があります(「現在の場所のすべての数字から最大の数字を引く」)。すべての桁から最大桁値を引いた後(最大桁が-1になった時点)、もう一度デクリメントしますが、実際には次のような条件があります。
私たちが見ている数字は、この場所での最大桁に等しい場合(* P = -1)、そしてこの場所は、一の位(あるQ = -1)、および最大桁が1(ある*(R + 5)非常に長い左のみ5細胞)である時、すなわち単項ブロック、0 =は、だけにして我々は去る* Pを示すために-1のみの繰り返し出力を出力しなければならないのそれ'8'
。他のすべての場合では、もう一度デクリメントします。
できた 明けましておめでとうございます!
編集1(3183→3001):新年あけましておめでとうございます!変数p2とr2を完全に取り除きました!pは、数字の始まりと終わりを見つけ続けるために、今度は前後に競争しますが、コードの方が短いようです。私もq2を削除しようとしましたが、そのようにコードを短くすることはできませんでした。
また、whileループの最後の値を再利用するなど、読み取り不可能な一般的なゴルフトリックを適用できる場所をいくつか見つけました。例を挙げると、
while *(++p) { 1 } // just increment p until *p is 0; the 1 is a noop
if (pd) { x } else { y } // where pd is a variable
のような方法でそれを書くことで'""""
、'"""
(最初に、次に2番目に)、(定数1)を保存できます
if (while *(++p) { pd }) { x } else { y }
もちろん、これは、whileループが少なくとも1回実行されることがわかっている場合にのみ機能しますが、実行される場合、戻り値はpdなので、ifの条件として使用できます。