Znajdź maksymalnie 3 liczby bez rozgałęziania


17

Tym razem Twoim celem jest znalezienie maksymalnie 3 liczb całkowitych (od - (2 ^ 31) do 2 ^ 31 - 1 w uzupełnieniu binarnym 2) bez użycia rozgałęzień lub pętli.

Jesteś tylko wolno używać

  • Nierówność / Równość ( ==, >, >=, <, <=, !=) Ci liczone jako 2 żetonów.

  • Arytmetyczna ( +, -, *, /)

  • Operatory logiczne ( !nie &&i, || lub)

  • Operatory bitowe ( ~nie, &i, |lub, ^xor, <<, >>, >>>arytmetyczne i logiczne lewy i prawy przesunięcia)

  • Stałe 0 tokenów

  • Zmienne przypisanie. 0 tokenów

Wejście 3 zmienne jak a, bi c. Podaj maksymalną liczbę.

Obowiązują standardowe zasady kodowania atomowego. Jeśli masz jakieś pytania, zostaw je w komentarzach. Jeden token to dowolny z powyższych ze specjalnymi zasadami.


A co z definiowaniem dodatkowej funkcji? Jeśli jest to dozwolone, ile żetonów się liczy?
obrzydliwy

@ Unikaj gołębia Możesz mieć tylko jedną funkcję, która przyjmuje 3 wejścia i wyjścia.
qwr

1
Na pierwszy rzut oka pomyślałem już to mieliśmy , ale myślę, że komparatory kosztujące 2 bardzo zmieniają grę.
primo

@primo W szczególności poprosiłem o 3 dane wejściowe, ponieważ w rzeczywistości pozwala na kilka interesujących ulepszeń
qwr

2
Czy możemy korzystać z wbudowanych funkcji?
Zarejestrowany użytkownik

Odpowiedzi:


7

Javascript 10 tokenów

Edycja za pomocą <i * zamiast fiddlingu bitowego - jak wskazano w komentarzach, operacje bitowe mogą zakończyć się niepowodzeniem dla danych wejściowych w pobliżu limitu zakresu (ponad 30 bitów)

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

C 8 żetonów

Niezależnie od języka, zrobi to każdy język podobny do C. Aby być wybrednym, w standardowym C nie jest przenośny, ponieważ prawe przesunięcie może nie przedłużać znaku (ale w zwykłych implementacjach to robi).

W C (i C ++, C # i Java, myślę) możemy łatwo poradzić sobie z problemami z przepełnieniem przy użyciu większych wartości tymczasowych:

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
Jestem wybredna, ale używając C ints twój kod nie działa dla x = 2147483647, y = -2, z = 0. Twój wybór, jeśli chcesz go zmienić
qwr

10

JavaScript

6 żetonów

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

6
+1 Widzę ocenę skrótu jako rodzaj rozgałęzienia, ale nie jest to zabronione w regułach
edc65


2
@ edc65 To jest. Zezwolenie &&i ||prawdopodobnie był niedopatrzeniem, które należy podkreślić, a nie wykorzystać.
primo

@primo To był interesujący problem. Wierzę, że niektóre architektury CISC mają instrukcje, które zawierają instrukcje warunkowe, więc nie jestem pewien, jak by się je liczyło.
qwr

2
Chyba powinno być 4 żetony czyli 2 &&, <a >. =Stosowany jest jako przypisanie i liczy się jako 0
Clyde Lobo

6

C: 10 żetonów

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

Zainspirowany odpowiedzią @ openorclose, ale przekonwertowany na C i pozbawiony rozgałęzień przy użyciu mnożenia, a nie zwarcia operatorów logicznych.


3

JavaScript

14 żetonów

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

1
Nie możesz tworzyć nowych funkcji
qwr

:( 14 tokenów następnie
Fabricio

2

Wiele języków (Python) (10 tokenów)

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

Och, ktoś już to opublikował :)


Nie możesz tworzyć nowych funkcji
qwr

Ahh ok! Nie czytałem komentarzy :)
Mardoxx

