Definieren Sie eine Funktion f so, dass f (f (n)) = -n für alle Ganzzahlen ungleich Null n ist

43

Diese Herausforderung wurde von einem Programmierblog inspiriert, den ich häufig betreibe. Den Originalbeitrag finden Sie hier: Ein Programmierpuzzle


Herausforderung

Definieren Sie eine Funktion f:Q->Qso, dass sie f(f(n)) = -nfür alle Ganzzahlen ungleich Null ngilt und wo Qdie Menge der rationalen Zahlen liegt.

Einzelheiten

In welcher Sprache bevorzugen Sie, definieren Sie eine Funktion oder ein Programm , fdas als Parameter akzeptiert eine Nummer nund gibt oder gibt eine Zahl f(n).

Die Eingabe kann über den für Ihre Sprache am besten geeigneten Mechanismus erfolgen: Funktionsargument, Lesen von STDIN, Befehlszeilenargument, Stapelposition, Spracheingabe, Gruppenzeichen usw.

Die Ausgabe sollte ein Rückgabewert einer Funktion / eines Programms sein oder auf STDOUT gedruckt werden.

Ich möchte Antworten auf Funktionen beschränken, die den Programmstatus oder den globalen Speicher / die Daten, die von außerhalb der Funktion sichtbar sind, nicht nutzen f. Wenn Sie zum Beispiel einen Zähler außerhalb fdieses Zählers belassen , zählt, wie oft faufgerufen wurde, und nur eine Negation auf der Grundlage dieses Zählers durchzuführen , ist für niemanden eine große Herausforderung oder ein großes Interesse. Die Entscheidungen fsollten sich nur auf Daten im flexikalischen Bereich stützen .

Diese Einschränkung ist jedoch wahrscheinlich für einige stapelorientierte Sprachen oder andere Arten von Sprachen ungeeignet, die diese Arten von Daten oder Bereichen nicht unterscheiden. Bitte verwenden Sie Ihr bestes Urteilsvermögen, um dem Geist dieser Herausforderung gerecht zu werden.


Wertung

Es gelten die allgemeinen Code-Golfregeln. Ihre Punktzahl ist die Anzahl der Bytes in Ihrem Quellcode.

Die minimale Antwort erfordert, dass die Domäne und die Codomäne von feine Teilmenge der Rationalen sind Q. Wenn Sie Ihre Domain und Codomain fauf die ganzen Zahlen beschränken Z, entspricht Ihre Punktzahl der Obergrenze von 90% der Anzahl der Bytes in Ihrem Quellcode.

Tiebreak

Im Falle eines Unentschieden wird Folgendes verwendet:

  1. Nur wenige druckbare Nicht-Leerzeichen- Symbole in Ihrem Quellcode
  2. Frühestes Datum und Uhrzeit der Beantwortung

Bearbeiten

Sie müssen keine Zahlen mit beliebiger Größe unterstützen. Bitte interpretieren Sie die Mengen Zund QDatentypen in der von Ihnen gewählten Sprache (in der Regel Integer bzw. Floating Point).

Wenn sich Ihre Lösung ausschließlich auf die zugrunde liegende Struktur oder das zugrunde liegende Bitmuster eines Datentyps stützt, beschreiben Sie bitte dessen Einschränkungen und die Verwendung.

seltsam
quelle
20
f (n) = i * n - reine Mathematik: P
Johannes Kuhn
8
@JohannesKuhn Aus diesem Grund sind Domain und Codomain auf die Rationals beschränkt
zwar am
Können Sie erklären, was das f:Q->Qbedeutet?
beary605
@ beary605 bedeutet, dass fes sich um eine Funktion handelt, die Mitglieder von Q(rationale Zahlen) anderen Mitgliedern (möglicherweise denselben) von (rationale Zahlen) zuordnet Q. siehe en.wikipedia.org/wiki/Function_(mathematics)#Notation
ardnew
7
Ich wusste, dass ich das kürzlich gesehen hatte, aber es dauerte eine Weile, bis ich mich daran erinnerte, wo. Eine weniger genau spezifizierte Version von StackOverflow wurde kürzlich geschlossen. Über 100 Antworten.
Peter Taylor

Antworten:

12

J, 9 Punkte (10 Zeichen)

