Quando (x == x + 2)? [chiuso]


90

La sfida: definire xin modo tale che l'espressione (x == x+2)valuti come vera.

Ho taggato la domanda con C, ma le risposte in altre lingue sono benvenute, purché siano creative o evidenzino un aspetto interessante della lingua.

Intendo accettare una soluzione C, ma altre lingue possono ottenere il mio voto.

  1. Corretto: funziona su implementazioni conformi agli standard. Eccezione: assumere un'implementazione dei tipi di base, se si tratta di un'implementazione comune (ad esempio supponendo che intil complemento a 32 bit 2) sia OK.
  2. Semplice: dovrebbe essere piccolo, utilizzare le funzioni linguistiche di base.
  3. Interessante - è soggettivo, lo ammetto. Ho alcuni esempi di ciò che considero interessante, ma non voglio dare suggerimenti. Aggiornamento : evitare il preprocessore è interessante.
  4. Veloce: verrà accettata la prima buona risposta.

Dopo aver ottenuto 60 risposte (non mi sarei mai aspettato una simile previsione), potrebbe essere utile riassumerle.

Le 60 risposte si dividono in 7 gruppi, 3 dei quali possono essere implementati in C, il resto in altre lingue:

  1. Il preprocessore C. #define x 2|0è stato suggerito, ma ci sono molte altre possibilità.
  2. Virgola mobile. Grandi numeri, infinito o NaN funzionano tutti.
  3. Puntatore aritmetico. Un puntatore a un'enorme struttura provoca l'aggiunta di 2 da avvolgere.

    Il resto non funziona con C:

  4. Sovraccarico dell'operatore - A +che non viene aggiunto o ==che restituisce sempre true.
  5. Effettuare xuna chiamata di funzione (alcune lingue lo consentono senza la x()sintassi). Quindi può restituire qualcos'altro ogni volta.
  6. Un tipo di dati a un bit. Poi x == x+2 (mod 2).
  7. Modifica 2: alcune lingue ti consentono di assegnarle 0.

29
Perché 4. Quick? Intendi "Chiunque ne conosca uno ed è abbastanza fortunato da leggere prima questa domanda"?
Luc

6
@ugoren Lascia votare la community (e vota per quelli che ti piacciono), quindi scegli la risposta migliore dopo circa 7 giorni :)
Luc

3
Per quanto riguarda la possibilità 2: NaN non funziona. NaN + 2 è di nuovo NaN, ma NaN == NaN è falso.
Martin B,

2
La soluzione Scala, dove x è un set contenente '2' e + significa add to Setdalla libreria standard, senza ridefinire +te stesso, non rientra in queste 7 categorie, IMHO.
Utente sconosciuto il

2
Perché questa domanda e tutte le risposte Community Wiki?
mbomb007,

Risposte:


71
main()
{
double x=1.0/0.0;
printf("%d",x==x+2);
}

Uscite 1.

Link: http://ideone.com/dL6A5


7
float x=1./0è un po 'più corto e forse più elegante. Comunque, questa è sicuramente la prima buona risposta.
ugoren,

1
Ahh buon vecchio dividere per zero. Mi ci è voluto più tempo per capire di quanto mi piacerebbe ammettere. haha
Concedi il

Argh, ho pensato anche a questo, ma su Windows non si compila quindi l'ho lasciato cadere. :( +1 però
Tudor

x = 1e999 è un altro modo per farlo.
shiona,

4
@shiona float x=1e20sarebbe abbastanza
l0n3sh4rk

125

Fortran IV:

2=0

Dopodiché ogni costante 2 nel programma è zero. Fidati di me, l'ho fatto (ok, 25 anni fa)


23
Una ragione in più per non toccare mai Fortran.
C0deH4cker,

3
Almeno lancia un avvertimento?
Michael Stern,

15
@MichaelStern ATTENZIONE: STAI CAMBIANDO IL VALORE DI 2!
Cruncher,

100

Questo sembra funzionare:

#define x 2|0

