Dividir, voltear y recombinar enteros


16

Antecedentes

Es bien sabido en matemáticas que los enteros se pueden poner en una correspondencia uno a uno con pares de enteros. Hay muchas formas posibles de hacer esto, y en este desafío, implementará una de ellas y su operación inversa.

La tarea

Su entrada es un número entero positivo n > 0. Se sabe que existen enteros únicos no negativos, a, b ≥ 0tales como . Su salida es la "versión invertida" de , el entero positivo .n == 2a * (2*b + 1)n2b * (2*a + 1)

Puede suponer que la entrada y la salida se ajustan al tipo de datos entero sin signo estándar de su idioma.

Reglas y puntaje

Puede escribir un programa completo o una función. El conteo de bytes más bajo gana, y las lagunas estándar no se permiten.

Casos de prueba

Estos se dan en el formato in <-> out, ya que la función que se implementará es su propio inverso: si le devuelve la salida, debe obtener la entrada original.

1 <-> 1
2 <-> 3
4 <-> 5
6 <-> 6
7 <-> 8
9 <-> 16
10 <-> 12
11 <-> 32
13 <-> 64
14 <-> 24
15 <-> 128
17 <-> 256
18 <-> 48
19 <-> 512
20 <-> 20
28 <-> 40
30 <-> 384
56 <-> 56
88 <-> 224
89 <-> 17592186044416

Tabla de clasificación

Aquí hay un fragmento de pila para generar una tabla de clasificación regular y una descripción general de los ganadores por idioma. Para asegurarse de que su respuesta se muestre, comience con un título, usando la siguiente plantilla de Markdown:

## Language Name, N bytes

¿Dónde Nestá el tamaño de su envío? Si mejora su puntaje, puede mantener los puntajes antiguos en el título, tachándolos. Por ejemplo:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Si desea incluir varios números en su encabezado (p. Ej., Porque su puntaje es la suma de dos archivos o desea enumerar las penalizaciones de los intérpretes por separado), asegúrese de que el puntaje real sea el último número en el encabezado:

## Perl, 43 + 2 (-p flag) = 45 bytes

También puede hacer que el nombre del idioma sea un enlace que luego aparecerá en el fragmento de la tabla de clasificación:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


1
Es curioso, este problema fue publicado en anarchy golf la semana pasada
— feersum

@feersum Oh, no estaba al tanto. Qué casualidad.
— Zgarb

2
Obligatorio xkcd.com/153
— corsiKa

Respuestas:


11

Jalea , 17 16 15 bytes

BUi1µ2*³:2*×Ḥ’$

Pruébalo en línea!

Cómo funciona

BUi1µ2*³:2*×Ḥ’$    Main link. Input: n

B                  Convert n to base 2.
 U                 Reverse the array of binary digits.
  i1               Get the first index (1-based) of 1.
                   This yields a + 1.
    µ              Begin a new, monadic chain. Argument: a + 1
     2*            Compute 2 ** (a+1).
       ³:          Divide n (input) by 2 ** (a+1).
                   : performs integer division, so this yields b.
         2*        Compute 2 ** b.
              $    Combine the two preceding atoms.
            Ḥ      Double; yield 2a + 2.
             ’     Decrement to yield 2a + 1.
           ×       Fork; multiply the results to the left and to the right.

Espera, ¿estás implementando operadores en Jelly para adaptarse al problema? En ese caso LOL
— Alexander Torstling

No soy. El único compromiso con Jelly después de que se publicó este desafío fue una actualización de la documentación, y todo el operador utilizado en esta respuesta se implementó durante al menos un mes. Siéntase libre de verificar
— Dennis

No se preocupe, no estoy familiarizado con las reglas ni nada, ¡solo pensé que era genial que el golf haya llegado a las personas que inventan sus propios idiomas!
— Alexander Torstling


10

Pyth, 16 15 bytes

*hyJ/PQ2^2.>QhJ

1 byte gracias a Dennis

Banco de pruebas

Explicación:

*hyJ/PQ2^2.>QhJ
                    Implicit: Q = eval(input())
     PQ             Take the prime factorization of Q.
    /  2            Count how many 2s appear. This is a.
   J                Save it to J.
  y                 Double.
 h                  +1.
          .>QhJ     Shift Q right by J + 1, giving b.
        ^2          Compute 2 ** b.
*                   Multiply the above together, and print implicitly.

7

MATL , 22 bytes

Yft2=XK~)pq2/2w^Ks2*Q*

Pruébalo en línea!

Explicación

Yf      % factor
t       % duplicate
2=      % compare to 2 (yields a logical array)
XK      % save a copy of that to variable K
~)      % keep only values != 2 in the factors array
p       % multiply that factors
q2/     % product - 1 / 2
2w^     % 2^x

K       % load variable K (the logical array)
s       % sum (yields the number of 2s)
2*Q     % count * 2 + 1

*       % multiply both values

