Quand fait-on (x == x + 2)? [fermé]


90

Le défi: définir xde manière à ce que l'expression (x == x+2)soit évaluée comme vraie.

J'ai marqué la question avec C, mais les réponses dans d'autres langues sont les bienvenues, à condition qu'elles soient créatives ou mettent en valeur un aspect intéressant de la langue.

J'ai l'intention d'accepter une solution C, mais d'autres langues peuvent obtenir mon vote.

  1. Correct - fonctionne sur les implémentations conformes aux normes. Exception - En supposant une implémentation des types de base, s'il s'agit d'une implémentation courante (en supposant par exemple intun complément de 32 bits), tout va bien.
  2. Simple - devrait être petit, utilisez les fonctionnalités de base du langage.
  3. Intéressant - c'est subjectif, je l'avoue. J'ai quelques exemples de ce que je considère intéressant, mais je ne veux pas donner d'indices. Mise à jour : Éviter le préprocesseur est intéressant.
  4. Rapide - La première bonne réponse sera acceptée.

Après avoir obtenu 60 réponses (je ne m'attendais pas à une telle préparation), il peut être bon de les résumer.

Les 60 réponses se divisent en 7 groupes, dont 3 peuvent être implémentés en C, le reste en autres langues:

  1. Le préprocesseur C #define x 2|0a été suggéré, mais il y a beaucoup d'autres possibilités.
  2. Point flottant. Les grands nombres, l'infini ou NaN fonctionnent tous.
  3. Pointeur arithmétique. Un pointeur sur une énorme structure provoque l'ajout de 2 à boucler.

    Le reste ne fonctionne pas avec C:

  4. Surcharge d'opérateur - A +qui n'ajoute pas ou ==qui retourne toujours vrai.
  5. Faire xun appel de fonction (certaines langues le permettent sans la x()syntaxe). Ensuite, il peut retourner quelque chose à chaque fois.
  6. Un type de données à un bit. Puis x == x+2 (mod 2).
  7. Changer 2- certaines langues vous permettent de l’affecter 0.

29
Pourquoi 4. Quick? Vous voulez dire "Celui qui en connaît un et qui a la chance de lire cette question en premier"?
Luc

6
@ugoren Laissez la communauté voter (et votez vous-même pour celles que vous aimez), puis choisissez la réponse après 7 jours ou plus :)
Luc

3
En ce qui concerne la possibilité 2: NaN ne fonctionne pas . NaN + 2 est à nouveau NaN, mais NaN == NaN est faux.
Martin B

2
La solution Scala, où x est un ensemble contenant '2', et + signifie add to Setpar la bibliothèque standard, sans +vous redéfinir , ne rentre pas dans ces 7 catégories, à mon humble avis.
utilisateur inconnu

2
Pourquoi cette question et toutes les réponses au Wiki de la communauté?
mbomb007

Réponses:


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

Sorties 1.

Lien: http://ideone.com/dL6A5


7
float x=1./0est un peu plus court et peut-être plus élégant. Mais de toute façon, c’est sûrement la première bonne réponse.
Ugoren

1
Ahh bon vieux diviser par zéro. Cela m'a pris plus de temps à comprendre que je ne voudrais l'admettre. haha
Grant

