符号なし16ビット整数の1の数をカウントします


24

符号なし16ビット整数の1の数をカウントするステートメントを作成します。

たとえば、入力がの場合、16ビットの2進数が6であるため1337、結果は6になります。613370000010100111001


2
ヒント:数字の一部の桁がmod 9の数字と一致するように、ビットの一部はmod 1の数字と等しくなります
。– PyRulez

8
@PyRulez任意の数は1を法とするゼロです。-
トーマス

1
こんにちは、間違った回答を承認済みの回答として選択しました(デフォルトでは、最初の投稿のタイブレーカーロジック)。
オプティマイザー

4
@トーマス私はそれが有用なヒントだと言ったことはありません。
PyRulez

2
ほとんどの回答が投稿された後、なぜこの質問に賛成票が集まりますか 有権者はコメントに理由を明記してください。(組み込みを使用しているため)標準の抜け穴に準拠しないes1024の(非常に巧妙な)4バイトの回答が受け入れられる場合、これが理由であると述べてください。そうでなければ、それは何ですか?
レベルリバーセント

回答:


37

80386マシンコード、4バイト

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

これは32ビットまたは16ビット(実モードまたは保護モード)モードですか?
FUZxxl

2
提供@FUZxxlアセンブリは交換が、16ビットのためのものであるaxcxしてeaxecx32ビットに変更されます。バイトコードはどちらでも同じです。
es1024

1
@ es1024バイトコードは、これが16ビットモードでコンパイルされ、32ビットバージョンが32ビットモードでコンパイルされた場合、同じです。
コールジョンソン

2
popcntは組み込みであり、標準の抜け穴のファウルに陥っていませんか?ただし、2番目のソリューションはまだ信用できます。
アルキミスト

5
マシンコードの長さを主張するとき、タイトルは「80386 Assembler」ではなく「80386 Machine Code」ではないでしょうか?
ケビンリード

14

Python 2、17バイト

bin(s).count('1')

bin組み込みの整数をバイナリ文字列に変換戻ります。次に、1数字をカウントします。

>>> s=1337
>>> bin(s)
'0b10100111001'
>>> bin(s).count('1')
6

11

J(5文字)

Jには明示的な型はありません。これはすべての整数に対して正しいことを行います。

+/@#:
  • +/ 合計
  • @
  • #: ベース2表現

11

C、21

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;


1
@ edc65ので、結局のところ、私は車輪を再発明しました。を省略して、少なくとも2バイトを節約しました{}。これはとても簡単な作業で、誰かがすでに思いついたのには驚かないはずです。
レベルリバーセント

「1960年に最初に公開された」、印象的。
mbomb007

素朴なアルゴリズムの修正:for(n=0;x;x/=2)n+=x&1;
Helios

1
@nmxprime OPはunsigned intを要求します。32ビットコンパイラで-7 = 11111111 11111111 11111111 11111001の場合、高速アルゴリズムでは30になりますが、これは正しいです。単純なアルゴリズムの場合、-7、-7 / 2 = -3、-3 / 2 = -1、-1 / 2 = 0を反復処理します。それは間違った答えを与えます。x / = 2をx >> = 1に変更すると、一部のコンパイラで正しい答えが得られる場合がありますが、負の数値の>>の空ビットに1または0をシフトするかどうかはCで定義されていません。1をシフトインするコンパイラーは、無限ループに入ります。回避策は、xを符号なし整数として定義することです。次に、x = -7は(1 << 32)-7 = 4294967289をxにロードします。
レベルリバーセント

5

ゼリー、非競合

言語はチャレンジが投稿された後に作成されたため、この回答は競合しません。

2バイト:

BS

Jellyは、@ Dennisによって作成された新しい言語で、Jのような構文を備えています。

         implicit: function of command-line arguments
B        Binary digits as list
 S       Sum

ここで試してみてください


4

Pyth、4バイト

sjQ2

プログラムは、ハミングの重みがSTDINにある番号を取得します。


4

ジュリア、29 27 19バイト

n->sum(digits(n,2))

これにより、単一の引数を受け入れる匿名関数が作成されますn。それを使用するには、それをのようなものに割り当て、のようf=n->...に呼び出しますf(1337)