Fondamentalmente, l'espressione viene espansa in (2|0 == 2|(0+2)). È un buon esempio del perché si dovrebbero usare le parentesi quando si definiscono le macro.


3
Certamente funziona e penso che sia la soluzione più elegante basata sul preprocessore. Ma penso che farlo senza il preprocesor sia più interessante.
ugoren,

Sono solo io o dovrei 2|(0+2)essere 1?
phunehehe,

1
@phunehehe: |è bit a bit OR ; ||è OR logico.
PleaseStand,

20
Questo in qualche modo mi ricorda i tavolini Bobby.
vsz,

1
@rakeshNS: ho aggiunto il set di parentesi extra per mostrare la precedenza dell'operatore . Ecco perché ho detto "Fondamentalmente".
PleaseStand,

79

Brainfuck

x

Questo ovviamente allunga un po '"valuta come vero", perché in Brainfuck nulla in realtà valuta nulla: manipoli solo un nastro. Ma se ora aggiungi la tua espressione

x
(x == x+2)

il programma è equivalente a

+

(perché tutto tranne che <>+-[],.un commento). Che non fa altro che incrementare il valore dove siamo ora. Il nastro è inizializzato con tutti gli zeri, quindi finiamo con un 1 sulla posizione del cursore, che significa "vero": se ora avessimo iniziato una sezione condizionale con [], entrerebbe in / loop.


12
+1 Deve essere la piegatura più creativa delle regole.
ninjalj,

3
Perché hai bisogno del x?
James,

3
@James La domanda dice di definire, xquindi qui xè definito come x.
user80551

1
@James la risposta non fa needaltro che il+
Cruncher

56

F #

let (==) _ _ = true
let x = 0
x == (x + 2) //true

13
Mi piace questa. Invece di giocoleria, ridefinisci semplicemente il significato di ==
evilcandybag,

4
Aspetta, l'operatore di uguaglianza in F # non è semplicemente =? ==non è nemmeno definito per impostazione predefinita.
Jwosty,

50

C

int main() { float x = 1e10; printf("%d\n", x == x + 2); }

Nota: potrebbe non funzionare se FLT_EVAL_METHOD != 0(vedi commenti sotto).


24
+1 per le applicazioni del mondo reale. Troppe persone non capiscono la matematica in virgola mobile.
Tim S.

1
@ mbomb007: Penso che siano diversi: la risposta a cui ti colleghi si basa INF + 2 == INF, mentre la mia risposta utilizza un singolo galleggiante di precisione che è abbastanza grande da far sì che 2 sia inferiore a un ULP.
Paolo R,

2
@ mbomb007: Penso anche che siano molto diversi - ∞ + 2 = ∞è qualcosa che chiunque potrebbe capire e non dipende da nulla di specifico del computer, mentre l'aggiunta di 2 a un numero concreto e che non ha alcun effetto è un po 'più sorprendente e specifico per la precisione limitata di computer e più interessante IMHO
GoatInTheMachine,

1
Questo può facilmente fallire quando FLT_EVAL_METHOD == 1la matematica viene eseguita come double. Raccomanda un valore FP più grande che sicuramente supererà anche la long doubleprecisione come1.0e37f
chux

1
@chux: grazie per la conferma - è sicuramente qualcosa che potrei aver bisogno di fare attenzione in futuro, poiché gran parte del mio codice finisce per essere multipiattaforma.
Paul R,

36

C #

class T {
  static int _x;
  static int X { get { return _x -= 2; } }

  static void Main() { Console.WriteLine(X == X + 2); }
}

Non uno short ma un po 'elegante.

http://ideone.com/x56Ul


4
Dannazione, ho appena ricevuto un badge "Nice Answer" per questo post. Scherzi a parte, ottenere badge per roba MALE ?! Non farlo a casa !
fjdumont,

È malvagio, ma è così bello ...
Kevin

32

Scala: { val x = Set(2); (x == x + 2) }


Haskell: Definisci ℤ / 2ℤ sugli Boolean:

instance Num Bool where
    (+) = (/=)
    (-) = (+)
    (*) = (&&)
    negate = id
    abs    = id
    signum = id
    fromInteger = odd