Argh, je pensais aussi à cela, mais sous Windows, la compilation n’est pas compilée, je l’ai donc laissé tomber. :( +1 cependant
Tudor

x = 1e999 est un autre moyen de le faire.
Shiona

4
@shiona float x=1e20serait assez
l0n3sh4rk

125

Fortran IV:

2=0

Après cela, chaque constante 2 du programme vaut zéro. Croyez-moi, je l'ai fait (ok, il y a 25 ans)


23
Raison de plus pour moi de ne jamais toucher Fortran.
C0deH4cker le

3
Est-ce au moins un avertissement?
Michael Stern

15
@MichaelStern AVERTISSEMENT: VOUS CHANGEZ LA VALEUR DE 2!
Cruncher

100

Cela semble fonctionner:

#define x 2|0

Fondamentalement, l'expression est étendue à (2|0 == 2|(0+2)). C'est un bon exemple de la raison pour laquelle il convient d'utiliser des parenthèses lors de la définition de macros.


3
Cela fonctionne certainement, et je pense que c'est la solution la plus élégante basée sur le pré-processeur. Mais je pense que le faire sans le préprocesseur est plus intéressant.
Ugoren

Est-ce juste moi ou devrait 2|(0+2)être 1?
Phunehehe

1
@phunehehe: |est bitwise OU ; ||est logique OU.
PleaseStand

20
Cela me rappelle en quelque sorte les petites tables de Bobby.
vsz

1
@rakeshNS: J'ai ajouté le jeu supplémentaire de parenthèses pour montrer la priorité des opérateurs . C'est pourquoi j'ai dit "fondamentalement".
PleaseStand

79

Brainfuck

x

Bien entendu, cela étire un peu "vrai", car dans Brainfuck rien n’est évalué comme quoi que ce soit - vous ne faites que manipuler une bande. Mais si vous ajoutez maintenant votre expression

x
(x == x+2)

le programme est équivalent à

+

(car tout sauf <>+-[],.un commentaire). Ce qui ne fait qu’incrémenter la valeur actuelle. La bande est initialisée avec tous les zéros, nous nous retrouvons donc avec un 1 sur la position du curseur, ce qui signifie "vrai": si nous commencions maintenant avec une section conditionnelle [], elle entrerait / bouclerait.


12
+1 Doit être la plus créative des règles
Ninjalj

3
Pourquoi avez-vous besoin de x?
James

3
@ James La question dit de définir xainsi xest défini comme x.
user80551

1
@ James la réponse ne fait needrien sauf le+
Cruncher

56

F#

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

13
J'aime celui la. Au lieu de jongler avec les chiffres, redéfinissez simplement le sens de ==
evilcandybag le

4
Attendez, l'opérateur d'égalité dans F # n'est-il pas simplement =? ==n'est même pas défini par défaut.
Jwosty

50

C

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

Remarque: peut ne pas fonctionner si FLT_EVAL_METHOD != 0(voir les commentaires ci-dessous).


24
+1 pour les applications du monde réel. Trop de gens ne comprennent pas les mathématiques à virgule flottante.
Tim S.

1
@ mbomb007: Je pense qu'ils sont différents - la réponse à laquelle vous vous associez repose sur INF + 2 == INFma réponse, alors que ma réponse utilise un flottant simple précision suffisamment grand pour que 2 soit inférieur à un ULP.
Paul R

2
@ mbomb007: Je pense aussi qu'ils sont très différents - ∞ + 2 = ∞c'est quelque chose que tout le monde peut comprendre et ne dépend de rien de spécifique à l'ordinateur, alors que l'ajout de 2 à un nombre concret et qu'il n'a aucun effet est un peu plus surprenant et spécifique à la précision limitée des ordinateurs, et plus intéressant à
mon humble avis

1
Cela peut facilement échouer lorsque FLT_EVAL_METHOD == 1le calcul est fait comme double. Recommandez une valeur de PF plus grande, supérieure à la long doubleprécision1.0e37f
chux

1
@ chux: merci pour la confirmation - c'est certainement une chose que je devrais peut-être surveiller à l'avenir, car une grande partie de mon code finit par être multi-plateforme.
Paul R

36

C #

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

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

Pas un shortie, mais un peu élégant.

http://ideone.com/x56Ul


4
Dang it, vient de recevoir un badge "Nice Answer" pour ce post. Sérieusement, obtenir des badges pour EVIL stuff?! Ne fais pas ça à la maison !
Fjdumont

C'est diabolique, mais c'est tellement beau ...
Kevin

32

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


Haskell: Définissez ℤ / 2ℤ sur Booleans:

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

alors pour tout x :: Boolnous aurons x == x + 2.

Mise à jour: Merci pour les idées en commentaire, j'ai mis à jour l'instance en conséquence.


3
Vous pouvez simplifier:fromInteger = odd
Rotsor le

1
Aussi (+)peut être défini comme (/=)je crois.
MatrixFrog

2
Une solution plus courte consisterait à créer une instance pour ().
Thomas Eding

31

Python

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

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

Agréable. Toutes les langues prenant en charge la surcharge des opérateurs peuvent utiliser des solutions similaires, mais C n'en fait pas partie.
Ugoren

__cmp__class X(int):__cmp__=lambda*x:0__eq__class X(int):__eq__=lambda*x:True
Fonctionne

Quelques personnages plus courts si vous ne prolongez pas d'int ..class X:__add__=lambda s,o:s
Doboy

Puis-je demander ce que cette multiplication fait?
seequ

2
@TheRare ce n'est pas réellement la multiplication. Étant __add__donné que plusieurs arguments ( lambda x,y:) sont normalement attribués , je sauvegarde certains caractères en utilisant * pour regrouper tous les arguments dans un tuple ( lambda *y:). Voir la documentation pour plus d'informations.
grc

31

GNU C supporte les structures sans membres et de taille 0:

struct {} *x = 0;

2
Très agréable! J'ai pensé à l'arithmétique de pointeur avec de très grandes données conduisant à un enveloppement, mais je n'ai pas pensé au contraire.
Ugoren

26

PHP:

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

Ou:

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

Sortie:

bool (true)


1
En fait, j'essayais de trouver cette réponse très simple en PHP, mais vous m'avez battu.
PleaseStand

25

C'est une idée fausse commune qu'en C, l'espace n'a pas d'importance. Je ne peux pas imaginer que quelqu'un n'ait pas proposé cela dans 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;
}

