Когда (х == х + 2)? [закрыто]


90

Задача: определить xтаким образом, чтобы выражение (x == x+2)оценивалось как истинное.

Я пометил вопрос буквой C, но ответы на других языках приветствуются, если они творческие или выделяют интересный аспект языка.

Я намерен принять решение C, но другие языки могут получить мой голос.

  1. Правильно - работает на стандартных реализациях. Исключение - при условии реализации основных типов, если это обычная реализация (например, при условии, что intэто 32-битное дополнение 2), это нормально.
  2. Просто - должно быть мало, использовать основные языковые функции.
  3. Интересно - это субъективно, я признаю. У меня есть несколько примеров того, что я считаю интересным, но я не хочу давать подсказки. Обновление : избегать препроцессора интересно.
  4. Быстрый - Первый хороший ответ будет принят.

После получения 60 ответов (я никогда не ожидал такого упоминания), возможно, было бы неплохо суммировать их.

60 ответов делятся на 7 групп, 3 из которых могут быть реализованы на C, остальные на других языках:

  1. Препроцессор C #define x 2|0было предложено, но есть много других возможностей.
  2. Плавающая точка. Большие числа, бесконечность или NaN все работают.
  3. Указатель арифметики. Указатель на огромную структуру приводит к добавлению 2 для переноса.

    Остальные не работают с C:

  4. Перегрузка оператора - A +, который не добавляет, или a, ==который всегда возвращает true.
  5. Выполнение xвызова функции (некоторые языки допускают это без x()синтаксиса). Тогда он может возвращать что-то еще каждый раз.
  6. Однобитный тип данных. Тогда x == x+2 (mod 2).
  7. Изменение 2- какой-то язык позволяет вам назначить 0его.

29
Почему 4. Quick? Ты имеешь в виду: «Кто знает, и кому посчастливилось прочитать этот вопрос первым»?
Люк

6
@ugoren Позвольте сообществу голосовать (и голосовать за тех, кто вам нравится), а затем выбрать лучший ответ через 7 дней или около того :)
Люк,

3
Что касается возможности 2: NaN не работает. NaN + 2 снова NaN, но NaN == NaN ложно.
Мартин Б

2
Решение Scala, где x - это Набор, содержащий «2», а «+» означает add to Setстандартную библиотеку, не переопределяя +себя, не вписывается в эти 7 категорий, ИМХО.
пользователь неизвестен

2
Почему этот вопрос и все ответы сообщества Wiki?
mbomb007

Ответы:


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

Выходы 1.

Ссылка: http://ideone.com/dL6A5


7
float x=1./0немного короче и, возможно, более элегантно. Но в любом случае, это, безусловно, первый хороший ответ.
Угорен

1
Аааа старый добрый делить на ноль. Мне потребовалось больше времени, чтобы понять, чем я хотел бы признаться. хаха
Грант