¡Muy agradable! Puede usar Qpara 1+(esto se ha introducido recientemente) y qpara 1-. Eso también ahorra un espacio (que podría ahorrar de Htodos modos). Ver aquí
— Luis Mendo

@LuisMendo Gracias. No conocía esa característica.
— Rainer P.

55
¡Bien hecho superando a Luis usando MATL!
— Stewie Griffin

6

Python 2, 39 bytes

lambda n:2*len(bin(n&-n))-5<<n/2/(n&-n)

n & -nda la mayor potencia de 2 que divide n. Funciona porque en la aritmética de complemento a dos, -n == ~n + 1. Si ntiene k ceros al final, tomar su complemento hará que tenga k al final. Luego, agregar 1 cambiará todos los finales a ceros, y cambiará el bit 2 ^ k de 0 a 1. Entonces -ntermina con un 1 seguido de k 0 (igual que n), mientras que tiene el bit opuesto nen todos los lugares más altos.


¿Puedes explicar brevemente cómo n&-nfunciona? veo lo que hace este truco pero no cómo :(
— Erwan

n&-ndevuelve la potencia más alta de 2 que divide n.
— Neil

@Erwan lo expliqué n & -n.
— feersum

Obtuve el programa correspondiente en Anarchy golf n=1;exec"c=n&-n;print n,':',2*len(bin(c))-5<<n/2/c;n+=1;"*100, pero hay dos caracteres detrás de la mejor solución.
— xnor

@xnor Sugerencia: la solución de 59 bytes (bueno, al menos la mía) no funciona para todos los valores de n.
— feersum

6

MATL , 25 26 bytes

:qt2w^w!2*Q*G=2#f2*q2bq^*

Esto usa la versión actual (10.2.1) del lenguaje / compilador.

Pruébalo en línea!

Explicación

Bastante sencillo, basado en la fuerza bruta. Intenta todas las combinaciones de a y b , selecciona la adecuada y realiza el cálculo requerido.

:q          % implicit input "n". Generate row vector [0,1,...,n-1], say "x"
t2w^        % duplicate and compute 2^x element-wise
w!2*Q       % swap, transpose to column vector, compute 2*x+1
*           % compute all combinations of products. Gives 2D array
G=2#f       % find indices where that array equals n
2*q2bq^*    % apply operation to flipped values

1
Ja! :-P Golpeado en tu propio idioma ... ¿primera vez?
— Stewie Griffin

@StewieGriffin ¡Sí! Un buen hito :-)
— Luis Mendo

5

Julia, 41 bytes

n->2^(n>>(a=get(factor(n),2,0)+1))*(2a-1)

Esta es una función anónima que acepta un entero y devuelve un entero. Para llamarlo, asígnelo a una variable.

Definimos acomo 1 + el exponente de 2 en la factorización prima de n. Dado que factordevuelve una Dict, se pueden usar getcon un valor por defecto de 0 en caso de que la descomposición en factores primos no contiene 2. desplazamiento de bits a la derecha npor a, y tomar de 2 a este poder. Multiplicamos eso por 2a-1para obtener el resultado.


4

Perl 5, 40 bytes

38 bytes más 2 para -p

$i++,$_/=2until$_%2;$_=2*$i+1<<$_/2-.5

-plee el STDIN en la variable $_.

$i++,$_/=2until$_%2incrementos $i(que comienzan en 0) y se reducen a la mitad $_hasta $_que no sea cero mod 2. Después de eso, $_es el factor impar del número original y $ies el exponente de 2.

$_=2*$i+1<<$_/2-.5- El lado derecho de la =es solo la fórmula para el número buscado: {1 más del doble del exponente de 2} veces {2 a la potencia de {la mitad del factor impar menos la mitad}}. Pero "times {2 to the power of ...}" se juega como "un poco desplazado hacia la izquierda por ...". Y ese lado derecho está asignado a $_.

Y -pgrabados $_.



2

JavaScript ES6, 36 33 bytes

n=>63-2*Math.clz32(b=n&-n)<<n/b/2

Tengo entendido que Math.clz32va a ser más corto que jugar contoString(2).length .

Editar: Guardado 3 bytes gracias a @ user81655.


Agradable. También puede guardar algunos bytes configurando n&-nuna variable:n=>63-2*Math.clz32(x=n&-n)<<n/x/2
— user81655

@ user81655 Gracias; Solo desearía haberlo usado n&=-n, pero necesito notra vez ...
— Neil

1

PARI / GP , 38 bytes

f(n)=k=valuation(n,2);(2*k+1)<<(n>>k\2)

Tenga en cuenta que >>y \tienen la misma precedencia y se calculan de izquierda a derecha, por lo que la última parte puede ser en n>>k\2lugar de (n>>k)\2. La versión no golfista sería kléxica con my:

f(n)=
{
  my(k=valuation(n,2));
  (2*k+1) << ((n>>k)\2);
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.