Basierend auf der Stackoverflow-Antwort :

   (*-[*_1&^)

Erste Idee (13 Zeichen):

   ((-*)-2&|*+:)

   ((-*)-2&|*+:) _10 _9 _8 _7 _6 _5 _4 _3 _2 _1 0 1 2 3 4 5 6 7 8 9 10
_9 10 _7 8 _5 6 _3 4 _1 2 0 _2 1 _4 3 _6 5 _8 7 _10 9

   ((-*)-2&|*+:) _9 10 _7 8 _5 6 _3 4 _1 2 0 _2 1 _4 3 _6 5 _8 7 _10 9
10 9 8 7 6 5 4 3 2 1 0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _10
randomra
quelle
Dies funktioniert für die Ganzzahleingabe, erzeugt jedoch eine imaginäre Ausgabe für Gleitkommawerte (die Funktion muss eine rationale Ausgabe für eine rationale Eingabe gemäß der Spezifikation erzeugen)
Volatility
5
@Volatility, die Spezifikation ist verwirrend formuliert, aber wie ich es lese, erlaubt es, Domain und Codomain auf ganze Zahlen zu beschränken.
Peter Taylor
Benötigen Sie die Klammern?
Cyoce
14

Python: 61 34 30 29 27 Punkte

f: Q -> Q

in Mathe:

       | 0.5-x   if x is in Q \ Z
f(x) = |
       | x+0.5   if x is in Z

in Python:

f=lambda x:.5+[x,-x][x%1>0]

getestet mit

filter(lambda n: n[0] != -n[1], map(lambda n:(n,f(f(n))),range(0,50)))

Logik dahinter:

Wenn Sie eine ganze Zahl nehmen nund in sie feinfügen, erhalten Sie x+0.5. Dies ist nicht eine ganze Zahl nicht mehr, so dass die nächste Anwendung wird 0.5-(x+0.5)das ist -x.

Credits

Dank an

  • Bakuriu für das Reduzieren von 61 Zeichen auf 34 Zeichen.
  • Volatilität zur weiteren Reduzierung der Codegröße auf 30 Zeichen.
  • Kopie zum Reduzieren der Codegröße auf 29 Zeichen (und Beheben eines möglichen Gleitkommaproblems).
  • aditsu für die Erwähnung einer Inkonsistenz, die mit den obigen Änderungen einherging .

Anmerkungen

Zuerst dachte ich, das wäre in Ordnung

f = lambda n: 1j*n

aber es ist f: N-> C und das ist nicht erlaubt: - /

Martin Thoma
quelle
1
Kann reduziert werden auf: Das f=lambda x:x%1>0and(-x+x%1)or x+.1sind nur 34 Zeichen.
Bakuriu
f=lambda x:[x+.1,x%1-x](x%1>0)ist nur 30
Volatilität
1
Ein Zeichen kürzer: f=lambda x:[x+.5,.5-x][x%1>0]. Beachten Sie die Verwendung von .5 anstelle von .1, um Präzisionsprobleme zu umgehen
kopieren Sie den
1
@AJMansfield 1.48 ist keine Ganzzahl.
Martin Thoma
1
Nein, das heißt es nicht. Wenn er das erwähnte, hätte er "alle rationalen Zahlen" schreiben sollen. f:Q->Qbedeutet nur, dass f rationale Zahlen auf rationale Zahlen abbildet. Was meine Definition von f tut.
Martin Thoma
11

C, 41 Punkte (41 oder 45 Zeichen)

Funktioniert mit 32- und 64-Bit.

f : Z -> Z(außer INT_MAX):

f(n){return (abs(n)%2*2-1)*n+n?(-n<n)*2-1:0;}

Wenn wir nicht einschließen müssen, können 0wir einige Zeichen (41 Zeichen) abschneiden:

f : Z -> Z(außer 0& INT_MAX):

f(n){return (abs(n)%2*2-1)*n+(-n<n)*2-1;}

Diese Funktion teilt alle Ganzzahlen auf der Grundlage ihres Vorzeichens und ihrer Parität in 4 Gruppen auf.

Wir haben also die 4 verschiedenen Kombinationen:

+ even, + odd, - even, - odd

Da wir nach zwei Durchgängen das Vorzeichen der Zahl, aber nicht die Parität wechseln müssen, erhalten wir zwei verschiedene mögliche Folgen:

  + even -> - odd -> - even -> + odd -\
^-------------------------------------/

  + even -> + odd -> - even -> - odd -\
^-------------------------------------/

In diesem Beispiel habe ich das erste ausgewählt.

Zuerst müssen wir alle geraden positiven Ganzzahlen auf ungerade negative Ganzzahlen abbilden. Wir tun dies, indem wir das Vorzeichen ändern und die Zahl erhöhen (Sie können stattdessen auch die Zahl verringern):

f1(n) = -n + 1

Wir müssen dann alle ungeraden negativen Ganzzahlen auf gerade negative Ganzzahlen abbilden. Wir müssen sicherstellen, dass f2(f1(n)) = -n:

f2(f1(n)) = -n
f2(-n + 1) = -n
f2(-n) = -n - 1
f2(n) = n - 1

Mit den gleichen Methoden finden wir f3und f4:

f3(n) = -n - 1
f4(n) =  n + 1

Um diese Funktionen zu einer einzigen Funktion zu kombinieren, beobachten wir, dass wir jedes Mal, nwenn das Vorzeichen gleich ist nund jedes Mal, wenn nes positiv ist, um eins inkrementieren und ansonsten um eins dekrementieren:

f1(n) = -n + 1 (+ even)
f2(n) =  n - 1 (- odd)
f2(n) = -n - 1 (- even)
f4(n) =  n + 1 (+ odd)

Dies kann also umgeschrieben werden als:

f(n) = odd(n) * n + sign(n)

wo odd(n)Renditen 1für ungerade Zahlen und -1für gerade Zahlen.

Es gibt insgesamt 4 Lösungen:

f(n) = odd(n) * n + sign(n)  (edge cases: f(f(0))  -> -2, f(f(INT_MAX))   -> -8)
f(n) = even(n) * n - sign(n) (edge cases: f(f(0))  -> -2, f(f(INT_MIN+1)) -> -6)
f(n) = odd(n) * n - sign(n)  (edge cases: f(f(1))  -> -3, f(f(INT_MIN))   -> -5)
f(n) = even(n) * n + sign(n) (edge cases: f(f(-1)) -> -1, f(f(INT_MIN))   -> -5)

INT_MINkönnte in allen 4 Funktionen immer als -INT_MIN == INT_MINKantenfall betrachtet werden als => f(f(INT_MIN)) = INT_MIN.

Tyilo
quelle
Dies ist im Wesentlichen das Gleiche wie meine GolfScript-Antwort (außer besser erklärt). Funktioniert das für 0?
Ben Reich
@BenReich Wie in der Antwort angegeben, funktioniert es nicht für 0und 3 andere Nummern.
Tyilo
1
@Tylio sehe ich jetzt. Macht Sinn. Es scheint, dass Sie den ZBonus nur nehmen sollten, wenn Sie mindestens 0 decken.
Ben Reich
@BenReich Der Bonus wurde entfernt, bis er behoben ist.
Tyilo
9

Hier ist mein Versuch.

long f(int i){return i;}
int f(long i){return -i;}

Live Beispiel :

int main()
{
  for(int i=-10; i<10; i=i+3)
    std::cout << f(f(i)) << "\n";
}

Die Eingabetypen können beliebig auf Ihre Bedürfnisse zugeschnitten werden. Diese Version funktioniert für ganzzahlige Literale, deren Größe kleiner als 2 ^ 32-1 ist.

Rubenvb
quelle
2
Das Problem sagte f:Q->Qnicht f:Z->Z.
AJMansfield
@AJMansfield der Scoring-Bereich der Spezifikation sollte Bonuspunkte für definierte Funktionen bieten f:Z->Z, entschuldigen Sie die verwirrende Formulierung
neu
6
Das Problem bei dieser Antwort ist, dass anscheinend zwei separate Funktionen definiert werden, während für die Spezifikation nur eine definiert werden muss. aber ich will keine semantikdebatte beginnen, es ist immer noch eine sehr durchdachte lösung
zwar
@ardnew, oh du hast recht. Auf diesen gültigen Einwand wurde ich nur Sekunden vor dem Teilen mit der Lounge <C ++> im SO-Chat hingewiesen. Ich frage mich, was der Compiler daraus macht (wenn es nicht die Aufrufe inline), aber meine Assembly ist scheiße.
Rubenvb
1
Ich denke, Sie können das Leerzeichen in entfernenreturn -i
Cyoce
6

JavaScript, 18

f=n=>n%1?.5-n:n+.5

Verwenden der neuen Fettpfeilnotation (Firefox 22).

Andere Version (18):

f=n=>n%1?-.5/n:.5/n

Vorherige Version (20):

f=n=>n-~~n?.5-n:n+.5

Beispiel:

> [-3,-2,-1,1,2,3].map(f).map(f)
[3, 2, 1, -1, -2, -3]
Kopieren
quelle
10
JavaScript entwickelt sich anscheinend zu CoffeeScript.
Peter Taylor
4

Mathematica 18

f=#+1/2-4#(#-⌊#⌋)&

Hier ⌊...⌋ist die Bodenfunktion. Es werden nur rationale Zahlen verwendet (keine Listen, komplexe Zahlen usw.)

f[10]
f[f[10]]

21/2

-10

f[-5]
f[f[-5]]

-9/2

5

ybeltukov
quelle
3

x86-Assemblersprache (FASM). Das Argument und das Ergebnis befinden sich im eax-Register.

Es funktioniert ordnungsgemäß für -2 ^ 30 <N <+ 2 ^ 30-1

16 Byte ausführbarer Code.

        use32

f_n:
        lea     edx, [2*eax]
        xor     edx, eax
        btc     eax, 30
        shl     edx, 1
        jnc     .end
        neg     eax
.end:
        retn
Johnfound
quelle
Nitpicking deine Zahlen; 2E30 wäre 2 * 10 ^ 30, nicht 2 ^ 30, wie ich denke, dass Sie wollen.
Nick T
@ NickT Mein Fehler. Fest.
Johnfound
Ich bin mir ziemlich sicher, dass Sie die Bytes im Quellcode zählen sollen.
Nyuszika7h
3

Common Lisp: 35 Bytes

(defun f(x)(/(if(> 1 x)-1/2 1/2)x))

Schema (und Schläger): 36 Bytes

(define(f x)(/(if(> 1 x)-1/2 1/2)x))

Ungolfed mit Kommentaren und Erklärungen:

(define (f x)
  (/             ;; divide
     (if (> 1 x) ;; if x is below 1 
         -1/2    ;; then -1/2 (the fraction)
         1/2)    ;; else 1/2 (the fraction)
      x))        ;; gets divided with x

Für jede Zahl xin [1,->]der ifwird in die Fraktion drehen , 1/2die in beiden Sprachen eine echte genaue Zahl ist.

Der Teilungsteil wird dann (/ 1/2 x)so , dass der Bruchteil wird, 1/(x*2)der immer darunter liegt 1. Denn 1es wird sein 1/2, denn 2es ist 1/4, etc.

Für jede Zahl unter 1 das ifwird wiederum in der Fraktion -1/2, die die Funktion tun macht (/ -1/2 x)was -1/(2*x)aber da wir der Wert erwarten können, aufgrund der vorherigen Ausführung sein , die wir für / 1 (x * 2) Herstellung einer doppelten Anwendung ersetzen kann x-1/((1/(x*2))*2) = -x

ZB da 1wird in 1/2die zweite Anwendung verwandelt(/ -1/2 1/2) ==> -1

Sylwester
quelle
Wie funktioniert das?
AJMansfield
@AJMansfield hat einige Informationen hinzugefügt. Fragen Sie einfach, ob etwas unklar ist. Das Lesen der LISP-Syntax ist wie Griechisch, wenn Sie es nicht gelernt haben und es einige Wochen dauert, bis Sie sich daran gewöhnt haben.
Sylwester
3

C, 60 (~ 66 * .9 ~)

int f(int x){if(!x&1||!~x)return ~x;if(x<0)return x-1;return x+1;}

Hier ist eine unkondensierte Version:

int f(int x){
    if(!x&1 || !~x) return ~x;
    if(x<0) return x-1;
    return x+1;
}

Diese Methode funktioniert nur mit ganzen Zahlen, sodass der 90% -Bonus gutgeschrieben wird. Ich schrieb es ursprünglich in Java, erkannte jedoch, dass dieses Programm insbesondere von logischen Operatoren im C-Stil profitieren kann.

Da es keine ganze Zahl ist , entspricht -INT_MIN, f(f(INT_MIN))zurück INT_MINstatt.

Das zugrunde liegende Mapping ist algebraisch eher einfach. Das Ausführen der Anweisung x=f(x)ersetzt x durch:

  • x+1, wenn xpositiv und ungerade ist
  • -x+1, wenn xpositiv und gerade ist
  • x-1, wenn xnegativ und ungerade ist
  • -x-1, wenn xnegativ und gerade ist

Das Ergebnis eines jeden Falls fällt beim nächsten Anwenden der Funktion auf x unter den nächsten Fall.

Wie Sie sehen können, ergibt sich, wenn Sie einen Fall mit dem darauf folgenden Fall erstellen -x.

Der Code ist das Ergebnis einer cleveren Vereinfachung der Funktion, um die Bitstruktur von Zweierkompliment-Ganzzahlen auszunutzen.

AJMansfield
quelle
3

> <> , 21 + 3 = 24 Bytes, 22 Punkte

:0)$:0($:1$2%2*-*+-n;

Verwenden Sie den offiziellen Python-Interpreter und die -vBefehlszeilenoption, um eine Eingabe für 3 Byte einzugeben.

Ich habe das Gefühl, dass dies besser sein könnte - ich werde es weiter untersuchen und versuchen, es nach unten zu spielen.

Bei Eingabe ngibt das Programm aus

(n>0) - ((n<0) + n * (1 - 2*(n%2)))

wo (n>0)und (n<0)sind Booleaner. Dies entspricht der Python-Antwort von Gelatin

(n>0) - (n<0) - n * (-1)**n

Es gibt jedoch ><>keinen eingebauten Exponentiationsoperator, daher verwenden wir (1 - 2*(n%2))anstelle von (-1)**n.

Was folgt, ist mathematische Theorie - lesen Sie, wenn (und nur wenn) Sie interessiert sind:

Bei einer f: Z -> Zsolchen Funktion , dass f(f(n)) = -nfür alle nin Z, sehen wir sofort, dass f(f(f(f(n)))) = n, oder mit anderen Worten, f^4die Identitätsfunktion ist. Insbesondere fist invertierbar und seine Umkehrfunktion ist f^3. Somit fist eine Permutation Z, und da f^4 = Id, so folgt daraus , daß jede Umlaufbahn (oder Zyklus) der fGröße entweder 1, 2oder 4.

Als nächstes sehen wir das f(0) = 0. Beweis: f(0) = f(-0) = f(f(f(0))) = -f(0)also f(0) = 0, wie gewünscht. Umgekehrt sei angenommen, xin einem Zyklus der Länge 1oder 2so f(f(x)) = x. Dann -x = xalso x = 0.

Es besteht also fbis auf den Fixpunkt (1-Takt) vollständig aus 4-Takten 0.

Ferner muss jeder 4-Zyklus die Form hat (x, y, -x, -y), und durch den Zyklus Drehung um uns annehmen können xund ybeide positiv. Umgekehrt bestimmt jedes solche Produkt von 4 Zyklen, in denen die ganzen Zahlen ungleich Null partitioniert werden, eine Auswahl von f.

Somit entspricht jede Auswahl von feindeutig einem gerichteten Graphen, dessen Scheitelpunkte die positiven ganzen Zahlen sind, so dass jeder Scheitelpunkt auf genau einen Pfeil fällt, der entweder eintritt oder austritt. Genauer gesagt hat jeder Scheitelpunkt im zugrunde liegenden ungerichteten Graphen einen genauen Grad 1. (Jeder 4-Takt (x y -x -y)mit xund ypositiv entspricht dem Pfeil x --> y.)

Die Funktion in dieser Antwort (und einige andere Antworten hier) entspricht dem Graphen , wo 1 --> 2, 3 --> 4und im Allgemeinen 2k-1 --> 2k.

Solche Diagramme sind in Bijektion mit unendlichem Sequenzen von geordneten Paaren (a_n, p_n), wobei jedes a_neine positive ganze Zahl ist und jedes p_nist entweder 0oder 1: Bei einem gegebenen Sequenz (a_1, p_1), (a_2, p_2), (a_3, p_3), ..., wir erste Paar 1mit 1 + a_1, und dann bilden wir entweder den Pfeil 1 --> 1 + a_1oder auf den Pfeil 1 + a_1 --> 1in Abhängigkeit davon , ob p_1ist 0oder 1. Im Wesentlichen ist der Pfeil entweder ein <Zeichen oder ein >Zeichen, abhängig von der Parität von p_1.

Nehmen Sie als nächstes die kleinste ungepaarte positive Ganzzahl kund zählen Sie ab k, genau in a_2Schritten, indem Sie eine beliebige Zahl überspringen, die bereits mit etwas gepaart ist. Koppeln Sie kmit dem Ergebnis und stellen Sie die Pfeilrichtung p_2wie oben beschrieben ein. Wiederholen Sie dann mit (a_3, p_3)usw.

Jeder Pfeil wird schließlich auf diese Weise bestimmt, sodass der Prozess genau definiert ist. Die Funktion in dieser Antwort entspricht der Sequenz (1,0), (1,0), (1,0), ..., da im Schritt ndie kleinste ungepaarte ganze Zahl ist 2n-1und keine ganzen Zahlen größer 2n-1sind, als mit irgendetwas gepaart wurden. Wir erhalten also 2n-1 --> 2nfür jede n(Pfeile sind auf diese Weise ausgerichtet, weil jede p_ngleich ist 0).

Die Mächtigkeit dieser Menge ist (N*2)^N = N^N, die durch den letzten Absatz dieser Antwort ist gleich 2^N, die Mächtigkeit der reellen Zahlen.

mathmandan
quelle
Befehlszeilenoptionen bestehen normalerweise jeweils aus einem Byte.
Katze
@cat Siehe den Abschnitt "Spezielle Aufrufe" in diesem Meta-Beitrag .
Mathmandan
2

So korrigieren Sie die frühere J-Antwort (ich habe nicht genug Reputation, um das Original zu kommentieren):

(*+[*1-~2*2|])

Es ersetzt nur das _1&^mit 1-~2*2|], was das entgegengesetzte Vorzeichen gibt. Also habe ich das -zu a geändert +(was nur bei Eingabe von 1und zählt _1).

