Meno, Plus, Tempi, Esponenziazione?


26

Questa è una CMC (chat mini challenge) che ho pubblicato nella nostra chatroom, The Ninteenth Byte , un po 'di tempo fa.

La sfida

Dato un numero intero positivo x, a seconda degli ultimi 2 bit di x, procedi come segue:

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

Input Output

Single Integer -> Single Integer  

Una nuova riga finale è consentita nell'output. Non sono ammessi altri spazi bianchi.

Casi test

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

Questa è una sfida di , quindi vince il codice più corto!


8
Non dovrebbe il 0caso essere x + 2, visto che gli altri sono x * 2, x ^ 2e x ^^ 2(tetrazione)? : P
ETHproductions

Qual è l'output più grande che dovremmo supportare (riguardo x ^ x)? 32 bit non è già sufficiente per il test case 11e 64 bit non è sufficiente per il test case 19.
Kevin Cruijssen,

@KevinCruijssen Dirò che devi solo gestire i casi in cui l'input e l'output rientrano nell'ambito della tua lingua, purché il tuo programma funzionerebbe teoricamente con una dimensione numerica infinita.
HyperNeutrino,

@HyperNeutrino Ok, in quel caso ho corretto il mio codice (Java 7) (per +72 byte .. xD)
Kevin Cruijssen

Risposte:


13

Gelatina , 8 byte

ị“+×*_”v

Provalo online!

Come funziona

Innanzitutto, nota che x&3equivale a x%4, dove %è modulo. Quindi, poiché Jelly utilizza l'indicizzazione modulare ( a[n] == a[n+len(a)]), quindi non abbiamo nemmeno bisogno di occuparcene.

Poi:

  • If x%4==0, return x_x(sottrazione) (per coerenza);
  • Se x%4==1, ritorna x+x;
  • If x%4==2, return x×x(moltiplicazione);
  • If x%4==3, return x*x(esponenziazione)

Nota che Jelly utilizza l'indicizzazione 1, quindi la sottrazione "_"viene spostata alla fine.

ị“+×*_”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.

2
@andrybak AFAIK Jelly ha una sua codifica - vedi qui , ma so che tutti i suoi caratteri sono 1 byte.
Stephen,

"8 byte". Come devono essere contati i byte? Questa risposta è composta da otto caratteri, ma almeno nella codifica stackexchange serve questa pagina, occupa fino a 15 byte (contati usando wc --bytes).
andrybak,

Se il linguaggio lo interpreta in una codifica, non ha senso usare un'altra codifica per il conteggio dei byte (imo)
Mackenzie McClane

@andrybak Il codice codificato in una codifica in modo che il browser lo mostri correttamente è di 15 byte. Il codice in una codifica che Jelly comprende è di 8 byte. Guarda github.com/DennisMitchell/jelly/wiki/Code-page se vuoi sapere come è codificato.
Etoplay


9

CJam , 12 byte

ri__"-+*#"=~

Provalo online!

Spiegazione

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.

Esegue una delle seguenti operazioni a seconda xdel valore mod 4 (mod 4 è equivalente a AND 3).

0:  -  Subtraction
1:  +  Addition
2:  *  Multiplication
3:  #  Exponentiation

6

Mathematica 25 byte

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

Salvato 4 byte grazie a @MartinEnder


4

Pyth, 8 byte

.v@"0y*^

Interprete


Sì, l'ho provato e funziona. E no, non posso usare al vposto di .v.
Erik the Outgolfer,

Pensavo che l'ambito fosse locale ... Pensavo di .vnon poter accedere Q... Apparentemente sono stato superato in Pyth. +1 per te.
Leaky Nun,

@LeakyNun No, è quello vche ha portata locale, .velimina solo un'espressione.
Erik the Outgolfer,

Ho molto da imparare ...
Leaky Nun,

3
Questo è bello! È assolutamente fantastico! Non avevo idea che fosse nemmeno possibile. Per i punti di stile, "0y*^potrebbe essere "-+*^.
isaacg,