Impressions 1.


Bien, bien que peut-être pas techniquement valide ( x == x+2est toujours faux). Mais une fois que vous avez soulevé l'idée, je pense que #define x -2*__LINE__c'est plus élégant.
Ugoren

3
@ugoren merci! Si vous voulez que tout cela soit sur une seule ligne, utilisez COUNTER au lieu de LINE - nécessite GCC 4.3+ cependant.
H2CO3

1
_CATest l'identifiant réservé. Tout ce qui commence par un tiret bas et une lettre majuscule est réservé en C.
Konrad Borowski

@xfix c'est tout à fait ça, mis à jour pour supprimer UB.
H2CO3

20

C

C'est plus intéressant sans utiliser de macros et sans abuser de l'infini.

/////////////////////////////////////
// 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);

Essayez-le si vous n'y croyez pas!


1
0. Non, je n'y crois toujours pas.
MSalters

@MSalters: Quel compilateur utilisez-vous? Vous pourriez avoir désactivé les trigraphes.
vsz

VS2010. Il est tout à fait possible que les trigrammes soient désactivés par défaut. Soit ça, soit la concaténation de ligne ne marche pas??\
MSalters

MSalters: le trigramme ??\ doit être converti en un seul \ , donc il n'y en a pas ??\ . Certains compilateurs modernes donnent toutefois des avertissements par défaut aux trigraphes et aux concaténations de lignes, même s’ils sont activés.
vsz

18

Mathematica:

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

Je pense que cette solution est nouvelle car elle utilise le concept de valeurs Up de Mathematica .

MODIFIER:

J'élargis ma réponse pour expliquer la signification des valeurs supérieures dans Mathematica .

La première ligne redéfinit essentiellement l'addition du symbole x. Je pourrais directement stocker une telle définition dans la fonction globale associée au +symbole, mais une telle redéfinition serait dangereuse car cette redéfinition pourrait se propager de manière imprévisible via les algorithmes intégrés de Mathematica .

À la place, en utilisant la balise x/:, j’ai associé la définition au symbole x. Désormais, chaque fois que Mathematica voit le symbole x, il vérifie s'il est exploité par l'opérateur d'addition +dans un motif de la forme x + 2 + ___où le symbole ___désigne une éventuelle séquence null d'autres symboles.

