Return True

11. Symmetric

function symmetric(x, y) {
  return x == y && y != x;
}

Задача, в которой явно нужно перечитать алгоритм сравнения двух значений. Правда, в нём вроде бы нет каких-то логических багов, и приведение типов от перестановки мест не меняется. То есть, вот эти две операции дадут одинаковое значение:

> 1 == '1'
true

> '1' == 1
true

И так со всеми типами. А потому единственное, что нас может заинтересовать, это алгоритм приведения объекта к примитиву.

При приведении объекта к примитиву, первым делом проверяется наличие у него метода @@toPrimitive. Если он есть, то используется возвращаемое им значение. А раз так, то можем в качестве решения использовать объект и число, причём объект будет возвращать разные значения при первом и втором вызове.

Например, объект может выглядеть так:

{
  [Symbol.toPrimitive]: () => {
    if (window.x) {
      return 2;
    } else {
      window.x = 1;
      return 1;
    }
  }
}

Сожмём, и вот, решение в 49 символов готово:

symmetric({[Symbol.toPrimitive]:_=>window.x?2:window.x=1},1)

Можем воспользоваться хаком из пятой задачи и сократить ещё пару символов:

symmetric({[Symbol.toPrimitive]:_=>window.x=-~window.x},1)

Однако, Symbol.toPritimive слишком длинный и всё рушит. А потому стоит пойти дальше по алгоритму приведения объекта к примитиву, и взять вместо @@toPrimitive свойство valueOf. Для нас оно будет работать один-в-один так же:

symmetric({valueOf:()=>window.x=-~window.x},1)

И вот, уже 35 символов. Правда, в топе вон у всех 20:

Топ по задаче symmetric

Значит надо искать, что ещё сократить. Очевидный кандидат на эту должность — window. Но мы не можем просто убрать его:

> symmetric({valueOf:_=>x=-~x},1)
ReferenceError: x is not defined

Такое решение не работает, потому что x не объявлен внутри функции. Но нам ведь ничего не мешает объявить x!

> symmetric({valueOf:_=>x=-~x},x=1)
false

Теперь всё ломает хак с -~, но нам это даже на руку, потому что вместо него можно использовать обычный постфиксный инкремент:

> symmetric({valueOf:_=>x++},x=1)
true

Вуа-ля! Решение в 20 символов готово.