2

C, 63 o 62 byte

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

-1 byte se le macro sono consentite, supponendo che xnon sia un'espressione simile 3+5(poiché ciò rovinerebbe la precedenza):

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

@ceilingcat Giusto, me ne sono dimenticato.
Tim Čas,

non si compila su MSVS2015; Intellisense ha detto che il cast to incomplete array type "int[]" is not allowedcompilatore ha detto error C4576: a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax; ANCHE! dove è int f (int x)? il codice è in realtà almeno 8 byte più lungo; inoltre è molto lento e inefficiente, in quanto valuta tutto - non ripeterlo IRL)

@ xakepp35 Cosa? 1) deve compilare in un compilatore C. La maggior parte dei compilatori C (leggi: quasi tutti tranne MSVC) supporta questa (int[])sintassi per questa situazione. 2) f(x)è perfettamente legale C89. Non ho specificato lo standard. 3) Si tratta della dimensione del codice, non dell'efficienza. E 4) Se stai per patrocinare, almeno usa un vero compilatore e / o controlla i tuoi fatti.
Tim Čas,

@Tim Čas Ah sì, mi dispiace davvero! Stavo cercando di compilarlo come codice C ++. È colpa mia) Compila e funziona alla grande!

2

Java 7, 75 byte

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);}

Anche se è valido secondo le regole, longè a 64 bit, quindi non riesce per i casi di test di esponenziazione di 19^19e sopra. Per risolvere il problema, possiamo usare un BigDecimalapproccio:

148 146 byte

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);}

Spiegazione (dell'approccio 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

Codice di prova:

Provalo qui.

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) + "; ");
    }
  }
}

Produzione:

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; 

Non è necessario correggere il programma in questo modo: P La vecchia risposta funzionerebbe se i numeri avessero dimensioni infinite; il primo programma sarebbe stato valido secondo le mie specifiche. : P
HyperNeutrino,

@HyperNeutrino Quindi ho specificato che nella risposta .. Ah bene, Java non vincerà comunque le sfide del code-golf. ;)
Kevin Cruijssen,

1
Sì, vorrei specificare. E sì, è Java, non vincerà. : D
HyperNeutrino,

2
" E sì, è Java, non vincerà.: D " Ci sono abituato. : P Anche la mia risposta Java più breve di sempre di 8 byte è troppo lunga rispetto alle risposte del golf. xD Anche se è stata la prima volta che ho battuto una risposta Python con la mia risposta Java, che deve contare per qualcosa che immagino. ;)
Kevin Cruijssen,

2

Assemblatore x86, sintassi Intel, 192 byte

.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

L'esempio finge di avere la massima velocità di lavoro. Is è un programma o una parte di programma che utilizza la convenzione fastcall. Presuppone la variabile di input xnel registro eaxe restituisce anche il risultatoeax . L'idea di base è stare lontano dall'uso dei salti condizionali, come in alcuni esempi qui. Inoltre, non si tratta di valutare tutto (come nell'esempio C con le matrici) ma di utilizzare una serie di puntatori per le funzioni e per eseguire salti incondizionati più veloci (jmp / call) come un analogo ottimizzato "C language switch () - case ..". Questa tecnica potrebbe essere utile anche in tipi di finita automi, come emulatori di processori, esecutori e così via.

Aggiornamento: per x64 usa "r" nei nomi dei registri, anziché "e" (es. raxInvece di eax, rcxinvece di ecx). La dimensione non verrà modificata e utilizzerà parole senza segno a 64 bit.


Benvenuti in PPCG! L'obiettivo di questa sfida è rendere il tuo codice il più breve possibile. In questo caso, il codice potrebbe essere facilmente abbreviato combinando tutte quelle dichiarazioni di funzioni. Puoi anche rimuovere alcuni spazi bianchi.
HyperNeutrino,