Cette redéfinition est très spécifique et utilise les capacités étendues de correspondance de motifs de Mathematica . Par exemple, l'expression x+y+2retourne x+y, mais l'expression x+3retourne x+3; parce que dans le premier cas, le motif pourrait être apparié, mais dans le dernier cas, le motif ne pourrait pas être apparié sans simplification supplémentaire.


1
Je pense que vous devriez expliquer ce que ça fait. La plupart des gens ne connaissent pas Mathematica (ou quelles sont les valeurs Up).
Ugoren

1
Merci @ugoren, je passe la majeure partie de mon temps sur le site Web de Mathematica Stack Exchange. J'ai donc oublié d'expliquer ce qui donnait un sens à mon exemple. J'ai fait un montage qui explique le concept aussi précisément que possible.
Carl Morris

17

Javascript:

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

Testez le violon


2
Vous pouvez utiliser Infinity, ou -Infinity, et à cause de cela, vous pouvez utiliser le raccourci de x = 1/0.
zzzzBov

6
@zzzzBov: C'est certainement un meilleur code de golf. J'ai choisi (99999999999999999 == 99999999999999999+2)parce que je pense que c'est un peu plus intéressant que (Infinity == Infinity+2), comme le dit le PO, "c'est subjectif" :)
Briguy37

Ceci est le seul cas dans le monde réel dans lequel j'ai vu un chèque comme celui - ci pour une bonne raison ( en plus des énigmes de programmation): Une faculté fonction (float-base) vérifiait son entrée pour être trop grand pour être pris en compte par -1récursifs . Le langage lui-même était Python, mais cela n'a pas vraiment d'importance dans ce cas.
Alfe

