¿Menos, más, tiempos, exponenciación?

26

Este es un CMC (mini desafío de chat) que publiqué en nuestra sala de chat, The Ninteenth Byte , hace un poco.

El reto

Dado un entero positivo x, dependiendo de los últimos 2 bits de x, haga lo siguiente:

x & 3 == 0: 0
x & 3 == 1: x + x
x & 3 == 2: x * x
x & 3 == 3: x ^ x (exponentiation)

De entrada y salida

Single Integer -> Single Integer  

Se permite una nueva línea final en la salida. No se permite ningún otro espacio en blanco.

Casos de prueba

input       output
    1            2
    2            4
    3           27
    4            0
    5           10
    6           36
    7       823543
    8            0
    9           18
   10          100
   11 285311670611
   12            0

Este es un desafío de , por lo que gana el código más corto.

Hiperneutrino
fuente
8
No debería el 0caso, ser x + 2, viendo que los otros son x * 2, x ^ 2y x ^^ 2(tetración)? : P
ETHproductions
¿Cuál es el mayor resultado que deberíamos admitir (con respecto x ^ x) 32 bits ya no es suficiente para el caso de prueba 11, y 64 bits no es suficiente para el caso de prueba 19.
Kevin Cruijssen
@KevinCruijssen Diré que solo tiene que manejar casos en los que la entrada y la salida están dentro del alcance de su idioma, siempre que su programa funcione teóricamente dado un tamaño de número infinito.
HyperNeutrino
@HyperNeutrino Ok, en ese caso arreglé mi código (Java 7) (para +72 bytes .. xD)
Kevin Cruijssen

Respuestas:

13

Jalea , 8 bytes

ị“+×*_”v

Pruébalo en línea!

Cómo funciona

En primer lugar, observe que x&3es equivalente a x%4, donde %es módulo. Entonces, dado que Jelly usa la indexación modular ( a[n] == a[n+len(a)]), entonces ni siquiera necesitamos ocuparnos de eso.

Luego:

  • Si x%4==0, devuelve x_x(resta) (por consistencia);
  • Si x%4==1, vuelve x+x;
  • Si x%4==2, retorno x×x(multiplicación);
  • Si x%4==3, retorno x*x(exponenciación)

Tenga en cuenta que Jelly utiliza la indexación 1, por lo que la resta "_"se mueve al final.

ị“+×*_”v  example input: 10
ị“+×*_”   index 10 of the string “+×*_”, which gives "×"
       v  evaluate the above as a Jelly expression,
          with 10 as the argument, meaning "10×" is the
          expression evaluated. The dyad "×" takes the
          second argument from the only argument, effectively
          performing the function to itself.
Monja permeable
fuente
2
@andrybak AFAIK Jelly tiene su propia codificación, mira aquí , pero sé que todos sus caracteres son de 1 byte.
Stephen
"8 bytes". ¿Cómo deben contarse los bytes? Esta respuesta consta de ocho caracteres, pero al menos en la codificación stackexchange sirve esta página, ocupa 15 bytes (contados usando wc --bytes).
andrybak
Si el lenguaje lo interpreta en una codificación, no tiene sentido usar otra codificación para el recuento de bytes (IMO)
Mackenzie McClane
@andrybak El código codificado en una codificación para que el navegador lo muestre correctamente es de 15 bytes. El código en una codificación que Jelly entiende es de 8 bytes. Mira github.com/DennisMitchell/jelly/wiki/Code-page si quieres saber cómo está codificado.
Etoplay
13

Python , 30 bytes

lambda x:[0,x+x,x*x,x**x][x%4]

Pruébalo en línea!

Mego
fuente
2
Versión alternativa en python 2: 'lambda x: [0,2, x, x ** x / x] [x% 4] * x'.
TLW
9

CJam , 12 bytes

ri__"-+*#"=~

Pruébalo en línea!

Explicación

ri            e# Read an int from input (call it x).
  __          e# Duplicate x twice.
    "-+*#"    e# Push this string.
          =   e# Get the character from the string at index x (mod 4).
           ~  e# Eval that char, using the two copies of x from before.