このdigits()関数は、2つの引数で呼び出されると、指定されたベースの入力の数字の配列を返します。したがってdigits(n, 2)、の2進数を返しますn。配列の合計を取得すると、のバイナリ表現に1の数がありnます。


これはもっと短くすることができます:ジュリアには機能がありますcount_ones
アンドリューは、Reinstate Monica

@AndrewPiliser:提案に感謝しますが、タスクを正確に達成する組み込み関数は標準の抜け穴と見なされ、明示的に禁止されていない場合は眉をひそめます。
アレックスA.


3

ジョー、4バイト

/+Ba

これは匿名関数です。Ba数値のバイナリ表現を与え、/+それを合計します。

   (/+Ba)13
3
   (/+Ba)500
6

3

R、24バイト

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()))同じではないでしょうか?
-seequ

@Sieg:残念ながら、から返されるsum()typeの入力を受け取ることはできません。rawintToBits()
アレックスA.

それは私にとって本当に奇妙です。
seequ

1
@ジーグ:ええ、それも私にとって奇妙です。しかたがない。すべてのポークチョップが完璧であれば、ホットドッグはありません。
アレックスA.

そして、それはこれまでで最も奇妙な比phorです。
seequ


3

4番目、48 49バイト

: c ?dup if dup 1- and recurse 1+ then ;
0 1337 c

実際の機能が必要な場合、2行目は

: c 0 swap c ;

「1337 c」で呼び出します。Forthの比較的冗長なコントロールワードは、これを困難なものにします(実際、これらは非常に困難です)。

編集:私の以前のバージョンは、負の数を正しく処理しませんでした。



3

ES6(34 22 21バイト):

これは、もう少し短くできる単純な再帰関数です。少し時間がかかり、再び実行されます。

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(39バイト):

両方の機能を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に適合させ、再帰的に多くの短縮を行いました!


1
これは、より小さな 'reguar' j​​avascript関数です。関数B(n、x){for(x = 0; n; n >> = 1)x + = n&1; return x}
wolfhammer

@ user1455003 LOTまたはご提案ありがとうございます!私はそれを使用し、ES6に適合させ、大幅に短縮しました。ありがとうございました!
イスマエルミゲル

どういたしまして!私はあなたがそれで何をしたかが好きです。再帰を使用すると、通常のjavascriptは39になります!関数B(n){return n?(1&n)+ B(n >> 1):0}
ウルフハンマー

@ user1455003必要に応じて、ES5パーツを編集し、ゴルフバージョンにバイトカウントを追加できます。(編集で評判を得られると思います)。
イスマエルミゲル

@ user81655すごい!できます!!!大いに感謝する!これはもっと短くできることを本当に知っていた
イスマエルミゲル

2

> <>(魚)、24バイト+ 2 = 26

0$11.>~n;
2,:?!^:2%:{+}-

プログラムは、mod 2を繰り返し、入力数がゼロになるまで減算して除算し、mod 2の合計を出力します。

-vフラグでテストします。例えば

py -3 fish.py ones.fish -v 1337

16ビット整数の場合、コードポイント入力はおそらく適切ではありません。(-vフラグバージョンは引き続き動作します。)
randomra

@randomraくそー、あなたは正しい。Unicode入力は機能しますが、16ビットは範囲外の数桁です
...-Sp3000

2

PHP(38バイト):

これは、ES6の回答と同じアプローチを使用します

<?=count(split(1,decbin($_GET[n])))-1;

これは完全なコードです。ファイルに配置し、パラメータを使用してブラウザからアクセスするだけですn=<number>

PHP <4.2(32バイト):

これは少し短いです:

<?=count(split(1,decbin($n)))-1;

PHP4.2からPHP5.4(それまでに削除されました)までデフォルトでディレクティブregister_globalsが設定さOffれていたため、これはPHP <4.2でのみ確実に機能します。

php.iniファイルを作成する場合register_globals=On、これは機能します。

コードを使用するには、ブラウザを使用してPOSTまたはGETでファイルにアクセスします。

@ViniciusMonteiroの提案(38/45バイト):

彼は、関数の非常に興味深い使用法を持つ2つの本当に良い提案をしましたarray_sum

38バイト:

<?=array_sum(str_split(decbin(1337)));

45バイト:

<?=array_sum(preg_split('//', decbin(1337)));