quindi per qualsiasi x :: Boolavremox == x + 2 .

Aggiornamento: grazie per le idee nel commento, ho aggiornato l'istanza di conseguenza.


3
Puoi semplificare:fromInteger = odd
Rotsor

1
Inoltre (+)può essere definito come (/=)credo.
MatrixFrog,

2
Una soluzione più breve sarebbe quella di creare un'istanza per ().
Thomas Eding,

31

Pitone

class X(int):__add__=lambda*y:0
x=X()

# Then (x == x+2) == True

Bello. Tutte le lingue che supportano il sovraccarico dell'operatore possono utilizzare soluzioni simili, ma C non è una di queste.
ugoren,

Funziona anche con sovraccarico __cmp__come class X(int):__cmp__=lambda*x:0(o __eq__anche se leggermente più lungoclass X(int):__eq__=lambda*x:True
dr jimbob,

Un paio di personaggi più corti se non si estende dall'int ..class X:__add__=lambda s,o:s
Doboy,

Posso chiedere cosa fa quella moltiplicazione?
Seequ,

2
@TheRare non è in realtà moltiplicazione. Poiché di __add__solito vengono forniti più argomenti ( lambda x,y:), salvo alcuni caratteri usando * per comprimere tutti gli argomenti in un tuple ( lambda *y:). Vedi i documenti per maggiori informazioni.
GRC

31

GNU C supporta strutture senza membri e dimensioni 0:

struct {} *x = 0;

2
Molto bella! Ho pensato all'aritmetica del puntatore con dati molto grandi che hanno portato a un avvolgimento, ma non ho pensato al contrario.
ugoren,

26

PHP:

$x = true;
var_dump($x == $x+2);

O:

var_dump(!($x==$x+2));

Produzione:

bool (true)


1
In realtà stavo cercando di trovare questa semplice e semplice risposta PHP, ma tu mi hai battuto.
PleaseStand,

25

È un'idea sbagliata comune che in C lo spazio bianco non abbia importanza. Non riesco a immaginare che qualcuno non l'abbia inventato in GNU C:

#include <stdio.h>
#define CAT_IMPL(c, d) (c ## d)
#define CAT(c, d) CAT_IMPL(c, d)
#define x CAT(a, __LINE__)

int main()
{
    int a9 = 2, a10 = 0;
    printf("%d\n", x ==
        x + 2);
    return 0;
}

Stampe 1.


Bello, anche se forse non tecnicamente valido ( x == x+2è ancora falso). Ma una volta che hai sollevato l'idea, penso che #define x -2*__LINE__sia più elegante.
ugoren,

3
@ugoren grazie! Se vuoi che tutto questo sia su una riga, usa COUNTER invece di LINE - richiede GCC 4.3+.
H2CO3,

1
_CATè un identificativo riservato. Tutto ciò che inizia con il trattino basso e la lettera maiuscola è riservato in C.
Konrad Borowski,

@xfix è esattamente giusto, aggiornato per rimuovere UB.
H2CO3,

20

C

È più interessante senza usare le macro e senza abusare dell'infinito.

/////////////////////////////////////
// At the beginning                 /
// We assume truth!                 /

int truth = 1;
int x = 42;

/////////////////////////////////////
// Can the truth really be changed??/
truth = (x == x + 2);

/////////////////////////////////////
// The truth cannot be changed!     /
printf("%d",truth);

Provalo se non ci credi!


1
0. No, ancora non ci credo.
Salterio

@MSalters: quale compilatore usi? È possibile che le trigrafi siano disabilitate.
vsz,

VS2010. È possibile che le trigrafi siano disabilitate per impostazione predefinita. Sia che la concatenazione di linea o quella non funzionino??\
MSalters,

MSalter: la trigrafia ??\ deve essere convertita in un singolo \ , quindi non c'è ??\ . Alcuni compilatori moderni tuttavia forniscono avvisi per impostazione predefinita sia alle trigrafi che alle concatenazioni di linee anche se abilitate.
vsz,

18

Matematica:

x /: x + 2 := x
x == x + 2

Penso che questa soluzione sia nuova perché utilizza il concetto di Up Values ​​di Mathematica .

MODIFICARE:

Sto espandendo la mia risposta per spiegare cosa significano Up Values ​​in Mathematica .

La prima riga essenzialmente ridefinisce l'aggiunta per il simbolo x. Potrei archiviare direttamente tale definizione nella funzione globale associata al +simbolo, ma una tale ridefinizione sarebbe pericolosa perché la ridefinizione potrebbe propagarsi in modo imprevedibile attraverso gli algoritmi integrati di Mathematica .

Invece, usando il tag x/:, ho associato la definizione al simbolo x. Ora, ogni volta che Mathematica vede il simbolo x, controlla se viene operato dall'operatore addizione +in uno schema della forma in x + 2 + ___cui il simbolo ___indica una possibile sequenza nulla di altri simboli.

Questa ridefinizione è molto specifica e utilizza le ampie capacità di abbinamento dei modelli di Mathematica . Ad esempio, l'espressione x+y+2ritorna x+y, ma l'espressione x+3ritorna x+3; perché nel primo caso, il modello potrebbe essere abbinato, ma nel secondo caso, il modello non potrebbe essere abbinato senza ulteriore semplificazione.


1
Penso che dovresti spiegare cosa fa. Molte persone non conoscono Mathematica (o cosa sono i valori positivi).
ugoren,

1
Grazie @ugoren, passo la maggior parte del mio tempo sul sito Web di Mathematica Stack Exchange, quindi ho dimenticato di spiegare cosa ha reso significativo il mio esempio. Ho fatto una modifica che spiega il concetto nel modo più conciso possibile.
Carl Morris,

17

Javascript:

var x = 99999999999999999;
alert(x == x+2);​

Test Fiddle


2
È possibile utilizzare Infinity, oppure -Infinity, e per questo motivo è possibile utilizzare il collegamento di x = 1/0.
zzzzBov,

6
@zzzzBov: è sicuramente un codice golf migliore. Ho scelto (99999999999999999 == 99999999999999999+2)perché penso che sia un po 'più interessante di (Infinity == Infinity+2), anche se come dice l'OP, "è soggettivo" :)
Briguy37