Ejecuta una de las siguientes operaciones dependiendo del xvalor del mod 4 (mod 4 es equivalente a AND 3).

0:  -  Subtraction
1:  +  Addition
2:  *  Multiplication
3:  #  Exponentiation
Gato de negocios
fuente
6

Mathematica 25 Bytes

0[2#,#*#,#^#][[#~Mod~4]]&

Guardado 4 Bytes gracias a @MartinEnder

Kelly Lowder
fuente
4

Pyth, 8 bytes

.v@"0y*^

Interprete

Erik el Outgolfer
fuente
Sí, he probado esto y funciona. Y no, no puedo usar en vlugar de .v.
Erik the Outgolfer
Pensé que el alcance era local ... Pensé .vque no podía acceder Q... Aparentemente me superaron en Pyth. +1 para ti
Leaky Nun
@LeakyNun No, es lo vque tiene alcance local, .vsolo evalúa una expresión.
Erik the Outgolfer
Tengo mucho que aprender ...
Leaky Nun
3
¡Eso es hermoso! Eso es absolutamente asombroso! No tenía idea de que eso fuera posible. Por puntos de estilo, "0y*^podría ser "-+*^.
isaacg
3

Haskell, 28 27 bytes

f x=cycle[0,x+x,x*x,x^x]!!x

Pruébalo en línea!

Editar: Gracias a @ Ørjan Johansen por 1 byte.

nimi
fuente
Hm, llego muy tarde, pero podrías acortar esto un byte cycle.
Ørjan Johansen
@ ØrjanJohansen: más vale tarde que nunca. ¡Gracias!
nimi
2

C, 63 o 62 bytes

#include<math.h>
f(x){return(int[]){0,x+x,x*x,pow(x,x)}[x&3];}

-1 byte si se permiten macros, suponiendo xque no sea una expresión como 3+5(ya que eso estropearía la precedencia):

#include<math.h>
#define f(x)(int[]){0,x+x,x*x,pow(x,x)}[x&3]
Tim Čas
fuente
@ceilingcat Correcto, se olvidó de eso.
Tim Čas
no se compila en MSVS2015; Intellisense dijo cast to incomplete array type "int[]" is not allowedCompiler dijo error C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax; ¡ADEMÁS! ¿Dónde está int f (int x)? el código es en realidad al menos 8 bytes más largo; también es muy lento e ineficiente, ya que evalúa todo - no lo repita IRL)
@ xakepp35 ¿Qué? 1) tiene que compilarse en un compilador de C. La mayoría de los compiladores de C (léase: casi todos menos MSVC) admiten esta (int[])sintaxis para esta situación. 2) f(x)es perfectamente legal C89. No especifiqué el estándar. 3) Se trata del tamaño del código, no de la eficiencia. Y 4) Si va a ser condescendiente, al menos use un compilador real y / o verifique sus hechos.
Tim Čas
@Tim Čas ¡Ah, sí, lo siento mucho! Estaba tratando de compilarlo como código C ++. Es mi culpa) ¡Se compila y funciona muy bien!
2

Java 7, 75 bytes

long c(int n){int x=n%4;return x<1?0:x<2?n+n:x<3?n*n:(long)Math.pow(n,n);}

Aunque es válido según las reglas, longes de 64 bits, por lo que falla en los casos de prueba de exponenciación de 19^19y superiores. Para arreglar eso podemos usar un BigDecimalenfoque:

148 146 bytes

import java.math.*;BigDecimal c(int n){int x=n%4;BigDecimal m=new BigDecimal(n);return x<1?m.subtract(m):x<2?m.add(m):x<3?m.multiply(m):m.pow(n);}

Explicación (del enfoque BigDecimal):

import java.math.*;                // Import required for BigDecimal
BigDecimal c(int n){               // Method with integer parameter and BigDecimal return-type
  int x=n%4;                       //  Input modulo-4
  BigDecimal m=new BigDecimal(n);  //  Convert input integer to BigDecimal
  return x<1?                      //  If the input mod-4 is 0:
    m.subtract(m)                  //   Return input - input (shorter than BigDecimal.ZERO)
   :x<2?                           //  Else if the input mod-4 is 1:
    m.add(m)                       //   Return input + input
   :x<3?                           //  Else if the input mod-4 is 2:
    m.multiply(m)                  //   Return input * input
   :                               //  Else:
    m.pow(n);                      //   Return input ^ input
}                                  // End of method

