セイロン、1431、764、697、571、547、538、501、493、467、451
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.hash.get(b))1});}
これはオリジナルであり、無料です。
Integer footprintCharacter(Integer b) {
return sum({0, for(i in 0..7) if(b.get(i)) 1 });
}
Integer footPrintString(String s) {
if(s == "test") {return 0;}
return sum({0, for(c in s) footprintCharacter(c.integer)});
}
shared void footprint() {
if(exists s = process.arguments[0]) {
print(footPrintString(s));
} else {
print("This program needs at least one parameter!");
}
}
これは、コマンドラインパラメーターから引数を取ります... process.argumentsは文字列の(空の場合もある)シーケンスであるため、いずれかを使用する前に、実際に存在するかどうかを確認する必要があります。それ以外の場合は、エラーメッセージを出力します(これは質問では不要であり、次のバージョンでは破棄されます)。
Ceylonのsum
関数は、満たす必要のあるタイプの要素の空でない Iterableを受け取ります。Summable
つまりplus
、Integerのようなメソッドを持っています。(各Summableタイプには独自のゼロがあるため、空のシーケンスでは機能せず、ランタイムはどちらが意味されるかを知る機会がありません。)
文字列の要素、または整数の1ビットは、空でない反復可能ではありません。したがって、ここでは、いくつかの要素を指定してイテレート可能オブジェクトを作成する機能を使用し、次に「理解」(ゼロ個以上の要素に評価されます)を指定します。そのため、文字の場合は1を追加しますが(対応するビットが設定されている場合のみ)、文字列の場合は文字の結果を追加します。(理解は、受信関数が実際に反復するときにのみ評価され、Iterableを構築するときは評価されません。)
これを縮小する方法を見てみましょう。まず、各関数は1か所でしか呼び出されないため、インライン化できます。また、上記のように、エラーメッセージを取り除きます。(764フットプリントポイント。)
shared void footprint() {
if (exists s = process.arguments[0]) {
if (s == "test") {
print(0);
} else {
print(sum({ 0, for (c in s) sum({ 0, for (i in 0..7) if (c.integer.get(i)) 1 }) }));
}
}
}
内側のネストは実際には必要ありませんsum
。これを1つの大きな理解にすることができます。(これにより、の37個のフットプリントポイントが節約さsum({0,})
れます。空白はさらに残りますが、いずれにしても最後には削除されます。)これは697です。
shared void footprint() {
if (exists s = process.arguments[0]) {
if (s == "test") {
print(0);
} else {
print(sum({ 0, for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
}
}
同様の原則を特別なケースの"test"
文字列に適用できます。その場合、結果は0(つまり、合計に寄与しない)であるため、合計の一部としてこれを行うことができます(ただし、条件を反転する必要があります) 。これにより、主にprint(0);
、ブレースといくつかのインデントスペースが節約され、フットプリントが571になります。
shared void footprint() {
if (exists s = process.arguments[0]) {
print(sum({ 0, if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
}
最初のについても同じことを行いますが、何if
もしないのではなく引数も与えないという副作用もあります0
。(少なくともここではそうなると思っていましたが、代わりに永遠のループでハングしているようです?奇妙なことです。)
shared void footprint() {
print(sum({ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
ここで関数の()
for を実際に省略できます。代替の関数呼び出し構文を使用します。これはの代わりにを使用し、反復可能な引数に内包表記を入力します。これにはフットプリント538があります。sum
{...}
()
shared void footprint() {
print(sum{ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 });
}
関数名footprint
(40)をp
(3)に置き換えると、さらに37ポイント節約され、501になります(Ceylon関数名は小文字で始まる必要があるため、ここでは3ポイント未満になりません)。
shared void p() {
print(sum{ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 });
}
変数名s
(5)およびc
(4)、i
(4)も最適ではありません。それらをa
(引数)、d
(数字?)、およびb
(ビットインデックス)に置き換えましょう。フットプリント493:
shared void p() {
print(sum{ 0, if (exists a = process.arguments[0]) if (a != "test") for (c in a) for (b in 0..7) if (c.integer.get(b)) 1 });
}
空白以外の最適化が残っていないので、不要な空白(各スペースに1ポイント、2つの改行ごとに2ポイント)を削除しましょう。
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.integer.get(b))1});}
APIを参照すると、Character.hashが実際にそのinteger
属性と同じ値を返すことがわかりました。しかし、30ではなく14ポイントしかないので、451になります!
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.hash.get(b))1});}