Trova il massimo di 3 numeri senza diramazione


17

Questa volta il tuo obiettivo è trovare il massimo di 3 numeri interi (da - (2 ^ 31) a 2 ^ 31 - 1 nel complemento di 2 binari) senza usare ramificazioni o anelli.

Hai solo il permesso di usare

  • La disuguaglianza / uguaglianza ( ==, >, >=, <, <=, !=) Questi contano come 2 gettoni.

  • Aritmetica ( +, -, *, /)

  • Operatori logici ( !non, &&e, || o)

  • Bitwise Operatori ( ~non, &e, |o, ^xor, <<, >>, >>>sinistra aritmetica e logica e si sposta a destra)

  • Costanti. 0 token

  • Assegnazione variabile. 0 token

Immettere 3 variabili come a, be c. Emette il numero massimo.

Si applicano le regole standard di golf atomico. In caso di domande, lasciarle nei commenti. Un token è uno dei precedenti con le regole speciali.


Che ne dite di definire una funzione extra? Se questo è consentito, quanti token conta?
afuoso

@voidpigeon Puoi avere una sola funzione, quella che accetta i 3 ingressi e uscite.
qwr

1
A prima vista ho pensato, "l' abbiamo già avuto prima " , ma penso che i comparatori che costano 2 cambino il gioco un po '.
primo

@primo Ho specificamente chiesto 3 input perché in realtà consente alcuni miglioramenti interessanti
qwr

2
Possiamo usare le funzioni integrate?
Utente registrato

Risposte:


7

Javascript 10 token

Modifica usando <e * invece di manipolare i bit - come sottolineato nei commenti, le operazioni sui bit potrebbero non riuscire per l'input vicino al limite dell'intervallo (oltre 30 bit)

function Max(x,y,z)
{
  var d=y-x;
  x=y-d*(d<0);
  d=x-z;
  return x-d*(d<0);
}

Token C 8

Il linguaggio agnostico infatti, qualsiasi linguaggio simile a C farà. Ad essere pignoli, nello standard C non è portatile perché il giusto spostamento potrebbe non estendere il segno (ma nelle implementazioni comuni lo fa).

In C (e C ++, C # e Java credo) possiamo facilmente gestire i problemi di overflow usando valori temporanei più grandi:

int Max(int x, int y, int z)
{
    long long X = x;
    long long Y = y;
    long long Z = z;
    long long D = Y-X;
    X=Y-((D>>63)&D);
    D=X-Z;
    return (int) (X-((D>>63)&D));
}

1
Sto diventando esigente, ma usando C ints il tuo codice non funziona per x = 2147483647, y = -2, z = 0. La tua scelta se vuoi cambiarla
qwr

10

Javascript

6 token

function maxOf3(a, b, c) {
    (b>a) && (a=b);
    (c>a) && (a=c);
    return a;
}

6
+1 Vedo la valutazione delle scorciatoie come un tipo di ramificazione, ma non è proibito nelle regole
edc65

11
Lo considererei come ramificato, ahah
solo il

2
@ edc65 Lo è. Consentire &&ed ||era probabilmente una svista, che dovrebbe essere sottolineato, piuttosto che sfruttato.
primo

@primo Questo è stato un problema interessante. Credo che alcune architetture CISC abbiano istruzioni che includono dichiarazioni condizionali, quindi non sono sicuro di come vengano contate.
qwr,

2
Immagino che dovrebbe essere 4 token cioè 2 &&, <e >. Il =viene utilizzato come un incarico e conta come 0
Clyde Lobo

6

C: 10 token

int max(int a, int b, int c)
{
    a += (b > a) * (b - a);
    a += (c > a) * (c - a);
    return a;
}

Ispirato dalla risposta di @ openorclose, ma convertito in C e reso privo di diramazioni utilizzando la moltiplicazione anziché operatori booleani in corto circuito.


3

Javascript

14 token

function max (a, b, c)
{
    var ab = (a >= b) * a + (a < b) * b;
    return (ab >= c) * ab + (ab < c) * c;
}

1
Non puoi creare nuove funzioni
qwr

:( 14 token allora
Fabricio

2

Molte lingue (Python) (10 token)

def max3(x,y,z):
    m = x ^ ((x ^ y) & -(x < y))
    return m ^ ((m ^ z) & -(m < z))

print max3(-1,-2,-3) # -1
print max3(-1,2,10) # 10

https://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax

Oh, qualcuno l'ha già pubblicato :)


Non puoi creare nuove funzioni
qwr

Ahh ok! Non ho letto i commenti :)
Mardoxx il

@qwr Non capisco, hai detto: You are only allowed to have one function, the one that takes the 3 inputs and outputs.è esattamente quello che ha questa risposta. Le 2 stampe sono solo test case
Cruncher,

1
@Cruncher Ho modificato la risposta che ho fatto max2(max2(x,y),z)inizialmente :)
Mardoxx il

@Mardoxx ah. Bene +1
Cruncher,

1

Token C ++ 11: 15

Utilizzando solo operatori aritmetici e bit per bit (poiché gli operatori di uguaglianza e logica booleana lo rendono troppo facile) ...

#include <iostream>

auto max(int32_t a, int32_t b, int32_t c)->int32_t {
  return c - ((c - (a - ((a - b) & (a - b) >> 31))) & (c - (a - ((a - b) & (a - b) >> 31))) >> 31);
}