Código de prueba:

Pruébalo aquí

import java.math.*;
class M{
  static BigDecimal c(int n){int x=n%4;BigDecimal m=new BigDecimal(n);return x<1?m.subtract(m):x<2?m.add(m):x<3?m.multiply(m):m.pow(n);}

  public static void main(String[] a){
    for (int i = 1; i <= 25; i++) {
      System.out.print(c(i) + "; ");
    }
  }
}

Salida:

2; 4; 27; 0; 10; 36; 823543; 0; 18; 100; 285311670611; 0; 26; 196; 437893890380859375; 0; 34; 324; 1978419655660313589123979; 0; 42; 484; 20880467999847912034355032910567; 0; 50; 
Kevin Cruijssen
fuente
No necesita arreglar el programa de esta manera: P La respuesta anterior funcionaría si los números tuvieran un tamaño infinito; El primer programa habría sido válido según mis especificaciones. : P
HyperNeutrino
@HyperNeutrino Luego especifico eso en la respuesta ... Ah, bueno, Java no ganará ningún desafío de código de golf de todos modos. ;)
Kevin Cruijssen
1
Sí, lo especificaría. Y sí, es Java, no va a ganar. : D
HyperNeutrino
2
" Y sí, es Java, no va a ganar.: D " Estoy acostumbrado. : P Incluso mi respuesta Java más corta de 8 bytes es demasiado larga en comparación con las respuestas de golf. xD Aunque era la primera vez que superaba una respuesta de Python con mi respuesta de Java, que tiene que contar para algo, supongo. ;)
Kevin Cruijssen
2

Ensamblador x86, sintaxis Intel, 192 bytes

.data
f dw @q,@w,@e,@r
.code
mov ecx, eax
and ecx, 3
mov edx,dword ptr f[ecx*4]
call [edx]
ret
q:
xor eax,eax
ret
w:
add eax,eax
ret
e:
mul eax,eax
ret
r:
mov ecx,eax
t:
mul eax,eax
loop t
ret

El ejemplo pretende la velocidad de trabajo más rápida. Is es un programa o parte del programa, que utiliza la convención de llamada rápida. Asume una variable de entrada xen el registro eaxy devuelve el resultado también en eax. La idea básica es mantenerse alejado del uso de saltos condicionales, como en algunos ejemplos aquí. Además, no es evaluar todo (como en el ejemplo de C con matrices) sino utilizar una matriz de punteros para functons y hacer saltos incondicionales más rápidos (jmp / call) como un análogo optimizado de "cambio de lenguaje C () - mayúsculas y minúsculas". Esta técnica también podría ser útil en tipos de autómatas finitos, como emuladores de procesadores, ejecutores, etc.

Upd: para x64 use "r" en los nombres de registro, en lugar de "e" (por ejemplo, en raxlugar de eax, en rcxlugar de ecx). El tamaño no se cambiará y utilizará palabras sin signo de 64 bits.


fuente
Bienvenido a PPCG! El objetivo de este desafío es hacer que su código sea lo más corto posible. En este caso, su código podría acortarse fácilmente combinando todas esas declaraciones de funciones. También puede eliminar algunos espacios en blanco.
HyperNeutrino
@HyperNeutrino asm en sí mismo es un lenguaje un poco "largo" :) así que no tengo idea de cómo hacer esto más corto. algún ejemplo de consejos?
Eh, lo siento, debo haber copiado mi comentario sobre tu respuesta C en esta publicación. No sé cómo programar en ASM, pero ¿podría eliminar algún espacio en blanco?
HyperNeutrino
@HyperNeutrino, lo siento ... pero parece que no) tiene que ser el código más largo entre otros, solo puedo trunc windows crlf a formato linux para 209-> 192 bytes, los cambios no son visibles)
Aw Eso es muy malo. Pero buena presentación independientemente! :)
HyperNeutrino
2