Hier sind die Tests:

   (*+[*1-~2*2|])6 3 _9 _8 1r2 _4.6 0 1 _1
7 _2 8 _9 1 7.28 0 2 _2
   (*+[*1-~2*2|])7 _2 8 _9 1 7.28 0 2 _2
_6 _3 9 8 0 _10.3568 0 _1 1

   NB. f^:2 = f@:f
   (*+[*1-~2*2|])^:(2)6 3 _9 _8 1r2 _4.6 0 1 _1
_6 _3 9 8 2 _5.0832 0 _1 1

Wie Sie sehen können, handelt es sich bei Domäne und Bereich um alle reellen Zahlen, dies funktioniert jedoch nur für ganze Zahlen (einschließlich 0).

Erläuterung:

(   *     + [ *  1-~    2*     2|]    )
 signum n + n * pred (twice (n mod 2))
James Wood
quelle
2

GolfScript ceiling(26*.9)=24

Golfscript verarbeitet nur Ganzzahlen. Wenden Sie also den ZBonus für insgesamt 24 Punkte an:

.{..0>2*(\)2%!2*(@*+}{ }if

Der Sonderfall 0 umfasst 8 Zeichen. Wenn wir 0 ignorieren, können wir eine 17-Punkte-Antwort haben:

..0>2*(\)2%!2*(@*+

Dieser Code verarbeitet eine Ganzzahl xüber dem Stapel wie folgt :

  • Wenn x0 ist, belasse es 0auf dem Stapel und wende keine Regeln mehr an.
  • Wenn gerade xist, negiere x.
  • Wenn xpositiv, addieren 1.
  • Wenn xnegativ ist, subtrahieren 1.

Dies verbindet logisch Sätze von 4 Zahlen in einem Zyklus, wobei fElemente des Zyklus durchquert werden und gegenüberliegende Ecken des Zyklus Negative voneinander sind. Jede Ganzzahl ist Teil von genau 1 solcher Zyklen, mit Ausnahme von 0, die in einem speziellen Fall geschrieben ist. Zum Beispiel für {-8, -7, 7, 8}:

  • 7 f -> 8
  • 8 f -> -7
  • -7 f -> -8
  • -8 f -> 7

Die einzigen relevanten Testfälle, an die ich denken konnte, waren eine negative Quote, eine negative Quote, eine positive Quote, eine positive Quote 0, und dann habe ich eingeworfen, -1und 1da ihre Nähe zu 0möglicherweise Probleme verursacht hat:

[-10 -5 -1 0 1 5 10]
{.{..0>2*(\)2%!2*(@*+}{ }if}:f;
{f f}%
-> [10,5,1,0,-1,-5,-10]

Ich bin sicher, dass das aktuelle GolfScript etwas verbessert werden kann. Es fühlt sich nicht so an, als ob es 26 Zeichen aufnehmen sollte! Würde gerne ein paar Vorschläge hören.

Ben Reich
quelle
2

Java, nur zum Spaß

Hier ist eine Implementierung, die eine tatsächliche Bijektion zwischen ℤ und ℤ² ausführt, was gleichzeitig eine ungerade Funktion ist (g (-x) == -g (x)). Es behandelt das entsprechende ℤ²-Element als komplexe Zahl, multipliziert es mit "i" und konvertiert es dann zurück zu back.

f (x) = g & supmin; ¹ (ig (x))
f (f (x)) = g & supmin; ¹ (-g (x)) = - x

Die Funktion läuft in O (1).

public class Ffn {
    public static int f(int n) {
        if (n == 0) {
            return 0;
        }
        // adjust sign
        int s = n > 0 ? 1 : -1;
        int m = n * s;
        // calculate square "radius"
        int r = (int) (Math.sqrt(2 * m - 1) + 1) / 2;
        int q = r * 2;
        // starting point
        int x = r, y = r;
        int k = q * (r - 1) + 1;

        if (m - k < q) {
            // go left
            x -= m - k;
        }
        else {
            // go left
            x -= q;
            // go down
            y -= m - k - q;
        }

        // multiply by i
        int x2 = -y * s, y2 = x * s;
        // adjust sign
        s = y2 < x2 || y2 == x2 && x2 < 0 ? -1 : 1;
        x2 *= s;
        y2 *= s;

        if (y2 == r) {
            // go left
            k += r - x2;
        }
        else {
            // go left and down
            k += q + r - y2;
        }
        return k * s;
    }

    public static void main(final String... args) {
        for (int i = 0; i < 1000000; ++i) {
            if (f(f(i)) != -i || f(f(-i)) != i) {
                System.out.println(i);
            }
        }
    }
}

PS Frohes Neues Jahr!

aditsu
quelle
Ich halte das Leerzeichen für unnötig.
Paprika
2

Python 3 - 38

Ähnlich wie @ Elch Antwort, aber f(n) == n. Funktioniert für alle ganzzahligen Werte.

f=lambda x:x*(isinstance(x,int)*2.0-1)
cjfaure
quelle
2

Perl, 33 (ohne Leerzeichen)

sub f{($=)=@_;$=-$_[0]?-$=:"$=.1"}

Bearbeiten:

  • $=.".1"verkürzt auf "$=.1"(danke ardnew).

Mathematik:

Mathematik

Ungolfed:

# script.pl
sub f {
  ($=) = @_;   # short for $= = int($_[0]); 
               # "int" is implicit in assignments to $=;
               # ($=) can be prepended by "local" to get
               # the function free of side effects.

  $= - $_[0] ? # short for $= != $_[0], check if input is integer
    -$=        # input is not an integer  
  : $= . ".1"  # input is integer
}  

# Testing
chomp;
$_ = sprintf "f(f($_)) = f(%s) = %s\n", f($_), f(f($_));

Beispiele:

perl -p script.pl
7
f(f(7)) = f(7.1) = -7
2
f(f(2)) = f(2.1) = -2
0
f(f(0)) = f(0.1) = 0
-1
f(f(-1)) = f(-1.1) = 1
-10
f(f(-10)) = f(-10.1) = 10
-1.23
f(f(-1.23)) = f(1) = 1.1
3.4
f(f(3.4)) = f(-3) = -3.1
1.0
f(f(1.0)) = f(1.1) = -1
Heiko Oberdiek
quelle
robuste Lösung - die Floating-Point-Testfälle, die Sie vorgeführt haben, sind nicht pro Spezifikation erforderlich (hätte dafür Bonuspunkte bieten müssen!). Hier ist der gleiche Algorithmus mit ein paar Bereinigungen, die um 22 Zeichen sub f{yzxzzc?-$_:x.$_}
eingehen
1
@ardnew: Danke. Ich bin jedoch anderer Meinung, dass Ihre Lösung denselben Algorithmus verwendet. Der Algorithmus sub f{yzxzzc?-$_:x.$_}ist nicht zustandsfrei, sondern verwendet einen Zustand über die Variable $_. Aus diesem Grund fist (im mathematischen Sinne) keine Funktion mehr, da je nach Zustand unterschiedliche Werte für den gleichen Eingabewert möglich sind (Wetter $_enthält a xoder nicht). Mein Algorithmus verwendet keinen Status. Die Informationen werden im Ausgabewert codiert. Ganzzahlen werden durch Addition in reelle Zahlen umgewandelt .1. Und reelle Zahlen werden mit umgeschaltetem Vorzeichen wieder in ganze Zahlen umgewandelt.
Heiko Oberdiek
Interessanterweise werden in Ihrer Implementierung aufgrund der anfänglichen Zuweisung keine Statusdaten verwendet und nicht aufgrund einer besonderen Eigenschaft von $=?
Ardnew
Ich wusste nicht, dass ich auch meine eigenen Anforderungen (die fdefiniert werden Q->Q) mit diesem xZeichen nicht erfüllt habe . auch $=.".1"kann verkürzt werden"$=.1"
ardnew
@ardnew: Die besondere Eigenschaft von $=ist nur, dass es nur ganzzahlige Zahlen akzeptiert . Das gleiche kann unter Verwendung eines gewöhnlichen Variable erreicht werden: $a=int$_[0]. Das kostet aber drei zusätzliche Bytes wegen der Funktion int.
Heiko Oberdiek
2

Julia, 26

julia> f(n::Int)=n//1
f (generic function with 1 method)
julia> f(n)=int(-n)
f (generic function with 2 methods)
julia> f(f(4))
-4

Nicht sehr wettbewerbsfähig, aber sehr julianisch, da es auf mehrfachen Versand ankommt. Es macht nur na Rational, wenn es ein Int ist, oder ein Int mit einem Minuszeichen, wenn es etwas anderes ist. Man könnte einwenden, dass dies 2 Funktionen sind, aber Julia betrachtet dies als eine Funktion mit zwei Methoden und entspricht der Definition einer Funktion mit einer if-Anweisung über den Typ von n.

gggg
quelle
Es ist nicht das, was ein Mathematiker eine Funktion nennen würde: in Julia 3==3//1kehrt zurück, kehrt trueaber f(3//1)==f(3)zurück false.
Omar
2

Süßigkeit , 20 18 Bytes

Verwendet den 3 -> 4 -> -3 -> -4 -> 3-Trick.

~A2%{|m}1A0>{+|-}.

Zum Aufrufen verwenden Sie den Schalter -i am Interpreter

Beispiel für einen Doppelaufruf:

$ candy -i 7 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> 8
$ candy -i 8 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> -7
$ candy -i -7 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> -8
$ candy -i -8 -e '~A2%{|m}1A0>{+|-}.'
program length: 18
>>> 7

Lange Form:

peekA
pushA
digit2
mod          # even/odd
if
else
  negate     # negate even numbers
endif
digit1
pushA
digit0
greater      # positive/negative
if
  add        # add two numbers from stack (original stack value, and delta)
else
  sub        # diff two numbers from stack (original stack value, and delta)
endif
retSub
Dale Johnson
quelle
2

Dyalog APL, 9 Punkte

×-⍨⊢ׯ1*⊢

Die Quelle ist 9 Bytes lang und qualifiziert sich für den Bonus (was überhaupt nicht hilft). Es wird auch die Formel aus der obersten SO-Antwort verwendet.

Lirtosiast
quelle
1

GTB , 22

@S;N,"--$x?N)→N~N#~-N&
Timtech
quelle
1

Java, 113 Bytes

Der Ansatz ist ziemlich einfach. Es endete mehr Bytes, als ich erwartet hatte, kann aber vielleicht ein bisschen heruntergolfen werden.

public class F{public static int f(int x){if(x<0)x+=-2147483647-++x;x+=1073741824;return x<0?-2147483647-++x:x;}

Es erzeugt im Grunde 4 verschiedene "Bereiche" von x, wobei die Tatsache ausgenutzt wird, dass Java Variablen glücklich herumlaufen lässt. Ich musste einige knifflige Konvertierungen für negative Zahlen durchführen, was der Hauptgrund dafür ist, dass diese größer als erwartet ausfielen.

Funktioniert für alle x außer -2147483648.

FIQ
quelle
1

Gleiche Zahlenfolge (3, 4, -3, -4, 3 ...) wie die Antwort auf das Golfscript, jedoch in Perl implementiert (42 Zeichen nach Entfernen des Leerzeichens)

sub f{($_[0]%2?1:-1)*$_[0]+($_[0]<0?-1:1)}

Besser leserlich:

sub f { ($_[0] % 2 ? $_[0] : -$_[0] ) + ( $_[0] < 0 ? -1 : 1 ) }

Oder noch besser lesbar:

sub f {
  my $n = shift;
  my $sign = $n >= 0 ? 1 : -1;
  # note that in perl $n % 2 is the same as int($n) % 2
  if( $n % 2 ) {
    # odd: add one to magnitude
    return $n + $sign
  } else {
    # even: subtract one from magnitude then invert
    return -($n - $sign)
  }
}

Ausgabe:

ski@anito:~/mysrc/.../acme$ echo 3 | perl -e 'sub f{($_[0]%2?1:-1)*$_[0] + ($_[0]<0?-1:1)}; my $x = <>; for(0..10) { print "$_: $x\n"; $x = f($x); }'
0: 3
1: 4
2: -3
3: -4
4: 3
5: 4
6: -3
7: -4
8: 3
9: 4
10: -3
Skibrianski
quelle
Das obige funktioniert auch für Nicht-Ganzzahlen: ski @ anito: ~ / mysrc /.../ acme $ echo 1.1234 | perl -e 'sub f {($ _ [0]% 2? 1: -1) * $ _ [0] + ($ _ [0] <0? -1: 1)}; mein $ x = <>; für (0..4) {print "$ _: $ x \ n"; $ x = f ($ x); } '0: 1.1234 1: 2.1234 2: -1.1234 3: -2.1234 4: 1.1234
Skibrianski
1

Sed, 25 Bytes.

|sed s/0+/0-/|sed s/^/0+/

Verwendungszweck:

$ echo 1.23 |sed s/0+/0-/|sed s/^/0+/
0+1.23
$ echo 0+1.23 |sed s/0+/0-/|sed s/^/0+/
0+0-1.23
Ken A
quelle
1

Matlab, 26 Zeichen

f=@(n) (n<0)-(n<0)-n*(-1)^n
bla
quelle
2
Dies ist keine gültige Antwort, da die Domäne und die Codomäne der Funktion nicht komplex sein dürfen.
Wrzlprmft
Oh, tut mir leid ... Ich habe gerade den Titel gelesen und war nicht so vorsichtig ... Mal sehen, ob ich das etwas
ändern
1

C ++ - 63 55.8

So sieht der Code aus:

int f(int n){return (n&45056?n^45056:n|45056)*(n&45056?-1:1);}

Es funktioniert nicht bei Ganzzahlen, deren viertes Byte gleich 0xB ist, da dieser Wert verwendet wird, um die Durchläufe zu verfolgen. Andernfalls funktioniert für jedes Mitglied von Z, einschließlich Null.

Darkgamma
quelle
kannst du das erklären Auf den ersten Blick sieht es so aus, als ob Sie einen Zähler für Anrufe fmit einer statischen Variablen führen. aber worum geht es dann sqrt?
Ardnew
Ich scheine die Frage falsch verstanden zu haben; dachte, dass eine statische Variable in Ordnung sei, da C ++ eine stapelorientierte Sprache ist, aber ich werde den Code korrigieren. Ansonsten habe ich keine Ahnung warum ich es brauche, sqrtda es sowieso beim Type Casting abgerundet wird. Ich werde es so umgestalten, dass es ohne die statische Variable funktioniert.
Darkgamma
Ich habe keine Ahnung, woher Sie die haben 55.8, aber Ihr aktueller Code ist 62 Bytes lang. Edit: Egal, ich habe die Frage nicht richtig gelesen.
Nyuszika7h
Die Einschränkung, dass das vierte Byte nicht gleich 0xB sein kann, macht dies leider zu einer ungültigen Antwort auf die Abfrage, die erfordert, dass (mindestens) alle Ganzzahlen bearbeitet werden.
Paprika
1

Aktualisiert mit einer von Synthetica bereitgestellten Funktion (offensichtlich diejenige, die dies jetzt gutschreiben sollte)

Sprache: Python

Anzahl der Zeichen: 41 einschließlich Leerzeichen

f=lambda x:-float(x) if str(x)==x else`x`
HolySquirrel
quelle
Bitte geben Sie auch den Namen der von Ihnen verwendeten Sprache und die Anzahl der Zeichen an.
ProgramFOX
Mir gefällt, wie das auch mit Nicht-Ganzzahlen funktioniert. Gut gemacht. :)
cjfaure
f=lambda x:-float(x) if str(x)==x else`x`ist ziemlich viel kürzer: 41 einschließlich Leerzeichen
ɐɔıɐɔuʎs
Danke Synthetica, ich wusste nicht einmal etwas über den Backticks-Trick! : D
HolySquirrel
Bei Ganzzahlen wird feine Zeichenfolge zurückgegeben. Die Spezifikation besagt, dass eine rationale Zahl zurückgegeben werden muss.
Omar
1

Prolog, 36 Bytes

Code:

X*Y:-X//1=:=X,Y is 0.5+X;Y is 0.5-X.

Erklärt:

Dyadic predicate which converts integers to floats and floats back to negated integers.

Beispiel:

10*X.
X = 10.5

10*Y,Y*X.
X = -10,
Y = 10.5
Emigna
quelle
1

Javascript ES6, 27 26 Bytes

a=>a%1?-Math.floor(a):a+.2
SuperJedi224
quelle
1

Mouse-2002 , 21 19 12 Bytes

$A1%[1%_|1%]

Definiert eine Funktion A; Rufen Sie es wie #A,#A,?;;folgt auf (der Benutzer wartet, bis er eine beliebige Nummer eingibt). Alternativ rufen Sie es wie in #A,#A,n;;dem neine beliebige Zahl.

Katze
quelle
1

Julia, 21

f(x)=(1-2(1>x>-1))/2x

Dann

julia> f(f(12//1))
-12//1

p // q ist Julias wörtliche Notation rationaler Zahlen.

mschauer
quelle