Ага, я тоже об этом, но в Windows это не компилируется, поэтому я его уронил. :( +1, хотя
Tudor

x = 1e999 - это еще один способ сделать это.
Шиона

4
@shiona float x=1e20будет достаточно
l0n3sh4rk

125

Фортран IV:

2=0

После этого каждая постоянная 2 в программе равна нулю. Поверьте мне, я сделал это (хорошо, 25 лет назад)


23
Тем больше у меня причин никогда не трогать Фортран.
C0deH4cker

3
Это хотя бы выбрасывает предупреждение?
Майкл Стерн

15
@MichaelStern ПРЕДУПРЕЖДЕНИЕ: ВЫ ИЗМЕНЯЕТЕ ЗНАЧЕНИЕ 2!
Cruncher

100

Это похоже на работу:

#define x 2|0

В основном, выражение расширяется до (2|0 == 2|(0+2)). Это хороший пример того, почему нужно использовать скобки при определении макросов.


3
Конечно, работает, и я думаю, что это самое элегантное решение на основе препроцессора. Но я думаю, что делать это без препроцессора более интересно.
Угорен

Это только у меня так должно 2|(0+2)быть 1?
phunehehe

1
@phunehehe: |это побитовое ИЛИ ; ||это логическое ИЛИ.
Пожалуйста, установите

20
Это как-то напоминает мне маленькие столики Бобби.
вс

1
@rakeshNS: я добавил дополнительный набор скобок, чтобы показать приоритет оператора . Вот почему я сказал «В основном».
Пожалуйста, установите

79

Brainfuck

x

Это делает конечно растянуть «вычисляться правда» немного, потому что в Brainfuck ничего на самом деле не оценивает ни к чему - вы только манипулировать лентой. Но если вы сейчас добавите свое выражение

x
(x == x+2)

программа эквивалентна

+

(потому что все, кроме <>+-[],.комментария). Который ничего не делает, но увеличивает значение там, где мы сейчас находимся. Лента инициализируется со всеми нулями, поэтому мы заканчиваем с 1 на позиции курсора, что означает «истина»: если бы мы сейчас начали условную секцию с [], она бы вошла в / loop.


12
+1 Должен быть самый творческий изгиб правил.
ниндзя

3
Зачем тебе это x?
Джеймс

3
@James Вопрос говорит, чтобы определить, xпоэтому здесь xопределяется как x.
user80551

1
@ Джеймс ответ не делает needничего, кроме+
Cruncher

56

F #

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

13
Мне нравится этот. Вместо того, чтобы манипулировать числами, просто переопределите значение ==
evilcandybag

4
Держись, разве оператор равенства в F # не просто =? ==даже не определен по умолчанию.
Jwosty

50

С

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

Примечание: может не работать, если FLT_EVAL_METHOD != 0(см. Комментарии ниже).


24
+1 для реальных приложений. Слишком много людей не понимают математику с плавающей точкой.
Тим С.

1
@ mbomb007: Я думаю, что они разные - ответ, на который вы ссылаетесь, основан на том INF + 2 == INF, что в моем ответе используется одиночная точность с плавающей точкой, достаточно большая, чтобы 2 было меньше, чем один ULP.
Пол Р

2
@ mbomb007: Я также думаю, что они очень разные - ∞ + 2 = ∞это то, что любой может понять, и он не зависит от конкретного компьютера, в то время как добавление 2 к конкретному числу и безрезультатное немного более удивительно и специфично для ограниченной точности. компьютеров и еще интереснее ИМХО
GoatInTheMachine

1
Это может легко потерпеть неудачу, когда FLT_EVAL_METHOD == 1математика сделана как double. Порекомендуйте большее значение FP, которое должно превышать даже long doubleточность, как1.0e37f
chux

1
@chux: спасибо за подтверждение - это определенно то, на что мне, возможно, стоит обратить внимание в будущем, так как большая часть моего кода оказывается кроссплатформенной.
Пол Р

36

C #

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

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

Не коротышка, но несколько элегантно.

http://ideone.com/x56Ul


4
Черт возьми, только что получил значок «Хороший ответ» для этого поста. Серьезно, получать значки для злых вещей ?! Не делай этого дома !
fjdumont

Это зло, но это так прекрасно ...
Кевин

32

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


Haskell: Определите ℤ / 2ℤ на eans Bool:

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

тогда по любому x :: Boolу нас будет x == x + 2.

Обновление: спасибо за идеи в комментарии, я обновил экземпляр соответственно.


3
Вы можете упростить:fromInteger = odd
Rotsor

1
Также (+)можно определить, как (/=)я считаю.
MatrixFrog

2
Более короткое решение - создать экземпляр для ().
Томас Эдинг

31

питон

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

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

Приятно. Все языки, поддерживающие перегрузку операторов, могут использовать похожие решения, но C не является одним из них.
Угорен

Также работает с перегрузкой __cmp__как class X(int):__cmp__=lambda*x:0(или __eq__хотя немного дольшеclass X(int):__eq__=lambda*x:True
р jimbob

Пара символов короче, если вы не выходите из инт ..class X:__add__=lambda s,o:s
Добой

Могу я спросить, что делает это умножение?
Seequ

2
@TheRare это на самом деле не умножение. Поскольку __add__обычно предоставляется несколько аргументов ( lambda x,y:), я сохраняю некоторые символы, используя *, чтобы упаковать все аргументы в кортеж ( lambda *y:). Смотрите документы для получения дополнительной информации.
grc

31

GNU C поддерживает структуры без членов и размера 0:

struct {} *x = 0;

2
Очень хорошо! Я думал об арифметике указателей с очень большими данными, приводящими к переносу, но не думал об обратном.
Угорен


25

Это распространенное заблуждение, что в Си пробел не имеет значения. Я не могу представить, что кто-то еще не придумал это в 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;
}

Печать 1.


Хороший, хотя, возможно, не технически действительный ( x == x+2все еще ложный). Но как только вы поднимете идею, я думаю, что #define x -2*__LINE__это более элегантно.
Угорен

3
@ Югорен, спасибо! Если вы хотите, чтобы все это было в одной строке, используйте COUNTER вместо LINE - хотя требуется GCC 4.3+.
H2CO3

1
_CATзарезервированный идентификатор. Все, что начинается с подчеркивания и заглавной буквы, зарезервировано в C.
Конрад Боровски

@xfix это совершенно верно, обновлено, чтобы удалить UB.
H2CO3

20

С

Это интереснее без использования макросов и без злоупотребления бесконечностью.

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

Попробуйте, если не верите!


1
0, Нет, все еще не верю этому.
MSalters

@MSalters: Какой компилятор вы используете? Возможно, у вас отключены триграфы.
вс

VS2010. Вполне возможно, что триграфы по умолчанию отключены. Либо это, либо конкатенация строк не работает??\
MSalters

MSalters: триграф ??\ должен быть преобразован в единый \ , поэтому нет ??\ . Однако некоторые современные компиляторы по умолчанию выдают предупреждения как к триграфам, так и к конкатенациям строк, даже если они включены.
вс

18

Mathematica:

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

Я думаю, что это решение является новым, поскольку оно использует концепцию Mathematica Up Values.

РЕДАКТИРОВАТЬ:

Я расширяю свой ответ, чтобы объяснить, что означают Up Values ​​в Mathematica .

Первая строка по существу переопределяет сложение для символа x. Я мог бы напрямую сохранить такое определение в глобальной функции, связанной с +символом, но такое переопределение было бы опасным, потому что переопределение может распространяться непредсказуемо через встроенные алгоритмы Mathematica .

Вместо этого, используя тег x/:, я связал определение с символом x. Теперь, когда Mathematica видит символ x, он проверяет, работает ли с ним оператор сложения +в шаблоне формы, x + 2 + ___где символ ___означает возможную нулевую последовательность других символов.

Это переопределение очень специфично и использует широкие возможности Mathematica по сопоставлению с образцом. Например, выражение x+y+2возвращает x+y, но выражение x+3возвращает x+3; потому что в первом случае шаблон может быть сопоставлен, но во втором случае шаблон не может быть сопоставлен без дополнительного упрощения.


1
Я думаю, вы должны объяснить, что он делает. Большинство людей не знают Mathematica (или что такое Up Values).
Угорен

1
Спасибо @ugoren, я провожу большую часть своего времени на веб-сайте Mathematica Stack Exchange, поэтому я забыл объяснить, в чем смысл моего примера. Я сделал редактирование, которое объясняет концепцию как можно более кратко.
Карл Моррис

17

Javascript:

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

Тестовая скрипка


2
Вы можете использовать Infinity, или -Infinity, и из-за этого вы можете использовать ярлык x = 1/0.
zzzzBov

6
@zzzzBov: Это определенно лучший код для гольфа. Я выбрал, (99999999999999999 == 99999999999999999+2)потому что я думаю, что это немного интереснее, чем (Infinity == Infinity+2), хотя, как говорит ОП, «это субъективно» :)
Briguy37