C #, 39 bytes

x=>new[]{0,2,x,Math.Pow(x,x-1)}[x&3]*x;

Explicación

Observa eso:

(xx, x + x, x * x, x ^ x) == (0, 2, x, x ^ (x-1)) * x

La solución crea una matriz, la indexa y luego multiplica el resultado por x:

x => new[] { 0, 2, x, Math.Pow(x,x-1) }[x&3] * x;

Versiones alternativas:

x=>new[]{0,x+x,x*x,Math.Pow(x,x)}[x%4];

(39B, toda la multiplicación realizada en la matriz, x%4reemplaza x&3)

x=>x%4<2?x%2*2*x:Math.Pow(x,x%4<3?2:x);

(39B, igual que la respuesta de @ MetaColon pero x%2*2*xreemplazando x*x%4<1?0:2)

usuario1655772
fuente
1

En realidad , 12 bytes

;;3&"-+*ⁿ"Eƒ

Pruébalo en línea!

Explicación:

;;3&"-+*ⁿ"Eƒ
;;            two copies of input (so 3 total)
  3&          bitwise AND with 3
    "-+*ⁿ"E   index into this string
           ƒ  call the respective function
Mego
fuente
1

J , 14 bytes

4&|{0,+:,*:,^~

Pruébalo en línea!

Monja permeable
fuente
(4&|{-,+,*,^)~funciona bien pero es el mismo número de bytes debido a los parens, aunque es un poco más obvio lo que hace.
Cyoce
1

Oasis , 25 bytes

mn4%3Q*nkn4%2Q*nxn4%1Q*++

Pruébalo en línea!

Cómo funciona

Tenga en cuenta que x&3es equivalente a x%4, donde %es módulo.

mn4%3Q*nkn4%2Q*nxn4%1Q*++  input is n
mn4%3Q*                    (n**n)*((n%4)==3)
       nkn4%2Q*            (n**2)*((n%4)==2)
               nxn4%1Q*    (n*2)*((n%4)==1)
                       +   add the above two
                        +  add the above two

Oasis es un lenguaje basado en la pila donde cada personaje es un comando.

Monja permeable
fuente
1

C #, 42 bytes

x=>x%4<2?x*x%4<1?0:2:Math.Pow(x,x%4<3?2:x)

En realidad, es C # normal, pero como no puede ejecutarlo como un programa completo y tiene que escribirlo en el interactivo, creo que puede llamarlo C # interactivo .

Explicacion :

x => (x % 4) < 2     //If the bits are smaller than 2 (1 or 0)
? x *           //multiply x with
    (x % 4) < 1 //if the bits are 0
    ? 0         //0 (results in 0)
    : 2         //or else with 2 (results in 2*x or x+x)
: Math.Pow(x,   //otherwise power x by
    (x % 4) < 3 //if the bits are 2
    ? 2         //2 (results in x^2 or x*x)
    : x);       //or else x (results in x^x)

No puedo decir si es la variante más corta, se agradece cualquier sugerencia.

MetaColon
fuente
No creo que sea válido. Por lo general, debe enviar un programa o función . Los fragmentos no están permitidos de forma predeterminada.
Cyoce
@Cyoce es un programa. Solo tiene que ejecutarlo a través del interactivo, que interpretará el programa.
MetaColon
Cuando ejecuto esto en interactivo, recibo un error porque xno está definido. Eso hace que sea un fragmento, no un programa completo.
Cyoce
@Cyoce En el desafío que decía, habría una variable x definida.
MetaColon
Eso no es lo que eso significa. "Dado un número entero positivo x" significa que recibe x un método de entrada estándar (es decir, función o programa).
Cyoce
1

PHP, 36 bytes

<?=[0,2,$x=$argn,$x**~-$x][$x&3]*$x;
usuario63956
fuente
1

dc, 27

Nunca he tenido la oportunidad de usar matrices en cc antes:

[+]1:r[*]2:r[^]3:r?dd4%;rxp

Pruébalo en línea .

Trauma digital
fuente
1

C, 115 bytes

#include<math.h>
#define D(K,L)K(x){return L;}
D(q,0)D(w,x+x)D(e,x*x)D(r,pow(x,x))(*g[])()={q,w,e,r};D(f,g[x%4](x))

El ejemplo es una función int f(int x)

Pretende una velocidad de trabajo más rápida, ya que evita que la CPU use saltos condicionales. Y esta es solo la forma correcta de optimización de velocidad para esta tarea. Además, intenta no evaluar todo, como en el ejemplo de la matriz C, return(int[]){0,x+x,x*x,pow(x,x)}[x%4];sino utilizar sabiamente una variedad de punteros a las funciones, para hacer saltos incondicionales mucho más rápidos (jmp / call) con una aritmética de direcciones mucho más rápida, como una versión optimizada de " switch () - case .. ". Esta técnica también podría ser útil en varios tipos de autómatas finitos, como emuladores de procesador, ejecutores, analizadores de flujo de comandos, etc., donde la velocidad es importante y el código switch(x%4) case(0):... case(1):... no es adecuado porque produce múltiples instrucciones cmp / jnz; y estas son operaciones costosas para la CPU

El programa de prueba más simple y corto (en condiciones predeterminadas) para el caso será el siguiente:

D(main,f(x))

Agregará solo 12 bytes de carga útil y totalizará nuestro tamaño a 127 bytes;

Pero es mejor que le digas al enlazador que use la ffunción como punto de entrada, en lugar de main. Esa es la forma, si nuestro objetivo es obtener el binario de trabajo más rápido posible para esta tarea desde el código más corto ;-) Esto sucede porque la biblioteca C agrega código de inicio / apagado adicional antes de llamar a su función main ().

El código se compila en MSVS Community 2015 sin ningún truco y problema y produce resultados correctos. No lo he probado con gcc, pero estoy seguro de que funcionará bien también.


fuente
1
Bienvenido a PPCG! El objetivo de este desafío es hacer que su código sea lo más corto posible. En este caso, su código podría acortarse fácilmente combinando todas esas declaraciones de funciones. También puede eliminar algunos espacios en blanco.
HyperNeutrino
Me gusta la idea de usar punteros para funciones
RosLuP
@RosLuP ye, pero es casi dos veces más largo que su versión de 60 bytes. pero funciona mucho más rápido, vale su tamaño.
@Hyper Neutrino Ok. Lo he comprimido más. Parece, esta es la versión final! No hay errores, todas las pruebas pasaron 8-)
@ xakepp35 ¿midiste que tu es más rápido que el mío?
RosLuP
1

