Estoy tratando de usar C # para encontrar el índice del primer 1 (de derecha a izquierda) en la representación binaria de un número. Por ejemplo, dado que 100 en binario es:
0b1100100
El primer 1 está en la tercera posición desde la derecha, por lo que debería producir 3.
234 debería producir 2, 0 debería producir 0, etc.
Aquí está mi solución actual:
k < 1 ? 0 :(int)Math.Log(k & -k, 2) + 1;
¿Alguna forma de acortar esto?
Convert.ToString(k,2).IndexOf("1")
es lo que quieres, o algo similar, un sitio incorrecto.Respuestas:
Si solo C # admite intrínsecos específicos de la máquina ... Hay una sola instrucción que puede hacer esto en lenguaje ensamblador x86, y también en la mayoría de las arquitecturas de otros procesadores. Entonces no solo tendría el código más corto, sino muy probablemente el más rápido.
De hecho, hacer que este código sea más corto es un problema extremadamente aburrido en comparación con hacer que este código sea rápido . Hay todo tipo de soluciones realmente ordenadas, eficientes y poco complicadas, y también podría considerar usar una tabla de búsqueda.
Sin embargo, nada de eso importa para el golf. Me parece que su solución actual es lo mejor que puede hacer. Por supuesto, puede eliminar el espacio en blanco superfluo:
Yo personalmente lo escribiría como:
porque creo que es un poco más claro tener la dirección de la prueba condicional de esa manera, así como compararla con cero, pero supongo que son seis en una dirección, media docena en la otra.
C # no admite la conversión implícita de
int
abool
C y C ++, por lo que realmente no puede acortar más la prueba condicional.También está atascado con la conversión explícita de
double
(como devuelto miMath.Log
) aint
, ya que C # no permitirá que esto suceda implícitamente. Por supuesto, eso normalmente es bueno porque señalaría que tiene un gran problema de rendimiento aquí: promocionarint
a a adouble
, calcular el registro de adouble
y luego convertir eldouble
resultado a aint
será enormemente lento, por lo que normalmente es algo que te gustaría evitar Pero estos son los tipos de perversiones que tienes que soportar cuando juegas golf de código.Inicialmente se me ocurrió
(sin pretensiones de claridad, por supuesto), lo que evita tomar el logaritmo y, por lo tanto, es una mejora en el tamaño y la velocidad del código. Desafortunadamente, esto no siempre obtiene la respuesta correcta, y supongo que es un requisito inflexible. :-) Específicamente, falla si el valor de entrada (
k
) es un factor de 8. Esto es reparable, pero no sin hacer que el código sea más largo que laMath.Log
versión.fuente
Math
debería estar completamente calificado, por lo que su otra versión debería ser mejor, aunque en realidad no he contado los bytes.System.
entonces debería ser más corta y correcta.