Коли (x == x + 2)? [зачинено]


90

Завдання: Визначте xтак, щоб вираз (x == x+2)оцінювався як істинний.

Я позначив це запитання С, але відповіді іншими мовами вітаються, якщо вони творчі або виділяють цікавий аспект мови.

Я маю намір прийняти рішення C, але мої голоси можуть отримати інші мови.

  1. Правильно - працює над стандартами, що відповідають стандартам. Виняток - якщо припустити реалізацію основних типів, якщо це звичайна реалізація (наприклад, якщо intє доповненням 32 біт 2), це нормально.
  2. Просте - має бути невеликим, використовуйте основні мовні функції.
  3. Цікаво - це суб’єктивно, визнаю. У мене є кілька прикладів того, що я вважаю цікавим, але не хочу давати підказки. Оновлення : уникати препроцесора цікаво.
  4. Швидкий - Перша хороша відповідь буде прийнята.

Отримавши 60 відповідей (я ніколи не очікував такого очікування), можливо, буде добре їх підсумувати.

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

  1. Препроцесор С. #define x 2|0було запропоновано, але є багато інших можливостей.
  2. Плаваюча точка. Велика кількість, нескінченність або NaN - це все.
  3. Арифметика вказівника. Вказівник на величезну структуру викликає додавання 2 для обгортання.

    Решта не працюють з C:

  4. Перевантаження оператора - +це не додавання або ==те, що завжди повертає істину.
  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 категорій, IMHO.
користувач невідомий

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
Ах добрий старий ділимо на нуль. На це знадобилося більше часу, ніж я хотів би визнати. ха-ха
Грант

Argh, я теж хоч цього, але в Windows не компілюється, тому я його кинув. :( +1 хоч
Тудор

x = 1e999 - це ще один спосіб зробити це.
shiona

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
Це якось нагадує мені маленького Боббі Столи.
vsz

1
@rakeshNS: Я додав додатковий набір дужок, щоб показати перевагу оператора . Ось чому я сказав "В основному".
Будь ласка, продовжте

79

Брейнфук

x

Це, звичайно, трохи розтягує "оцінити справжнє", тому що в Brainfuck насправді нічого не оцінюється - ти лише маніпулюєш стрічкою. Але якщо ви тепер додасте своє вираження

x
(x == x+2)

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

+

(тому що все, але <>+-[],.це коментар). Що не робить нічого, крім збільшення значення, де ми зараз є. Стрічка ініціалізується з усіма нулями, тому ми закінчуємо знаком 1 на курсорі, що означає "вірно": якби ми зараз запустили умовний розділ з [], він би входив / циклічно.


12
+1 Має бути найкреативнішим згинанням правил.
ніндзя

3
Навіщо вам це потрібно x?
Джеймс

3
@James Питання говорить, щоб визначити, xтут xвизначено як x.
user80551

1
@James відповідь не означає needнічого, окрім+
Cruncher

56

F #

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

13
Мені це подобається. Замість того, щоб жонглювати номерами, просто
перезначте

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 до конкретного числа, і це не має ніякого ефекту, є трохи більш дивним і характерним для обмеженої точності комп’ютерів та ще цікавіше IMHO
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
Заплакав, щойно отримав значок «Приємна відповідь» за цю посаду. Серйозно, отримання значків для EVIL речей ?! Не робіть цього вдома !
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
Ротсор

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
dr jimbob

На пару символів коротше, якщо ви не подовжуєтеся з int ..class X:__add__=lambda s,o:s
Doboy

Чи можу я запитати, що робить це множення?
seequ

2
@TheRare це насправді не множення. Оскільки __add__зазвичай дається кілька аргументів ( lambda x,y:), я зберігаю деякі символи, використовуючи *, щоб упакувати всі аргументи в кортеж ( lambda *y:). Докладнішу інформацію див. У документах .
grc

31

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

struct {} *x = 0;

2
Дуже хороша! Я думав про арифметику вказівника з дуже великими даними, що ведуть до обгортання, але не думав про зворотне.
угорен


25

Поширене неправильне уявлення про те, що для C пробіли не мають значення. Я не уявляю, що хтось не придумав цього в 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
@ugoren дякую! Якщо ви хочете, щоб все це було в одному рядку, використовуйте COUNTER замість LINE - хоча GCC 4.3+ і новіші.
H2CO3

1
_CATє зарезервованим ідентифікатором. Все, що починається з підкреслення, і великі літери зарезервовано у С.
Конрад Боровський,

@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: Який компілятор ви використовуєте? У вас можуть бути відключені триграфі.
vsz

VS2010. Цілком можливо, що триграфи відключені за замовчуванням. Або це, або конкатенація рядків не працює??\
MSalters

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

18

Математика:

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

Я вважаю, що це рішення є новим, оскільки воно використовує концепцію Mathematica Up Values.

Редагувати:

Я розширюю свою відповідь, щоб пояснити, що означають Up Value в Mathematica .

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

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

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


1
Я думаю, ви повинні пояснити, що це робить. Більшість людей не знає Mathematica (або що таке вище значення).
угорен

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, але це в цьому випадку насправді не має значення.
Альфе

5
@NicoBurns not ture :(
ajax333221

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

17

схема

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

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

1
Тепер зробіть це для (= x 2).
Джо Z.

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

@ugoren це визначено для цього за допомогою цієї програми. x тут просто назва функції. І так є ==
Cruncher

16

Очевидна відповідь:

Коли цей термін припиняється:

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

1
+1 meta.codegolf.stackexchange.com/a/1070/8766, але це насправді геніально.
user80551

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

Ця відповідь передувала цій посаді з двома роками. Все, що сьогодні вважається кліше, в певний момент було новим.
daniero

16

Ось рішення для JavaScript, яке не використовує Infinityі -Infinityкрайові випадки додавання з плаваючою комою. Це не працює ні в Internet Explorer 8 і нижче, ні в жорсткому режимі ES5. Я б не назвав withзаяву і getters особливо "розширеними" можливостями.

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функціональний виклик, хоча це виглядає як прочитане змінною. Я припускаю порядок оцінки зліва направо, але це нормально, оскільки це вказано в JS (на відміну від C).
угорен

14

Далі не відповідає стандартам C , але він повинен працювати майже на будь-якій 64-бітній платформі:

int (*x)[0x2000000000000000];

Чудово в принципі, але, здається, реалізовано неправильно. xзбільшувались би на кроки 2 ^ 61, так x + 8би дорівнювали x.
угорен

@ugoren, це працює для мене, на Linux з 4-байтовим int.
хан

Ви абсолютно праві. Я пропустив той факт, що це масив int, а не char.
угорен

10

Шавлія:

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

повертає True

Загалом для GF (2 ** n) завжди вірно, що x = x + 2 для будь-якого x

Це не помилка чи проблема із переповненням чи нескінченністю, це насправді правильно


1
Цей

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

Перл 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 мають визначені класи, які переосмислюють +оператор. Я відповім ще більш низькою демонстрацією гнучкості пітона. (Це фрагмент, характерний для 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, або порожній список, обидва з яких є числовим нулем. І x + 2 розбирається на x (+2). perl -MO=Deparseрозкриваєprint "true\n" if x() == x(2);
Перлеоне

Це приголомшливо, @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 для отримання додаткової інформації.

Таким чином, це в основному буде працювати на будь-якій мові, що дозволяє додавати цілі числа до плавців, і результат цього буде float.


6

Ось рішення для C ++ на основі перевантаження оператора. Він покладається на неявну конвертацію з " 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 символів - рішення нескінченності

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

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