auto main()->int {
  // test harness
  std::cout << max(9, 38, 7) << std::endl;
  return EXIT_SUCCESS;
}


Mi sembra perfetto: ideone.com/pEsvG3
Riot

Hai letto per caso il commento? Penso che 2 miliardi sia maggiore di 0 [ ideone.com/vlcnq9 ]
edc65,

Ah capisco; sì, ha un problema con quei numeri nell'altro tuo commento, quando è coinvolto uno 0. Ma non per 2 ^ 30 come hai detto. ideone.com/LicmXa
Riot

Non è lo 0 coinvolto. Il problema sono numeri grandi e overflow, prova max (2000000000, -200000000, 1111111111).
edc65,

0

J (Non in competizione)

Mi stavo solo chiedendo come sarebbe una soluzione in J. Questo utilizza un ,e un #però, quindi non sarà in competizione.

((a<b),(b<c),(c<a))#b,c,a

Questo competerebbe, ma è troppo lungo, con 9 token:

(b*a<:b)+(c*b<c)+(a*c<a)

0

abbiamo i seguenti presupposti:

  • max (a; b) = (a + b + | ab |) / 2

  • max (a, b, c) = max (max (a, b), c)

  • abs (a) = (a + (a >> 31)) ^ (a >> 31)

possiamo usare lo pseudo-codice:

funzione max (a, b, c)

{

out1 = ((a + b) + (((ab) + ((ab) >> 31)) ^ ((ab) >> 31))) div 2

out2 = ((out1 + c) + (((out1-c) + ((out1-c) >> 31)) ^ ((out1-c) >> 31))) div 2

ritorno 2

}


Scrivi il codice attuale e fornisci il numero di token nella tua risposta.
Programma FOX il

0

C # (2 ° tentativo)

Ho capito ... Nessuna funzione integrata ...

Ma è permesso usare altri tipi di dati integrati o semplicemente int? Se consentito, proporrei:

int foo2(int a, int b, int c)
{
   var x = new SortedList<int,int>();

   x[a] = 1;
   x[b] = 1;
   x[c] = 1;

   return x.Keys[2];
}

0

token javascript 8

sebbene simile alla risposta di @ openorclose, in realtà utilizzo gli operatori logici per l'assegnazione stessa.

function max( a, b, c ) {
    x=( a > b && a) || b;
    return ( x > c && x ) || c;
}

violino


0

R (10 token)

function max(a, b, c) {
  max <- a
  max <- max + (b - max) * (b > max)
  max <- max + (c - max) * (c > max)
  return(max)
}

0

Brainfuck (Non in competizione)

>,[-<+>>>+<<]>,[-<+>>>+<<]>[>[-<->>]<<]<[-]>[-]>[-]<<<[->>>>+<<<<]>>>>[-<+>>>+<<]>,[-<+>>>+<<]>[>[-<->>]<<]<<

0

TIS-100, 8 operazioni

MOV ACC UP #A
SUB UP     #B
SUB 999
ADD 999
ADD UP     #B
SUB UP     #C
SUB 999
ADD 999
ADD UP     #C
MOV ACC DOWN

Il provider (UP) esegue solo MOV, quindi non mostrato nel codice Forse non funziona quando è troppo vicino al bordo del 999


-1

VBA (6 token)

 Function max3(a As Integer, b As Integer, c As Integer)
 i = IIf(a >= b And a >= c, a, IIf(b >= c, b, c))
 max3 = i
 End Function  

non sono sicuro se questo non si sta ramificando.


Si sta ramificando, solo in linea. In particolare, l'onnipresente operatore ternario (che essenzialmente è) non è una delle operazioni consentite.
tomsmeding

Grazie @tomsmeding, posso chiedere qual è l'onnipresente operatore ternario (è IIF () nel mio codice?)
Alex

sì scusa, con onnipresente intendevo che è presente in quasi tutte le lingue e l'operatore ternario è il tuo IIfInline-If. Nella maggior parte delle lingue, ad esempio, lo è a>=b ? a : b. Si sta davvero ramificando.
tomsmeding

-1

JavaScript: 4 token (** basato su un'ampia interpretazione di "assegnazione"!)

Ovviamente il mio punteggio di 4 è estremamente generoso / indulgente!

Per arrivare a quel punteggio ho assunto che "assegnazione" (vale 0 token nella domanda) include cose come assegnazione additiva, assegnazione sottrattiva, assegnazione moltiplicativa e assegnazione XOR-ing ( ^=)

function f(a, b, c) {
  d = a;
  d -= b;
  d = d >= 0;

  a *= d;  //a = a if (a>=b), else 0
  d ^= true; //invert d
  b *= d;  //b = b if (b<a), else 0

  a += b;  //a is now max(a,b)

  d = a;
  d -= c;
  d = d >= 0;

  a *= d;  //a = a if (a>=c), else 0
  d ^= true; //invert d
  c *= d;  //c = c if (c<a), else 0
  a += c;  //a is now max(max(a,b),c)

  return a;
}

Se quei compiti contano effettivamente il punteggio è 14 :)


Perché in d -= brealtà è lo stesso di d = d - b, direi che usi l'aritmetica e che dovresti considerarlo come un token.
Programma FOX il

Sì, mi rendo conto che - stavo (scherzando) cercando di sfruttare il significato di "incarico". Penso di averlo reso abbastanza ovvio!
jcdude,
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.