@HyperNeutrino asm stesso è un po 'un linguaggio "lungo" :) quindi non ho idea di come accorciarlo. qualche consiglio di esempio?

Eh, scusa, devo aver copiato il mio commento sulla tua risposta C in questo post. Non so come programmare in ASM ma potresti rimuovere potenzialmente degli spazi bianchi?
HyperNeutrino,

@HyperNeutrino, scusa .. ma sembra di no) deve essere il codice più lungo tra gli altri, posso solo troncare windows crlf in formato linux quindi 209-> 192 byte, le modifiche non sono visibili)

Aw. È troppo male. Ma bella presentazione a prescindere! :)
HyperNeutrino

2

C #, 39 byte

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

Spiegazione

Osservare che:

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

La soluzione crea un array, si indicizza in esso e quindi moltiplica il risultato per x:

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

Versioni alternative:

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

(39B, tutta la moltiplicazione eseguita nell'array, x%4sostituisce x&3)

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

(39B, uguale alla risposta di @ MetaColon ma x%2*2*xsostituzione x*x%4<1?0:2)


1

In realtà , 12 byte

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

Provalo online!

Spiegazione:

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



1

Oasi , 25 byte

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

Provalo online!

Come funziona

Si noti che x&3è equivalente a x%4, dove %è modulo.

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 è un linguaggio basato su stack in cui ogni personaggio è un comando.



1

C #, 42 byte

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

In realtà è normale C #, ma dato che non puoi eseguirlo come un intero programma e devi inserirlo nell'interattivo, suppongo che potresti chiamarlo C # interattivo .

Spiegazione :

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)

Non so se sia la variante più breve, tutti i suggerimenti sono apprezzati.


Non penso sia valido. In genere è necessario inviare un programma o una funzione . Gli snippet non sono consentiti per impostazione predefinita.
Cyoce,

@Cyoce È un programma. Devi solo eseguirlo attraverso l'interattivo, che interpreterà il programma.
MetaColon

Quando eseguo questo in interattivo, ricevo un errore perché xnon è definito. Ciò rende questo un frammento, non un programma completo.
Cyoce,

@Cyoce Nella sfida che diceva, ci sarebbe stata una variabile x definita.
MetaColon

Non è quello che significa. "Dato un numero intero positivo x" significa che ti viene dato x attraverso un metodo di input standard (cioè funzione o programma).
Cyoce,




1

C, 115 byte

#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))

L'esempio è una funzione int f(int x)

Pretende di avere la massima velocità di lavoro poiché impedisce alla CPU di utilizzare i salti condizionati. E questo è solo il modo corretto di ottimizzazione della velocità per questo compito. Inoltre, cerca di non valutare tutto, come nell'esempio dell'array C return(int[]){0,x+x,x*x,pow(x,x)}[x%4];Ma di usare saggiamente l'array di puntatori alle funzioni, al fine di eseguire salti incondizionati molto più veloci (jmp / call) con aritmetiche di indirizzi molto più veloci, come versione ottimizzata di " scatola dell'interruttore..". Questa tecnica potrebbe essere utile anche in diversi tipi di finita automi - come emulatori di processori, esecutori, parser di flussi di comandi e così via - dove la velocità conta e il codice switch(x%4) case(0):... case(1):... è inadatto perché produce più istruzioni cmp / jnz; e queste sono operazioni costose per la CPU

Il programma di test più semplice e breve (in condizioni predefinite) per il caso sarà il seguente:

D(main,f(x))

Aggiungerà solo 12 byte di payload e totalizzerà la nostra dimensione a 127 byte;

Ma dovresti dire al linker di usare la ffunzione come punto di ingresso, invece dimain . Questo è il modo, se miriamo a ottenere il binario di lavoro più veloce possibile per questa attività dal codice più breve ;-) Ciò accade perché la libreria C aggiunge un codice di avvio / arresto aggiuntivo prima di chiamare la funzione main ().