5
@NicoBurns not ture :(
ajax333221

2
@NicoBurns, l'exécution de ce code dans la console produit false; où que vous obteniez cette information sur JS est fausse et ne doit pas faire confiance.
zzzzBov

17

schème

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

Agréable. Scheme (x == x + 2)ressemble à C, mais signifie une chose totalement différente.
Ugoren

1
Maintenant, fais-le pour (= x 2).
Joe Z.

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

@ugoren cela est défini pour faire cela par ce programme. x est simplement le nom d'une fonction ici. Et ainsi est ==
Cruncher


16

Voici une solution pour JavaScript qui ne tire pas parti Infinityet les -Infinitycas bord de plus à virgule flottante. Cela ne fonctionne ni dans Internet Explorer 8 et versions antérieures, ni dans le mode strict opt-in ES5. Je n'appellerais pas la withdéclaration et les accesseurs particulièrement des fonctionnalités "avancées".

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

Édité pour ajouter: L'astuce ci-dessus est également possible sans utiliser withet get, comme l'a noté Andy E dans Astuces pour jouer au golf en JavaScript et aussi par jncraton sur cette page:

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

Un bon concept - faire xun appel de fonction, même s'il ressemble à une lecture de variable. Je suppose que l’évaluation va de gauche à droite, mais c’est acceptable car elle est spécifiée dans JS (contrairement à C).
Ugoren

14

Ce qui suit n’est pas conforme aux normes C , mais devrait fonctionner sur n’importe quelle plate-forme 64 bits:

int (*x)[0x2000000000000000];

Génial en principe, mais semble être mal appliqué. xserait incrémenté par étapes de 2 ^ 61, donc x + 8serait égal x.
Ugoren

@ugoren, cela fonctionne pour moi, sur Linux avec 4 octets int.
han

Vous avez absolument raison. J'ai raté le fait que ce soit une panoplie de int, pas char.
Ugoren

10

Sauge:

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

renvoie True

En général pour GF (2 ** n), il est toujours vrai que x = x + 2 pour tout x

Ce n'est pas un bug ou un problème de débordement ou d'infini, c'est en fait correct


1
Même astuce fonctionne avec PARI / GP
Hagen von Eitzen

10

Common Lisp

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

C'est assez facile quand xne doit pas être une valeur réelle.


8

APL (Dyalog)

X←1e15
X=X+2

APL n’a même pas l’infini, c’est juste que les flotteurs ne sont pas assez précis pour faire la différence entre 1.000.000.000.000.000et 1.000.000.000.000.002. Pour autant que je sache, c'est la seule façon de faire cela dans APL.


J'aime beaucoup cela parce que c'est la première solution pour exploiter la précision de flottement.
AndrewKS

1
@ Andrewks: En fait, Paul R était un peu plus tôt.
MSalters

8

Perl 6

Je suis surpris de ne pas voir cette solution avant. Quoi qu'il en soit, la solution est la suivante: qu’en xest-il 0et 2à la fois? my \xdans cet exemple, déclare la variable sigilless - cette question demande à propos x, pas à la manière de Perl $x. L' ?? !!opérateur est ternaire.

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

Mais...

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

xest plusieurs valeurs à la fois. xest égal à 0et 2à la fois. x + 2est égal à 2et 4à la fois. Donc, logiquement, ils sont égaux.


8

Python 2.X (Utilisation de la redéfinition des entiers (mis en cache))

J'ai remarqué que toutes les réponses python ont défini des classes qui redéfinissent l' +opérateur. Je vais vous répondre avec une démonstration encore plus faible de la flexibilité de python. (Ceci est un extrait spécifique à python2)

En python, les entiers sont plus ou moins stockés de cette façon en C:

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

Autrement dit, une struct avec size_t, void *et longobjet, dans cet ordre.
Une fois que nous utilisons, et le cache donc un entier, on peut utiliser python ctypesmodule pour redéfinir cet entier, de sorte que non seulement x == x+2, mais2 == 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

Impressions

True
True

7

Perl

Utilisation d'un sous-programme avec des effets secondaires sur une variable de package:

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

Sortie: true!


1
sub x{}"travaille" aussi .. (au moins dans mon 5.10.1), mais je ne peux pas comprendre pourquoi ..
mykhal

2
Parce que sub x{}renvoie undef ou une liste vide, les deux étant un zéro numérique. Et x + 2 est analysé comme x (+2). perl -MO=Deparserévèleprint "true\n" if x() == x(2);
Perleone

C'est génial, @mykhal et @Perleone!
memowe

7

Python

exploiter la précision en virgule flottante rend cela très simple.

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

Pour le rendre moins spécifique au système nécessite une importation supplémentaire

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

Cela devrait fonctionner dans d'autres langues aussi. Cela fonctionne car les représentations de 1000000000000000000000.0 et 100000000000000002.0 sont exactement les mêmes pour la machine, en raison de la façon dont les points flottants sont représentés à l'intérieur de la machine. voir http://en.wikipedia.org/wiki/IEEE_floating_point pour plus d'informations.

Cela fonctionnera donc dans n’importe quel langage qui vous permettra d’ajouter des entiers aux flottants et d’en faire le résultat.


6

Voici une solution pour C ++ basée sur la surcharge des opérateurs. Il s'appuie sur la conversion implicite d'un enumvers 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;
}

Vous pouvez utiliser std::boolalphaau lieu de ?:.
Jon Purdy

5

Je sais que c'est un défi de code ... mais je l'ai joué au golf. Pardon.

Ruby - 13 caractères - Solution Infinity

x=1e17;x==x+2

retourne vrai

Ruby - 41 caractères - Solutions de surcharge opérationnelle

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

ou

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

5

S'il est possible d'exploiter un peu la question, j'ajouterai du nouveau Java. L’astuce n’est certes pas nouvelle, mais il est peut-être intéressant de noter que cela est possible en 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));
}

Et les résultats:

(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

Cette solution VBScript fonctionne de manière similaire à ma solution JavaScript. Je n'ai pas encore utilisé de préprocesseur, la solution semble triviale.

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

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

J'allais publier la même solution en ruby, jusqu'à ce que je voie la vôtre - c'est possible parce que les deux langues permettent l'omission des parenthèses.
Waldrumpus
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.