これは本当に素晴らしいアイデアであり、36バイトの長さになるようにもう少し短くすることができます。

<?=array_sum(split(1,decbin(1337)));

2
または、echo array_sum(str_split(decbin(1337)));を使用できます。エコーも使用できますarray_sum(preg_split( '//'、decbin(1337)));
ビニシウスモンテイロ

1
@ViniciusMonteiroご提案ありがとうございます。本当に気に入りました!答えに追加しました。
イスマエルミゲル

<?=substr_count(decbin(1337),"1");(34バイト)を使用して4バイトを
獲得する

1
@Cogiceroそして、引用符を削除することでさらに節約できます<?=substr_count(decbin(1337),1);。これは合計32バイトです。それが十分に異なるコードであることを考えると、あなた自身の答えとしてそれを投稿しませんか?私はそれを賛成します!
イスマエルミゲル

@Cogicero It'sは2つだけあなたがパラメータ化を使用する場合は、短いバイト:<?=substr_count(decbin($argv[1]),1);(または$_GET[n]、36バイト)
タイタス


2

Japt、3バイト(非競合)

¢¬x

ここで試してみてください。


男、私は何らかの理由でそれらの日付を見たことがない。
ママファンロール

1
ハハ、Japtは最短です:ところで、¢o1 lうまくいきます。別の興味深いアプローチは-¢¬r-0; ¢¬2進数の配列に分割しr-0、0から始めて減算により減少し-、結果を否定して正にします。
ETHproductions

昨夜の時点で、を使用できるようになりました¢¬x
ETHproductions

2

蜜蝋31 27バイト

競合しない答え。蜜蝋はこの課題よりも新しいものです。

このソリューションは、「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リポジトリ蜜蝋インタプリタ、言語仕様と例を含みます。


1

Java、17バイト

以下のための作品byteshortchar、とint。ラムダとして使用します。

Integer::bitCount

ここでテスト

ビルトインを使用しない場合:

42バイト

s->{int c=0;for(;s!=0;c++)s&=s-1;return c}

ここでテスト


6
これは標準の抜け穴です。必要なことを正確に行う組み込み関数は禁止されています。
-FUZxxl

@FUZxxl OPは標準の抜け穴を決して禁止しませんでした
コールジョンソン


6
@FUZxxl es1024はデフォルトで標準の抜け穴が閉じられるのは正しいですが、組み込み関数を使用することは、現在、投票の内訳が+ 43 / -26の場合、受け入れられる抜け穴ではありません。
マーティンエンダー

1

クリップ、6

2つの方法:

cb2nx1

これは、要件の簡単な翻訳です:数値の基数2表現の1のカウント。

r+`b2n

別の方法。base-2表現の桁の合計を取得します。






1

PowerShell(51バイト)

"$([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
AdmBorkBork

1

Clojure、42バイト

#(count(filter #{\1}(Long/toString % 2)))

右から左に読んで、バイナリ文字列に変換し、文字のシーケンスに変換し、1s でフィルター処理して、持っている数を数えます。

EDITED ジークからの助けを借りて


42:#(count(filter #{\1}(Integer/toString% 2)))
seequ

もう1つのキャラクターが必要です#(count(filter #{\1}(Integer/toString % 2)))
ニールマッソン

いいえ、しません。:)
seequ

これは私がそれを試みたときに私が得たものである:CompilerException java.lang.IllegalArgumentException: No matching method: toString_PERCENT_
ニール・マッソン

Try Clojureでテストしました。どうやらページは突然認識しませんInteger/toString。しかし、それは数秒前に機能しました。
seequ

1

Haskell 42文字

t 0=[]
t n=t(quot n 2)++[rem n 2]
f=sum.t

f :: Integer -> Integer
対話型インタープリターから関数の使用を宣言するf <number>main=print$f <number>、ファイルの最後に行を追加します。


あなたは直接加算することによってバイトを大幅に節約することができますrem n 2秒の代わりに、それのリストを作成し、使用しないでdiv代わりにquott 0=0 t n=t(div n 2)+rem n 2なし- fもう。
nimi

1

Matlab、13バイト

de2bi2進数を表すゼロと1のベクトルを作成し、sumすべてのエントリの合計を返します。

sum(de2bi(n))

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.