この投稿の目的は<all languages>
、特定のものではなく、簡単に適用できるすべてのゴルフのヒントを収集することです。
そのロジックを大半の言語に適用できるという回答のみを投稿する
回答ごとに1つのヒントをお願いします
<all languages>
...
この投稿の目的は<all languages>
、特定のものではなく、簡単に適用できるすべてのゴルフのヒントを収集することです。
そのロジックを大半の言語に適用できるという回答のみを投稿する
回答ごとに1つのヒントをお願いします
<all languages>
...
回答:
通常、2つの結果ループまたは2つのネストされたループを1つにマージできます。
前:
for (i=0; i<a; i++) foo();
for (i=0; i<b; i++) bar();
後:
for (i=0; i<a+b; i++) i<a?foo():bar();
foo
呼び出されたa
回数、bar
と呼ばれるb
時代。これは、「後」では、ループがa+b
最初のa
呼び出しfoo
、次の呼び出しの順に実行されるためbar
です。
for(y=0;y<Y;++y)for(x=0;x<X;++x)
多くの場合、for(i=0;i<X*Y;++i)
でx
置き換えられ、i%X
でy
置き換えられi/X
ます。
明白なことに言及するだけです:
ゴルフ(特にプログラムが長くなるより難しい問題)を頻繁に行う場合、他の基本的なオプションを試すことなく、最初に選択したパスに固執することがあります。もちろん、一度に1行または数行のマイクロゴルフ、または全体的なアイデアの一部をマイクロゴルフすることもできますが、多くの場合、まったく異なる解決策を試してはいけません。
これはHitting 495(Kaprekar)で特に顕著であり、実際のアルゴリズムから逸脱し、同じ結果を得るために適用できるパターンを探すことが多くの言語(Jではなく)で短縮されました。
欠点は、同じことをおそらく半ダース解決することです。ただし、HQ9 +以外の実際にはすべての言語で機能します(Hello Worldを出力する別の方法を見つけるのは少し無駄です)。
コードがさまざまな入力を処理する必要がある場合は、包括的なテストを作成し、それらをすべて非常に迅速に簡単に実行できるようにします。これにより、危険な変換を一度に1歩ずつ実行できます。ゴルフは、ひねくれた意図を持ったリファクタリングのようになります。
例えば、場合A
やB
ブールとあなたの言語ですが、ある程度の数字のようなブール値を扱い、A and (not B)
とA>B
等価です。Pythonの例
if A and not B:
foo()
次と同じです:
if A>B:
foo()
B>A or foo()
これは、これを表現するさらに短い方法であり、ブール式の遅延評価を利用して、必要なときにのみ計算するようにします。
B>A or foo
評価されますfoo
場合はB==A
これが私たちが望むものではありません。(そう?)
代わりにx=1
、既に1に等しいものを探してみてください。
たとえば、関数の戻り値:printf("..");x=0;
-> x=!printf("..");
。常に否定できるため、または必要なのは正しい真理値だけであるため(そして、それが1か19かは気にしない)、0で最も簡単です。
~
のためにx+1
とx-1
このトリックは、単項のビットごとの否定演算子~
と単項の通常の否定演算子を持つ言語に適用されます-
。
プログラムに式が含まれている場合-x-1
、~x
バイトを節約するために式を置き換えることができます。これはあまり頻繁には発生しませんが、-
両方の式を否定()した場合に何が起こるかを見てください:x+1
等しい-~x
!同様に、x-1
等しいです~-x
。(チルダが指す方向を考えてください:右が+
、左が-
。)
これは便利です。なぜなら、これらの演算子があると考えることができるすべての言語で、ほとんどの演算子よりも優先順位が高いからです。これにより、括弧を節約できます。ここで4バイトを保存する方法をご覧ください。
(x+1)*(y-1) ==> -~x*~-y
あなたの言語の空白の規則を知ってください。一部の句読点またはその他の文字は、周囲の空白を必要としない場合があります。次のBourneシェル関数を検討してください。
f () { echo a; echo b; }
Bourneシェルで();
は、メタキャラクターであり、空白を囲む必要はありません。ただし、{}
単語であり、メタ文字の隣にない限り空白が必要です。隣の4つのスペースでゴルフをすることができます();
が、{
との間のスペースを維持する必要がありecho
ます。
f(){ echo a;echo b;}
Common LispとPicoLisp、()
メタ文字です。次のコードを検討して、2つの数値の平均を見つけます。
(/ (+ a b) 2)
2つのスペースでゴルフを楽しめます。
(/(+ a b)2)
一部の言語には、空白に関する奇妙で微妙な規則があります。整数の行の合計と積を出力するこのRubyプログラムを検討してください。
#!ruby -an
i=$F.map &:to_i
puts"#{i.reduce &:+} #{i.reduce &:*}"
それぞれの&
前にスペースが必要です。Rubyでは、ブロックパラメータを渡す場所をi=$F.map &:to_i
意味します。しかし、意味どこバイナリ演算子です。i=$F.map(&:to_i)
&
i=$F.map&:to_i
i=$F.map.&(:to_i)
&
この奇妙さは、あいまいな句読点を使用するPerlやRubyなどの言語で発生します。疑わしい場合は、REPLを使用するか、短いプログラムを作成して空白ルールをテストしてください。
52個あります。それらをすべて使用してください!異なるアプローチを試して、長さを比較することを恐れないでください。言語と利用可能な特定のショートカット/ライブラリ機能を知ってください。
$
、_
識別子として使用できます。
@
T-SQLの有効な変数名です@a
。代わりに使用します。
条件演算子
bool ? condition_true : condition_false
IF 文よりも、文字的に賢明です。
if(a>b){r=a;}else{r=b;}
として書くことができます
r=a>b?a:b;
a&&b||c
代わりに使用できます。少し長くなりますが、それでも短いですif
。
Iff
ありますが、それは関数ですが、すべての引数の評価の対象となります。
if(a ? b : c)
a&&b||c
返すことができることc
に注意してください。falseのa
場合b
は少しエッジケースですが、それを忘れないでください^^
説明を書くと、コードの各部分をもう一度徹底的に調べ、特定のパッセージを書く際の考えと選択を明確にする必要があります。そうすることで、いくつかのバイトを節約する可能性のあるさまざまなアプローチが可能であること、または必ずしも当てはまらない仮定を無意識に行ったことに気付くかもしれません。
このヒントは、アルゴリズムの選択に疑問を投げかけ、まったく新しいものを試すことに似ています。しかし、各部分がどのように機能するかを実際に書き留めるステップは、代替案を認識するために時々非常に重要であることがわかりました。
ボーナスとして、説明を含む回答は他のユーザーにとってより興味深いものであるため、支持される可能性が高くなります。
簡単なように聞こえますが、注意することで、実際に何もしないことでいくつかのキャラクターを「保存」できる場合があります。
Windowsを使用している場合は、入力することができる\r\n
だけではなく\r
、または\n
あなたがリターンを打つとき-行あたりの余分なバイトを追加します!制御文字を回して、これを行っていないことを再確認してください。
メモ帳で++あなたはすべて変換することができます\r\n
だけで行末までを\r
に行くことによってEdit > EOL Conversion > UNIX/OSX Format
。
また、文字カウントに末尾の空白を含めないでください!コードの一番下の行の改行も重要ではないため、カウントする必要もありません。
コードゴルフは、質問(他の設定で暗示されている場合でも、質問されるものとされないもの)を理解することと同じくらい、質問されるものだけを満たせるコードを生成することと同じです。
明示的に要求されたもの以外の入力を処理する必要はありません。いくつかのテストケースがあり、一般的な要件がない場合、コードはそれらのケースでのみ機能します。等。
ちょっとしたケースかもしれませんが、時には役に立つかもしれません。これは、m = 2 n -1が適用されるすべての数値の右端nビットが1に設定されているという事実に依存しています。
だから、7 10 == 00000111 2、15 10 == 00001111 2、31 10 == 00011111 2など。
トリックですx&~m
。これは、いつでもtrueを返しますx
されていない 0との間m
(両端を含む)、およびそれ以外の場合はfalse。次の最短の等価式:から6バイトを節約しますx>=0&&x<=m
が、明らかにm
2 n -1を満たす場合にのみ機能します。
新しい変数の代わりに関数パラメーターを再利用する
main(i){...
変数1割り当てを行います。2文字が保存され
数字を保存するよりも大きい/小さい:
//use:
if(n>9){A}else{B}
//instead of:
if(n<10){B}else{A}
ちょうどからコードを交換することを忘れないでくださいif
とelse
、彼らはまったく同じことを行う(あるいは不平等の側面を切り替える)されます!
注:これは、10の累乗とその負数で適用できます。...-100, -10, 10, 100...
if(n>99999)
vsif(n<1e5)
ハードコードされた整数値に対してチェックするときは、可能であれば代わりにandを使用>
します。たとえば、<
>=
<=
if(x>24&&x<51)
使用するより2バイト短い
if(x>=25&&x<=50)
<1
の代わりに==0
ゼロチェック(またはとして>0
の代わりに、!=0
ミラーリングされたチェックのため)。
x
整数であることに関するメモを追加してはいけませんか?
ループを実行してブールチェックの1つまたは複数のインスタンスをチェックする場合、最初の真の値でループを終了するより効率的なプログラムになる可能性があります。ただし、ブレークを削除し、すべての繰り返しをループ処理することで、コードを短くすることができます。
int main() {
bool m = false;
int n = 1000;
for (int i = 0; i < n; i++) {
if (i >= 100) {
m = true;
break; // remove this line
}
}
return 0;
}
if
次の場合でも、ステートメントを簡略化できますm|=i>=100
。(また、この場合にi>=100
to i>99
を単純化することもできますが、ここではあまり関係ありません)
ほとんどの言語には、ある種のトークンの周りで文字列を文字列の配列に分割する方法があります。これは、文字列ごとの余分なオーバーヘッドが(少なくとも)2つの文字列区切り文字ではなく、1文字のトークンの1つのコピーになるため、長さが言語依存のしきい値に達すると、必然的に配列リテラルよりも短くなります。
例:GolfScript
["Foo""Bar""Baz""Quux"] # 23 chars
になる
"Foo
Bar
Baz
Quux"n/ # 20 chars
一部の言語では、しきい値は1つのストリングと同じくらい低くなっています。たとえば、Javaで、
new String[]{"Foo"} // 19 chars
になる
"Foo".split("~") // 16 chars
%w{Foo Bar Baz Quux}
。
qw(Foo Bar Baz Quux)
ます。文字列のリストになります。
複数の式を組み合わせる場合は、言語の演算子優先順位表を確認して、括弧を保存するために順序を変更できるかどうかを確認してください。
例:
(a&b)&&c
、括弧を必要a&b&&c
と(a*b)+c
しません。そうではありません。a+(b<<c)
として書き換えることができますa+b*2**c
。c
が、小さな整数リテラル(<14)の場合は保存されます。a<b&&c<d
とa<b&c<d
(あなたは短絡評価を必要としない場合)forループ内にX
ステートメントがある場合、2番目のセミコロンの後にforループ内でステートメントを移動して、3バイトを節約できます。(コンマを使用してステートメントを分離します){
}
X-1
(
)
for(blah;blah;HERE)
,
の代わりに
for(int i=0;i<9;){s+=s.length();println(i++);}
ステートメントの一方をforループの(
中括弧に)
移動し、他方を除外することができます
for(int i=0;i<9;println(i++))s+=s.length();
そして3バイト節約します(@ETHProductionsのおかげでもう1バイト節約されました)
簡単に言えば、
の代わりに
for(blah;blah;){blah 1;blah 2;...;blah X}
あなたはこれで終わるので、文を移動します
for(blah;blah;blah 2,...,blah X)blah 1;
そして3バイト節約
for
が最後のステートメントである場合は、;
オプションになります
~
のためにa-b-1
とa+b+1
→ に関する@Lynnの提案に加えて、そして→x+1
-~x
x-1
~-x
、ゴルフa-b-1
やゴルフもできますa+b+1
。
a-b-1 // 5 bytes
a+~b // 4 bytes
a+b+1 // 5 bytes
a-~b // 4 bytes
それほど頻繁に使用しないヒントのように見えるかもしれませんが、使用する~x
代わりに使用する-x-1
ことはあまりありませんが、ここでは有用なヒントとして十分に使用しています。特に配列のインデックス付けでは、場合によっては上記を使用できます。
ands(またはors、この場合は単に 'all'を 'any'に置き換えてください)によって連鎖された条件の長い連なりを絞ろうとするときに思いついた簡単なトリック。
例えば:
if a>0 and a<10 and a+b==4 and a+3<1:
になる
if all([a>0,a<10,a+b==4,a+3<1]):
all(array-of-Booleans)
組み込まれていますか?
[a>0,a<10,a+b==4,a+3<1].all?
if 10>a>0 and a+b==4>1>a+3:
どの最適化がコンパイラによって保証され、どの最適化レベルで行われるかを確認し、それらを自由に使用してください。また、パフォーマンスが懸念事項ではない場合でも、最適化を有効にしてテストし、コンパイラフラグがなくてもコードは技術的に有効であるため、1文字のみを割引できます。
次のHaskell関数を考慮して2 ^ nを計算します(Haskellには既に1つまたは3つのべき乗演算子が組み込まれているという事実を無視します)(23文字):
p 0=1;p x=p(x-1)+p(x-1)
問題は-ものすごく遅い、指数関数的な時間で実行されることです。これにより、コードがテスト不能になったり、質問で指定されたパフォーマンスの制約が満たされないことがあります。関数の繰り返し呼び出し(25文字)を避けるために、一時変数またはすぐに呼び出される関数リテラルを使用したくなるかもしれません。
p 0=1;p x=(\y->y+y)$p$x-1
しかし、コンパイラは既にあなたのためにそれを行うことができます、あなたはただ-O
コンパイラフラグとして設定する必要があります!サイトごとに少数の余分な文字を費やして共通の部分式を手動で削除する代わりに、プログラム全体で合計1文字または2文字の基本的な最適化を行うようコンパイラーに指示します。
p(x-1)*2
か?
たぶん多少明らかですが...
代入演算子は値を返すことに注意してください!
たとえば、yをxに追加し、xが何かより大きいかどうかを確認する場合は、次のようにします。
if(25<x+=y)
の代わりに
x+=y;if(x>25)
または、文字列をトリミングした後、文字列の長さを検索することもできます。
strlen(s=trim(s))
のではなく
s=trim(s);strlen(s)
a = (b=c)+1;
に設定b
しc
、次にに設定a
しb+1
ます。
a=1+b=c
。また、PHPとJavaScriptをリストに追加できます。
=
ので、オペレータに右よりも左に高い優先順位を1+x=2
有効であると評価3
これは特にポリグロットに役立ちますが、他の課題にも適用できます。場合によっては、コンパイラのバグがバイトをたたき飛ばしたり、実装のバグがいくつかの文字を保存したり、本当に最先端の機能がスコアを改善したりすることがあります。