Это единственный случай из реальной жизни, в котором я видел такую ​​проверку по уважительной причине (помимо загадок программирования): факультативная функция (основанная на -1числах с плавающей запятой) проверяла свои входные данные на предмет их слишком большого значения для обратного отсчета и повторения , Сам язык был Python, но это не имеет большого значения в этом случае.
Alfe

5
@NicoBurns не ture :(
ajax333221

2
@NicoBurns, выполнение этого кода в консоли производит false; где бы вы ни получали эту информацию о JS, это неверно и ей нельзя доверять.
zzzzBov

17

схема

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

Приятно. Схема (x == x + 2)выглядит так же, как C, но означает совершенно другое.
Угорен

1
Теперь сделай это для (= x 2).
Джо З.

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

@ugoren это определено для этой программы. х это просто имя функции здесь. И так же ==
Cruncher

16

Очевидный ответ:

Когда это заканчивается:

while (x != x+2) { }
printf("Now");

1
+1 meta.codegolf.stackexchange.com/a/1070/8766 но это на самом деле гениально.
user80551

1
Я думаю, while(!(x == x+2)) {}было бы больше по духу
Cruncher

Этот ответ предшествует этой мета-публикации с двумя годами. Все, что сегодня считается клише, в какой-то момент было новым.
Даниеро

16

Вот решение для JavaScript, которое не использует Infinityи -Infinityкрайние случаи сложения с плавающей точкой. Это не работает ни в Internet Explorer 8 и ниже, ни в строгом режиме opt-in ES5. Я бы не назвал это withутверждение и получателей особенно «продвинутыми» функциями.

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

Отредактировано, чтобы добавить: вышеупомянутый трюк также возможен без использования withи get, как отметил Энди E в Советы по игре в гольф на JavaScript, а также jncraton на этой странице:

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

Хорошая концепция - сделать xвызов функции, хотя она выглядит как переменная read. Я предполагаю порядок оценки слева направо, но все в порядке, поскольку он указан в JS (в отличие от C).
Угорен

14

Следующее не соответствует стандартам C , но должно работать практически на любой 64-битной платформе:

int (*x)[0x2000000000000000];

Великолепно в принципе, но, похоже, реализовано неправильно. xбудет увеличиваться с шагом 2 ^ 61, поэтому x + 8будет равно x.
Угорен

@ugoren, у меня это работает, в Linux с 4 байтами int.
хань

Вы совершенно правы. Я упустил тот факт, что это массив int, а не char.
Угорен

10

Sage:

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

возвращает True

Вообще для GF (2 ** n) всегда верно, что x = x + 2 для любого x

Это не ошибка или проблема с переполнением или бесконечностью, это на самом деле правильно


1
Тот же трюк работает с PARI / GP
Хаген фон Айцен

10

Обыкновенный Лисп

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

Это довольно легко, когда xне должно быть реальной стоимости.


8

APL (Дьялог)

X←1e15
X=X+2

У APL даже нет бесконечности, просто поплавки недостаточно точны, чтобы определить разницу между 1.000.000.000.000.000и 1.000.000.000.000.002. Насколько я знаю, это единственный способ сделать это в APL.


Мне это очень нравится, потому что это первый ответ, использующий точность с плавающей точкой.
AndrewKS

1
@AndrewKS: На самом деле Пол Р. был немного раньше.
MSalters

8

Perl 6

Я удивлен, что не видел это решение раньше. В любом случае, решение - что, если xесть 0и 2сразу? my \xв этом примере объявляется переменная без сигил - этот вопрос задается xне в стиле Perl $x. ?? !!Является тройным оператором.

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

Но...

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

xэто несколько значений одновременно. xравно 0и 2сразу. x + 2равно 2и 4сразу. Итак, по логике они равны.


8

Python 2.X (с использованием переопределения (кэшированных) целых чисел)

Я заметил, что во всех ответах на python определены классы, которые переопределяют +оператор. Я отвечу еще более низкоуровневой демонстрацией гибкости python. (Это специфический для Python2 фрагмент)

В Python целые числа хранятся более или менее таким образом в C:

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

То есть, структура с size_t, void *и longобъектом, в таком порядке.
Как только мы используем и, следовательно, кешируем целое число, мы можем использовать ctypesмодуль python для переопределения этого целого числа, так что он не только делает x == x+2, но и2 == 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

Печать

True
True

7

Perl

использование подпрограммы с побочными эффектами для переменной пакета:

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

Выход: true!


1
sub x{}"работает" также .. (по крайней мере, в моем 5.10.1), но я не могу понять, почему ..
mykhal

2
Потому что sub x{}возвращает либо undef, либо пустой список, оба из которых являются числовым нулем. И х + 2 анализируется как х (+2). perl -MO=Deparseпоказываетprint "true\n" if x() == x(2);
Perleone

Это круто, @mykhal и @Perleone!
Memowe

7

питон

Использование точности с плавающей точкой делает это очень простым.

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

Чтобы сделать его менее специфичным для системы, требуется дополнительный импорт

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

Это должно работать и на других языках. Это работает, потому что репрезентация 100000000000000000.0 и 100000000000000002.0 одинаковы для машины, потому что плавающие точки представлены внутри машины. см. http://en.wikipedia.org/wiki/IEEE_floating_point для получения дополнительной информации.

Так что это в основном будет работать на любом языке, который позволяет вам добавлять целые числа к числам с плавающей точкой, и в результате получается число с плавающей точкой.


6

Вот решение для C ++, основанное на перегрузке операторов. Он основан на неявном преобразовании из a enumв 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;
}

Вы можете использовать std::boolalphaвместо ?:.
Джон Перди

5

Я знаю, что это проблема кода ... но я играл в гольф. Сожалею.

Ruby - 13 символов - решение Infinity

x=1e17;x==x+2

возвращает истину

Ruby - 41 персонаж - решения для перегрузки Op

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

или же

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

5

Если все в порядке, чтобы использовать этот вопрос немного, то я добавлю немного новой Java. Уловка, конечно, не нова, но, возможно, интересно, что это возможно в 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));
}

И результаты:

(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

Это решение VBScript работает аналогично моему решению JavaScript. Я не использовал препроцессор, но решение кажется тривиальным.

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

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

Я собирался опубликовать то же самое решение в ruby, пока не увидел ваше - это возможно, потому что оба языка допускают пропуск круглых скобок.
Вальдрампус
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.