符号なし16ビット整数の1の数をカウントするステートメントを作成します。
たとえば、入力がの場合、16ビットの2進数が6であるため1337
、結果は6になります。6
1337
0000010100111001
符号なし16ビット整数の1の数をカウントするステートメントを作成します。
たとえば、入力がの場合、16ビットの2進数が6であるため1337
、結果は6になります。6
1337
0000010100111001
回答:
F3 0F B8 C1
これは整数inを取り、cx
カウントin を出力しますax
。
popcnt ax, cx ; F3 0F B8 C1
そして、これはPOPCNTを使用しない11 10バイトのソリューションです:
31 C0 D1 E9 10 E0 85 C9 75 F8
次と同等です:
xor ax, ax ; 31 C0 Set ax to 0
shr cx, 1 ; D1 E9 Shift cx to the right by 1 (cx >> 1)
adc al, ah ; 10 E0 al += (ah = 0) + (cf = rightmost bit before shifting)
test cx, cx ; 85 C9 Check if cx == 0
jnz $-6 ; 75 F8 Jump up to shr cx, 1 if not
ax
とcx
してeax
とecx
32ビットに変更されます。バイトコードはどちらでも同じです。
for(n=0;x;n++)x&=x-1;
あなたは「いくつかのステートメントを書く」(「関数」ではない)と言ったので、数字はで提供されx
、1の数はで返されると仮定しましたn
。初期化する必要がない場合n
は、3バイト節約できます。
これは、x&x-1
何かが2のべき乗であるかどうかをテストするための有名な表現の適応です(ある場合はfalse、そうでない場合はtrue)。
ここでは、質問の番号1337で動作しています。1を引くと、最下位1ビットとすべてのゼロが右に反転します。
0000010100111001 & 0000010100111000 = 0000010100111000
0000010100111000 & 0000010100110111 = 0000010100110000
0000010100110000 & 0000010100101111 = 0000010100100000
0000010100100000 & 0000010100011111 = 0000010100000000
0000010100000000 & 0000010011111111 = 0000010000000000
0000010000000000 & 0000001111111111 = 0000000000000000
編集:完全を期すために、ここに1バイト長い(そしてかなり遅い)素朴なアルゴリズムがあります。
for(n=0;x;x/=2)n+=x&1;
{}
。これはとても簡単な作業で、誰かがすでに思いついたのには驚かないはずです。
for(n=0;x;x/=2)n+=x&1;
n->sum(digits(n,2))
これにより、単一の引数を受け入れる匿名関数が作成されますn
。それを使用するには、それをのようなものに割り当て、のようf=n->...
に呼び出しますf(1337)
。
このdigits()
関数は、2つの引数で呼び出されると、指定されたベースの入力の数字の配列を返します。したがってdigits(n, 2)
、の2進数を返しますn
。配列の合計を取得すると、のバイナリ表現に1の数がありn
ます。
count_ones
ri2b:+
ri "Read the input and convert it to integer";
2b "Convert the integer into base 2 format";
:+ "Sum the digits of base 2 form";
sum(intToBits(scan())>0)
scan()
stdinから入力を読み取ります。
intToBits()
整数を受け取り、raw
入力のバイナリ表現のゼロと1を含む型のベクトルを返します。
intToBits(scan())>0
論理ベクトルを返します。各要素はTRUE
、対応するバイナリベクトル要素が1である場合(すべての要素が0または1および1> 0であるため)、それ以外の場合FALSE
です。
Rでは、論理ベクトルをTRUE
合計して要素の数を取得できるため、上記のように論理ベクトルを合計すると、必要なものが得られます。
入力を直接sum()
処理できないraw
ため、論理を使用した回避策に注意してください。
sum(intToBits(scan()))
同じではないでしょうか?
sum()
typeの入力を受け取ることはできません。raw
intToBits()
私を思い出させてくれたalephalphaに感謝しDigitCount
ます。
DigitCount[#,2,1]&
これは、もう少し短くできる単純な再帰関数です。少し時間がかかり、再び実行されます。
B=n=>n&&(1&n)+B(n>>1)
http://www.es6fiddle.net/imt5ilve/で試してみてください(のvar
ために必要です'use strict';
)。
私は魚を倒したとは信じられない!
古いもの:
n=>n.toString(2).split(1).length-1
両方の機能をES5に簡単に適合させることができます。
function B(n){return n?(1&n)+B(n>>1):0}
//ungolfed:
function B(number)
{
if( number > 0 )
{
//arguments.callee points to the function itself
return (number & 1) + arguments.callee( number >> 1 );
}
else
{
return 0;
}
}
古いもの:
function(n){return n.toString(2).split(1).length-1}
@ user1455003は私に本当に素晴らしいアイデアを与えてくれました。
function B(n,x){for(x=0;n;n>>=1)x+=n&1;return x}
私はそれをES6に適合させ、再帰的に多くの短縮を行いました!
0$11.>~n;
2,:?!^:2%:{+}-
プログラムは、mod 2を繰り返し、入力数がゼロになるまで減算して除算し、mod 2の合計を出力します。
-v
フラグでテストします。例えば
py -3 fish.py ones.fish -v 1337
-v
フラグバージョンは引き続き動作します。)
<?=count(split(1,decbin($_GET[n])))-1;
これは完全なコードです。ファイルに配置し、パラメータを使用してブラウザからアクセスするだけですn=<number>
。
これは少し短いです:
<?=count(split(1,decbin($n)))-1;
PHP4.2からPHP5.4(それまでに削除されました)までデフォルトでディレクティブregister_globals
が設定さOff
れていたため、これはPHP <4.2でのみ確実に機能します。
でphp.ini
ファイルを作成する場合register_globals=On
、これは機能します。
コードを使用するには、ブラウザを使用してPOSTまたはGETでファイルにアクセスします。
彼は、関数の非常に興味深い使用法を持つ2つの本当に良い提案をしましたarray_sum
:
38バイト:
<?=array_sum(str_split(decbin(1337)));
45バイト:
<?=array_sum(preg_split('//', decbin(1337)));
これは本当に素晴らしいアイデアであり、36バイトの長さになるようにもう少し短くすることができます。
<?=array_sum(split(1,decbin(1337)));
<?=substr_count(decbin(1337),"1");
(34バイト)を使用して4バイトを
<?=substr_count(decbin(1337),1);
。これは合計32バイトです。それが十分に異なるコードであることを考えると、あなた自身の答えとしてそれを投稿しませんか?私はそれを賛成します!
<?=substr_count(decbin($argv[1]),1);
(または$_GET[n]
、36バイト)
¢o1 l
うまくいきます。別の興味深いアプローチは-¢¬r-0
; ¢¬
2進数の配列に分割しr-0
、0から始めて減算により減少し-
、結果を否定して正にします。
¢¬x
。
競合しない答え。蜜蝋はこの課題よりも新しいものです。
このソリューションは、「Bit Twiddling Hacks」ウェブサイトから設定されたビットをカウントするBrian Kheriganの方法を使用します。
ループを実行し、ビットカウントをインクリメントし、while number=number&(number-1)
まで繰り返しnumber = 0
ます。解決策は、ビットが設定されている回数だけループを通過します。
いくつかの命令を並べ替えることで、4バイトを削ることができました。ソースコードと説明の両方が更新されました:
pT_
>"p~0+M~p
d~0~@P@&<
{@<
説明:
pT_ generate IP, input Integer, redirect
>" if top lstack value > 0 jump next instruction,
otherwise continue at next instruction
p redirect if top lstack value=0 (see below)
~ flip top and 2nd lstack values
0+ set top lstack value to 0, set top=top+2nd
M decrement top lstack value
~ flip top and 2nd lstack values
p redirect to lower left
< redirect to left
& top=top&2nd
@ flip top and 3rd lstack values
@P increment top lstack value, flip top and 3rd values
~0~ flip top and 2nd values, set top=0, flip top and 2nd again
d redirect to upper left
>"p~0+M..... loop back
p if top lstack = 0 at " instruction (see above), redirect
0 set lstack top to zero (irrelevant instruction)
< redirect to the left
@ flip top and 3rd lstack values
{ output top lstack value as integer (bitcount)
クローン私のGitHubリポジトリ蜜蝋インタプリタ、言語仕様と例を含みます。
以下のための作品byte
、short
、char
、とint
。ラムダとして使用します。
Integer::bitCount
ビルトインを使用しない場合:
42バイト
s->{int c=0;for(;s!=0;c++)s&=s-1;return c}
"$([char[]][convert]::ToString($s,2)|%{"+$_"})"|iex
説明:
[convert]::ToString($s,2)
からバイナリ文字列表現を生成し$s
ます。
[char[]]
char配列としてキャストし、各charを列挙できるようにします。
|%{"+$_"}
各文字の前に+記号を付けて、結果のサブ式を
"$()"
暗黙的に呼び出します。パイプされた文字列を合計します(例: "+1 +0 +1 +1 +0 +1 +0 +0" = 4).ToString()
|iex
-join
演算子と暗黙的.ToString()
に45のバイトを達成するために[char[]][convert]::ToString($s,2)-join'+'|iex
...または、異なるアプローチの使用インラインとして-replace
オペレータに43のバイトを達成するために([convert]::ToString($s,2)-replace0).length
#(count(filter #{\1}(Long/toString % 2)))
右から左に読んで、バイナリ文字列に変換し、文字のシーケンスに変換し、1
s でフィルター処理して、持っている数を数えます。
EDITED ジークからの助けを借りて
#(count(filter #{\1}(Integer/toString% 2)))
#(count(filter #{\1}(Integer/toString % 2)))
CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
Integer/toString
。しかし、それは数秒前に機能しました。