@qwr Nie rozumiem, powiedziałeś: You are only allowed to have one function, the one that takes the 3 inputs and outputs.Dokładnie to ma ta odpowiedź. 2 odbitki to tylko przypadki testowe
Cruncher

1
@Cruncher Zredagowałem odpowiedź, którą zrobiłem max2(max2(x,y),z)początkowo :)
Mardoxx

@Mardoxx ah. Cóż +1
Cruncher

1

C ++ 11: 15 tokenów

Używanie tylko operatorów arytmetycznych i bitowych (ponieważ operatory logiki równości i logicznej sprawiają, że jest to zbyt łatwe) ...

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

Niepowodzenie dla dużych liczb (> 2 ^ 30), patrz komentarz codegolf.stackexchange.com/questions/32476/#comment68870_32477
edc65

Dla mnie wygląda dobrze: ideone.com/pEsvG3
Riot

Czy przypadkowo przeczytałeś komentarz? Myślę, że 2 miliardy to więcej niż 0 [ ideone.com/vlcnq9 ]
edc65

O, rozumiem; tak, ma problem z tymi liczbami w twoim innym komentarzu, gdy występuje 0. Ale nie dla 2 ^ 30, jak powiedziałeś. ideone.com/LicmXa
Riot

To nie dotyczy 0. Problemem są duże liczby i przepełnienie, spróbuj max (2000000000, -200000000, 1111111111).
edc65

0

J (nie konkuruje)

Zastanawiałem się tylko, jak wyglądałoby rozwiązanie w J. To używa ,a #, ale nie będzie konkurować.

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

To konkurowałoby, ale jest zbyt długie, z 9 żetonami:

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

0

mamy następujące założenia:

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

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

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

możemy użyć pseudo-kodu:

funkcja 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))) dział 2

zwróć 2

}


Proszę wpisać rzeczywisty kod i podać liczbę tokenów w swojej odpowiedzi.
ProgramFOX

0

C # (druga próba)

Mam to ... Brak zintegrowanych funkcji ...

Ale czy można używać innych zintegrowanych typów danych, czy tylko zwykłego int? Jeśli pozwolę, zaproponowałbym:

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

javascript 8 tokenów

chociaż podobne do odpowiedzi @ openorclose, faktycznie używam operatorów logicznych do samego przypisania.

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

skrzypce


0

R (10 żetonów)

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

0

Brainfuck (nie konkuruje)

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

0

TIS-100, 8 operacji

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

Dostawca (UP) wykonuje tylko MOV, więc nie pokazano w kodzie Może nie działać, gdy jest zbyt blisko krawędzi 999


-1

VBA (6 żetonów)

 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  

nie jestem pewien, czy to nie rozgałęzia się.


Rozgałęzia się, tylko w linii. W szczególności wszechobecny operator trójskładnikowy (którym tak naprawdę jest) nie jest jedną z dozwolonych operacji.
tomsmeding

Dzięki @tomsmeding, czy mogę zapytać, jaki jest wszechobecny operator trójskładnikowy (czy w moim kodzie jest to IIF ()?)
Alex

tak, przepraszam, z wszechobecnym miałem na myśli, że jest obecny w prawie każdym języku, a operatorem potrójnym jest twój IIf, Inline-If. W większości języków jest to na przykład a>=b ? a : b. To naprawdę rozgałęzia się.
tomsmeding

-1

JavaScript: 4 tokeny (** oparte na szerokiej interpretacji „przypisania”!)

Oczywiście mój wynik 4 jest wyjątkowo hojny / łagodny!

Aby dojść do tego wyniku, założyłem, że „przypisanie” (warte 0 żetonów w pytaniu) obejmuje takie rzeczy, jak przypisanie addytywne, przypisanie odejmujące, przypisanie multiplikatywne i 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;
}

Jeśli te zadania faktycznie się liczą, wynik wynosi 14 :)


Ponieważ w d -= brzeczywistości jest to to samo d = d - b, powiedziałbym, że używasz arytmetyki i że powinieneś liczyć to jako token.
ProgramFOX

Tak, zdaję sobie sprawę, że - próbowałem (żartobliwie) wykorzystać znaczenie „zadania”. Myślę, że to dość oczywiste!
jcdude
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.