R, 47 42 bytes

x=scan();c(`-`,`+`,`*`,`^`)[[x%%4+1]](x,x)

Aplica la función -, +, *, o ^basado en el módulo de xa xy x.

-es lo único (algo) inteligente, ya x-xque siempre es 0.

R, 33 bytes

pryr::f(c(0,2*x,x^2,x^x)[x%%4+1])

El mismo método que usan otras personas. Aunque es más corto, no me gusta tanto.

JAD
fuente
0

Pyth , 12 bytes

.vjd,+@"-+*^

Pruébalo en línea!

Cómo funciona

En primer lugar, observe que x&3es equivalente a x%4, donde %es módulo. Entonces, dado que Pyth usa la indexación modular ( a[n] == a[n+len(a)]), entonces ni siquiera necesitamos ocuparnos de eso.

Luego:

  • Si x%4==0, devuelve x-x(por consistencia);
  • Si x%4==1, vuelve x+x;
  • Si x%4==2, vuelve x*x;
  • Si x%4==3, vuelve x^x.

.vjd,+@"-+*^  example input: 10
      @"-+*^  "-+*^"[10], which is "*"
     +        "*10"
    ,         ["*10","10"]
  jd          "*10 10"
.v            evaluate as Pyth expression
              (Pyth uses Polish notation)

Más información sobre la notación polaca: Wikipedia (lástima si estás en Turquía).