Questo è l'unico caso del mondo reale in cui ho visto un controllo come questo per una buona ragione (oltre alla programmazione degli enigmi): una funzione di facoltà (basata su float) stava controllando il suo input per essere troppo grande per essere contato -1e ricorsivo . Il linguaggio stesso era Python, ma in questo caso non importa.
Alfe,

5
@NicoBurns not ture :(
ajax333221

2
@NicoBurns, produce quel codice nella console false; ovunque tu stia ottenendo tali informazioni su JS è sbagliato e non dovrebbe essere attendibile.
zzzzBov

17

schema

(define == =)
(define (x a b c d) #t)
(x == x + 2)
;=> #t

Bello. Lo schema è (x == x + 2)simile a quello di C, ma significa una cosa totalmente diversa.
ugoren,

1
Ora fallo per (= x 2).
Joe Z.

(define (x a b c d) #t):)
Cruncher,

@ugoren questo è definito per fare questo da questo programma. x è semplicemente il nome di una funzione qui. E così è ==
Cruncher,


16

Qui è una soluzione per JavaScript che non sfrutta le Infinitye -Infinitybordi casi di virgola mobile aggiunta. Questo non funziona né in Internet Explorer 8 e versioni precedenti né nella modalità rigorosa ES5 di opt-in. Non definirei l' withaffermazione e le funzioni particolarmente "avanzate".

with ({ $: 0, get x() {return 2 * this.$--;} }) {
    console.log(x == x+2);
}

Modificato per aggiungere: il trucco sopra è possibile anche senza usare withe get, come notato da Andy E in Suggerimenti per giocare a golf in JavaScript e anche da jncraton in questa pagina:

var x = { $: 0, valueOf: function(){return 2 * x.$++;} };
console.log(x == x+2);

Un bel concetto: fare xuna chiamata di funzione, sebbene sembri una lettura variabile. Presumo un ordine di valutazione da sinistra a destra, ma va bene poiché è specificato in JS (a differenza di C).
ugoren,

14

Quanto segue non è conforme agli standard C , ma dovrebbe funzionare praticamente su qualsiasi piattaforma a 64 bit:

int (*x)[0x2000000000000000];

Ottimo in linea di principio, ma sembra essere implementato in modo errato. xsarebbe incrementato con incrementi di 2 ^ 61, quindi x + 8sarebbe uguale x.
ugoren,

@ugoren, funziona per me, su Linux con 4 byte int.
han

Hai assolutamente ragione. Ho perso il fatto che è una serie di intno char.
ugoren,

10

Saggio:

x=Mod(0,2)
x==x+2

restituisce True

In generale per GF (2 ** n) è sempre vero che x = x + 2 per qualsiasi x

Questo non è un bug o un problema con overflow o infinito, in realtà è corretto


1
Lo stesso trucco funziona con PARI / GP
Hagen von Eitzen,

10

Lisp comune

* (defmacro x (&rest r) t)
X
* (x == x+2)
T

È abbastanza facile quando xnon deve essere un valore reale.


8

APL (Dyalog)

X←1e15
X=X+2

APL non ha nemmeno l'infinito, è solo che i float non sono abbastanza precisi da dire la differenza tra 1.000.000.000.000.000e 1.000.000.000.000.002. Questo è, per quanto ne so, l'unico modo per farlo in APL.


Mi piace molto perché è la prima risposta a sfruttare la precisione del galleggiante.
AndrewKS,

1
@AndrewKS: In realtà Paul R era un po 'prima.
MSalters,

8

Perl 6

Sono sorpreso di non aver visto questa soluzione prima. Comunque, la soluzione è: cosa succede se lo xè 0e 2subito? my \xin questo esempio dichiara la variabile sigilless - questa domanda pone x, non in stile Perl $x. È un ?? !!operatore ternario.

$ perl6 -e 'my \x = 0|2; say x == x + 2 ?? "YES" !! "NO"'
YES

Ma...

$ perl6 -e 'my \x = 0|2; say x == x + 3 ?? "YES" !! "NO"'
NO

xsono più valori contemporaneamente. xè uguale 0e 2immediato. x + 2è uguale 2e 4immediato. Quindi, logicamente sono uguali.


8

Python 2.X (Uso della ridefinizione di numeri interi (memorizzati nella cache)

Ho notato che tutte le risposte di Python hanno classi definite che ridefiniscono il + operatore. Risponderò con una dimostrazione ancora più di basso livello della flessibilità di Python. (Questo è uno snippet specifico di python2)

In Python, gli interi sono memorizzati più o meno in questo modo in C:

typedef struct {            // NOTE: Macros have been expanded
    Py_ssize_t ob_refcnt;
    PyTypeObject *ob_type;
    long ob_ival;
} PyIntObject;

Cioè, una struttura con una size_t, void *e longoggetto, in questo ordine.
Una volta che usiamo, e quindi memorizziamo nella cache un numero intero, possiamo usare il ctypesmodulo di Python per ridefinire quel numero intero, in modo che non solo lo faccia x == x+2, ma2 == 0

import ctypes
two = 2 # This will help us access the address of "2" so that we may change the value

# Recall that the object value is the third variable in the struct. Therefore,
# to change the value, we must offset the address we use by the "sizeof" a 
# size_t and a void pointer
offset = ctypes.sizeof(ctypes.c_size_t) + ctypes.sizeof(ctypes.c_voidp)

# Now we access the ob_ival by creating a C-int from the address of 
# our "two" variable, offset by our offset value.
# Note that id(variable) returns the address of the variable.
ob_ival = ctypes.c_int.from_address(id(two)+offset)

#Now we change the value at that address by changing the value of our int.
ob_ival.value = 0

# Now for the output
x = 1
print x == x+2
print 2 == 0

stampe

True
True

7

Perl

usando una subroutine con effetti collaterali su una variabile del pacchetto:

sub x () { $v -= 2 }
print "true!\n" if x == x + 2;

Produzione: true!


1
sub x{}"funziona" pure .. (almeno nel mio 5.10.1), ma non riesco a capire perché ..
mykhal

2
Perché sub x{}restituisce undef o un elenco vuoto, entrambi i quali sono uno zero numerico. E x + 2 viene analizzato come x (+2). perl -MO=Deparserivelaprint "true\n" if x() == x(2);
Perleone il

Fantastico, @mykhal e @Perleone!
ricorda il

7

Pitone

lo sfruttamento della precisione in virgola mobile rende tutto molto semplice.

>>> x = 100000000000000000.0
>>> (x == x+2)
True

Per renderlo meno specifico del sistema è necessaria un'importazione extra

>>> import sys
>>> x = float(sys.maxint + 1)
>>> (x == x+2)
True

Questo dovrebbe funzionare anche in altre lingue. Questo funziona perché le rappresentazioni di 100000000000000000.0 e 100000000000000002.0 sono esattamente le stesse per la macchina, a causa del modo in cui i punti fluttuanti sono rappresentati all'interno della macchina. vedi http://en.wikipedia.org/wiki/IEEE_floating_point per ulteriori informazioni.

Quindi questo funzionerà fondamentalmente in qualsiasi lingua che ti consenta di aggiungere numeri interi ai float e avere il risultato di essere un float.


6

Ecco una soluzione per C ++ basata sul sovraccarico dell'operatore. Si basa sulla conversione implicita da an enuma an int.

#include <iostream>

enum X {};
bool operator==(X x, int y)
{
    return true;
}

int main()
{
    X x;
    std::cout << std::boolalpha << (x == x+2) << std::endl;
    return 0;
}

Puoi usare std::boolalphainvece di ?:.
Jon Purdy,

5

So che è una sfida del codice ... ma l'ho giocata a golf. Scusate.

Rubino - 13 personaggi - Soluzione infinita

x=1e17;x==x+2

ritorna vero

Rubino - 41 caratteri - Op Soluzioni di sovraccarico

class Fixnum;def + y;0 end end;x=0;x==x+2

o

class A;def self.+ y;A end end;x=A;x==x+2

5

Se va bene sfruttare un po 'la domanda, aggiungerò un po' di nuovo Java. Il trucco non è certo nuovo, ma forse interessante che ciò sia possibile in Java.

static void pleaseDoNotDoThis() throws Exception {
    Field field = Boolean.class.getField("FALSE");
    field.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, true);
}

public static void main(String args[]) throws Exception {
    pleaseDoNotDoThis();
    doit(1);
    doit("NO");
    doit(null);
    doit(Math.PI);
}

static void doit(long x) {
    System.out.format("(x == x + 2) = (%d == %d) = %s\n", x, x+2, (x == x + 2));
}

static void doit(String x) {
    System.out.format("(x == x + 2) = (%s == %s) = %s\n", x, x+2, (x == x + 2));
}

static void doit(double x) {
    System.out.format("(x == x + 2) = (%f == %f) = %s\n", x, x+2, (x == x + 2));
}

E i risultati:

(x == x + 2) = (1 == 3) = true
(x == x + 2) = (NO == NO2) = true
(x == x + 2) = (null == null2) = true
(x == x + 2) = (3,141593 == 5,141593) = true
(x == x + 2) = (Infinity == Infinity) = true

4

Questa soluzione VBScript funziona in modo simile alla mia soluzione JavaScript. Non ho usato un preprocessore, ma la soluzione sembra banale.

y = 0
Function x
x = y
y = -2
End Function

If x = x + 2 Then
    WScript.Echo "True"
Else
    WScript.Echo "False"
End If

Avevo intenzione di pubblicare la stessa soluzione in ruby, fino a quando non ho visto la tua: è possibile perché entrambe le lingue consentono l'omissione delle parentesi.
Waldrumpus,
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.