C # Premier 1 (de droite à gauche) en nombre binaire

10

J'essaie d'utiliser C # pour trouver l'index du premier 1 (de droite à gauche) dans la représentation binaire d'un nombre. Par exemple, puisque 100 en binaire est:

0b1100100

Le premier 1 est en troisième position à partir de la droite, il devrait donc donner 3.

234 devrait donner 2, 0 devrait donner 0, etc.

Voici ma solution actuelle:

k < 1 ? 0 :(int)Math.Log(k & -k, 2) + 1;

Est-ce que je peux raccourcir cela?

Eric Cepress
la source
1
L'astuce évidente est de supprimer vos espaces étrangers. Je vois 10 espaces que vous pourriez facilement supprimer.
James
Convert.ToString(k,2).IndexOf("1")est ce que vous voulez, ou quelque chose de similaire, un mauvais site.
Urne de poulpe magique du
14
@ close-voter - Pourquoi les votes serrés? Je pense que c'est une question de conseils sur le sujet . Ou y a-t-il eu des changements de règles que j'ai manqués à cet égard?
Digital Trauma

Réponses:

3

Si seulement les intrinsèques spécifiques à la machine pris en charge par C # ... Il existe une seule instruction qui peut le faire dans le langage d'assemblage x86, ainsi que sur la plupart des autres architectures de processeur. Vous auriez alors non seulement le code le plus court, mais probablement le plus rapide.

En fait, raccourcir ce code est un problème extrêmement ennuyeux par rapport à rendre ce code rapide . Il existe toutes sortes de solutions très soignées, efficaces et qui tournent les bits, et vous pouvez également envisager d'utiliser une table de recherche.

Rien de tout cela n'a d'importance pour le golf, cependant. Il me semble que votre solution actuelle est la meilleure que vous puissiez faire. Bien sûr, vous pouvez supprimer les espaces blancs superflus:

k<1?0:(int)Math.Log(k&-k,2)+1

Je l'écrirais personnellement comme:

k>0?(int)Math.Log(k&-k,2)+1:0

parce que je pense que c'est un peu plus clair d'avoir la direction du test conditionnel de cette façon, ainsi que de le comparer à zéro, mais je suppose que c'est six dans un sens, une demi-douzaine dans l'autre.

C # ne supporte pas la conversion implicite de intla boolcomme C et C ++ font, vous ne pouvez pas réduire vraiment le test conditionnel plus loin.

Vous êtes également bloqué avec la distribution explicite de double(comme retourné mon Math.Log) à int, car C # ne permettra pas que cela se produise implicitement. Bien sûr, c'est normalement une bonne chose car cela soulignerait que vous avez un gros problème de performances ici: promouvoir un inten un double, calculer le journal d'un double, puis reconvertir le doublerésultat en un intsera extrêmement lent, donc c'est normalement quelque chose que vous voudriez éviter. Mais ce sont les types de perversions que vous devez supporter lorsque vous jouez au golf à code.


J'avais initialement trouvé

k > 0
      ? ((k & -k) >> 1) + 1
      : 0

(non golfé pour plus de clarté, bien sûr), ce qui évite de prendre le logarithme et est donc une amélioration de la taille et de la vitesse du code. Malheureusement, cela n'obtient pas toujours la bonne réponse, et je suppose que c'est une exigence inflexible. :-) Plus précisément, il échoue si la valeur d'entrée ( k) est un facteur de 8. Ceci est réparable, mais pas sans allonger le code que la Math.Logversion.

Cody Grey
la source
Notez que pour le golf de code, le Mathdoit être entièrement qualifié, donc votre autre version devrait être meilleure même si je n'ai pas réellement compté les octets.
TheLethalCoder
Vous voulez dire celui qui produit la mauvaise sortie? @the
Cody Gray
Eh bien, vous avez dit qu'il y avait une solution, mais cela la rendrait plus longue. Si le correctif est plus court que lorsque la version OP comprend, System.il doit être plus court et correct.
TheLethalCoder