847 Stimmen

Bestimmung der Funktion f(f(n)) == -n

Eine Frage, die mir bei meinem letzten Vorstellungsgespräch gestellt wurde:

Eine Funktion entwerfen f , so dass:

f(f(n)) == -n

Wo n ist ein 32-Bit vorzeichenbehaftete Ganzzahl Sie können nicht mit komplexen Zahlen arithmetisch rechnen.

Wenn Sie eine solche Funktion nicht für den gesamten Zahlenbereich entwickeln können, entwickeln Sie sie für den größtmöglichen Bereich.

Irgendwelche Ideen?

6 Stimmen

Um welche Stelle ging es bei diesem Vorstellungsgespräch?

27voto

Anurag Punkte 136648

Ausnutzung von JavaScript-Ausnahmen.

function f(n) {
    try {
        return n();
    }
    catch(e) { 
        return function() { return -n; };
    }
}

f(f(0)) => 0

f(f(1)) => -1

0 Stimmen

Ich bezweifle, dass Ausnahmen auf diese Weise schon einmal verwendet wurden... :)

0 Stimmen

+1 Unkonventionelles Denken. Cool! Aber in der Produktion Code würde ich typeof verwenden, nur um sicher zu sein.

23voto

Eclipse Punkte 43775

Für alle 32-Bit-Werte (mit dem Vorbehalt, dass -0 gleich -2147483648 ist)

int rotate(int x)
{
    static const int split = INT_MAX / 2 + 1;
    static const int negativeSplit = INT_MIN / 2 + 1;

    if (x == INT_MAX)
        return INT_MIN;
    if (x == INT_MIN)
        return x + 1;

    if (x >= split)
        return x + 1 - INT_MIN;
    if (x >= 0)
        return INT_MAX - x;
    if (x >= negativeSplit)
        return INT_MIN - x + 1;
    return split -(negativeSplit - x);
}

Im Grunde müssen Sie jede -x => x => -x-Schleife mit einer y => -y => y-Schleife verbinden. Ich habe also die gegenüberliegenden Seiten der Schleife split .

z.B. für 4-Bit-Ganzzahlen:

0 => 7 => -8 => -7 => 0
1 => 6 => -1 => -6 => 1
2 => 5 => -2 => -5 => 2
3 => 4 => -3 => -4 => 3

21voto

Skizz Punkte 66931

Eine C++-Version, die wahrscheinlich die Regeln etwas verbiegt, aber für alle numerischen Typen (Floats, Ints, Doubles) und sogar Klassentypen funktioniert, die das unäre Minus überladen:

template <class T>
struct f_result
{
  T value;
};

template <class T>
f_result <T> f (T n)
{
  f_result <T> result = {n};
  return result;
}

template <class T>
T f (f_result <T> n)
{
  return -n.value;
}

void main (void)
{
  int n = 45;
  cout << "f(f(" << n << ")) = " << f(f(n)) << endl;
  float p = 3.14f;
  cout << "f(f(" << p << ")) = " << f(f(p)) << endl;
}

0 Stimmen

Eine gute Idee. Als Alternative könnte man wahrscheinlich auf die Struktur verzichten und stattdessen eine Funktion einen Zeiger zurückgeben lassen, die andere Funktion dereferenzieren und negieren.

20voto

LiraNuna Punkte 61060

X86 asm (AT&T-Stil):

; input %edi
; output %eax
; clobbered regs: %ecx, %edx
f:
    testl   %edi, %edi
    je  .zero

    movl    %edi, %eax
    movl    $1, %ecx
    movl    %edi, %edx
    andl    $1, %eax
    addl    %eax, %eax
    subl    %eax, %ecx
    xorl    %eax, %eax
    testl   %edi, %edi
    setg    %al
    shrl    $31, %edx
    subl    %edx, %eax
    imull   %ecx, %eax
    subl    %eax, %edi
    movl    %edi, %eax
    imull   %ecx, %eax
.zero:
    xorl    %eax, %eax
    ret

Code geprüft, alle möglichen 32bit Integer übergeben, Fehler bei -2147483647 (Unterlauf).

19voto

teeks99 Punkte 3423

Verwendet Globals...aber so?

bool done = false
f(int n)
{
  int out = n;
  if(!done)
  {  
      out = n * -1;
      done = true;
   }
   return out;
}

3 Stimmen

Ich bin mir nicht sicher, ob dies die Absicht des Fragestellers war, aber +1 für "über den Tellerrand schauen".

5 Stimmen

Anstatt bedingt "done = true" zu sagen, sollten Sie immer "done = !done" sagen, so dass Ihre Funktion mehr als einmal verwendet werden kann.

0 Stimmen

@Chris, da done innerhalb eines if(!done)-Blocks auf true gesetzt wird, ist es äquivalent zu done=!done, aber !done muss nicht berechnet werden (oder vom Compiler optimiert werden, wenn er schlau genug ist).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X