Il codice viene compilato su MSVS Community 2015 senza trucchi e problemi e produce risultati corretti. Non l'ho provato con gcc, ma sono sicuro che funzionerà anche bene.


1
Benvenuti in PPCG! L'obiettivo di questa sfida è rendere il tuo codice il più breve possibile. In questo caso, il codice potrebbe essere facilmente abbreviato combinando tutte quelle dichiarazioni di funzioni. Puoi anche rimuovere alcuni spazi bianchi.
HyperNeutrino,

Mi piace l'idea di utilizzare i puntatori alle funzioni
RosLuP,

@RosLuP, ma è quasi due volte più lungo della versione di 60 byte. ma funziona molto più velocemente, vale le sue dimensioni.

@Hyper Neutrino Ok. L'ho compresso di più. Sembra che questa sia la versione finale! Non ci sono bug, tutti i test sono stati superati

@ xakepp35 hai misurato che il tuo è più veloce del mio?
RosLuP,

1

R, 47 42 byte

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

Applica la funzione -, +, *, o ^sulla base del modulo di xa xed x.

- è l'unica (piuttosto) cosa intelligente, da allora x-x è sempre 0.

R, 33 byte

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

Stesso metodo usato da altre persone. Anche se è più corto, non mi piace tanto.


0

Pyth , 12 byte

.vjd,+@"-+*^

Provalo online!

Come funziona

Innanzitutto, nota che x&3equivale a x%4, dove %è modulo. Quindi, poiché Pyth utilizza l'indicizzazione modulare ( a[n] == a[n+len(a)]), quindi non abbiamo nemmeno bisogno di occuparcene.

Poi:

  • If x%4==0, return x-x(per coerenza);
  • Se x%4==1, ritorna x+x;
  • Se x%4==2, ritorna x*x;
  • Se x%4==3, ritorna x^x.

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

Altro sulla notazione polacca: Wikipedia (peccato se sei in Turchia).


Eh? Questo mi sembra troppo. Vedi la mia risposta per i dettagli.
Erik the Outgolfer,

0

Japt , 13 byte

Ov"^+*p"gU +U

Provalo online!

Questo utilizza lo stesso metodo delle altre risposte eval, tranne per il fatto che il programma -Unega U, quindi usiamo invece ^(XOR bit a bit).


0

Vim, 50 byte

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

Qui, ^Vrappresenta un Ctrl+V, ^Rrappresenta Ctrl-Re ^[rappresenta la escchiave

Funziona costruendo prima l'espressione e poi lasciando bc valutare. Prevede l'input sulla prima riga in un buffer altrimenti vuoto.

Spiegazione:

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.

Quando ^Vscrivo, incolla ciò che ho negli appunti, invece del numero ...
Leaky Nun

1
Provalo online! Inoltre, puoi fare Dinvece did$
DJMcMayhem

0

Pyth, 9 byte

@[0yQ*QQ^

Suite di test

Non c'è niente di speciale qui, basta calcolare i quattro valori e selezionarne uno con l'indicizzazione modulare.

@[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

0

Lotto, 135 byte

@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%

Speravo di creare l'espiazione costruendo e valutando una stringa del modulo in [0+...+0, 2+...+2, x+...+x, x*...*x]base agli ultimi due bit di xma sfortunatamente il codice per selezionare l'operazione impiegava troppo tempo per esprimersi perché non potevo usare *come forparametro, ma ero almeno in grado di usare un po 'di inganno per liberare alcuni byte.


0

Retina , 87 byte

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

Provalo online! (Il link include la suite di test.)

Explanation: The first two lines convert the input into unary and duplicate it (so we now have x;x). The next two lines look for an x&3 of either 0 or 1 and change x;x into x;0 or x;2 appropriately. The next two lines look for x&3==3 and change x;x into x;x;x;...;x;1;x (x xs). This means that we have either x;0, x;2, x;x, or x;...;x and it remains to multiply everything together and convert back to decimal. (The multiplication code is based on that in the Retina wiki but amended to handle multiplication by zero.)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.