Monja permeable
fuente
¿Eh? Esto me parece demasiado. Vea mi respuesta para más detalles.
Erik the Outgolfer
0

Japt , 13 bytes

Ov"^+*p"gU +U

Pruébalo en línea!

Esto usa el mismo método que las otras respuestas de evaluación, excepto que el programa -Usimplemente niega U, por lo que usamos ^(XOR bit a bit) en su lugar.

ETHproducciones
fuente
0

Vim, 50 bytes

y$o^R"A-+*^^V^[0^R"lx0"_Dp^[0D@"kJ0"ad$:r!echo ^R"^R0|bc^<Enter>

Aquí, ^Vrepresenta a Ctrl+V, ^RrepresentaCtrl-R y ^[representa la escclave

Funciona construyendo primero la expresión y luego dejando bcevaluarla. Espera la entrada en la primera línea en un búfer vacío.

Explicación:

y$o^R"                                                          Copies the input into register " and pastes it on the second line
      A-+*^^V^[0^R"lx0"_Dp                                      Enters that text after the input on the second line
                          ^[0D@"                                Executes the second line as a Vim command.
                                                                For example, if the input is 12, the second line would be 12A-+*^^[012lx0"_Dp, which means:
                                                                  12A-+*^^[           Insert the text -+*^ 12 times
                                                                           012lx0"_Dp Go 12 chars to the right and remove everything except for that.
                                                                If effect, this basically just selects the appropriate operation.
                                kJ0"ad$                         Put the operator after the number, cut it into register a
                                       :r!                      Execute the following shell command and put the result into the buffer:
                                          echo ^R"^R0|bc<Enter> The shell command "echo [contents of register a][contents of registers 0]|bc. As said above, register a contains the input and the operator, and register 0 contains the input. The <enter> then executes this command.
Loovjo
fuente
Cuando ^Vlo escribo solo pega lo que tengo en mi portapapeles, en lugar del número ...
Leaky Nun
1
Pruébalo en línea! Además, puede hacerlo en Dlugar ded$
DJMcMayhem
0

Pyth, 9 bytes

@[0yQ*QQ^

Banco de pruebas

Aquí no pasa nada, solo calcule los cuatro valores y seleccione uno con indexación modular.

@[0yQ*QQ^
@[0yQ*QQ^QQ)Q    Implicit variable introduction
@           Q    Modularly index into the following list
 [0        )     0
   yQ            Q*2
     *QQ         Q*Q
        ^QQ      Q^Q
isaacg
fuente
0

Lote, 135 bytes

@set/an=%1*2^&6
@goto %n%
:6
@set n=1
@for /l %%i in (1,1,%1)do @set/an*=%1
@goto 0
:4
@set n=%1
:2
@set/an*=%1
:0
@echo %n%

Esperaba crear la exponenciación construyendo y evaluando una cadena del formulario [0+...+0, 2+...+2, x+...+x, x*...*x]dependiendo de los dos últimos bits, xpero desafortunadamente el código para seleccionar la operación tardó demasiado en expresarse porque no podía usarlo *como forparámetro, pero estaba al menos capaz de usar algunos trucos de caída para eliminar algunos bytes.

Neil
fuente
0

Retina , 87 bytes

.+
$*1;$&$*
;((1111)*)(1?)$
;$3$3
1(?=1.*;((1111)*111)$)
$1;
+`\G1(?=.*;(1*))|;1*$
$1
1

Pruébalo en línea! (El enlace incluye un conjunto de pruebas).

Explicación: Las dos primeras líneas convierten la entrada en unaria y la duplican (así que ahora la tenemos x;x). Las siguientes dos líneas buscan una x&3de o 0o 1y cambian x;xa x;0o x;2apropiadamente. Las siguientes dos líneas buscan x&3==3y cambian x;xa x;x;x;...;x;1;x( x xs). Esto significa que tenemos o bien x;0, x;2, x;x, o x;...;xy queda por todo lo que se multiplican juntos y volver a convertir decimal. (El código de multiplicación se basa en eso en la wiki de Retina, pero se modificó para manejar la multiplicación por cero).

Neil
fuente