Hacker News new | past | comments | ask | show | jobs | submit login
Return True to Win (alf.nu)
234 points by moklick on Aug 12, 2016 | hide | past | favorite | 116 comments

This table is quite useful to solve some problems: https://dorey.github.io/JavaScript-Equality-Table/

JS gets even weirder when you include all the comparison operators.


Did you know undefined is equal to undefined, but not <= undefined or >= undefined?

Or that two instances of the same object/array are not equal (e.g. [-1] != [-1]), but are both <= and >= each other?

Or that /.*/ is non-comparable (only != is true) to all numbers, but greater than [-0.5] and "-0.5", and less than [0] and "0"?

Most of the examples you point out make sense if you know that using greater than or less than casts the value to a number. >= and <= always cast their parameters to numbers while == only does if either side is already a number.

If you define "make sense" as "having an explanation not rooted in the supernatural", then yes.

By that definition, Brainf*ck[1] also makes sense.


What a clusterfuck.

And yet, people say Brendan Eich doesn't believe in equality!

> Moral of the story: Always use 3 equals unless you have a good reason to use 2.

  NaN === Nan  // => false
  [] === []    // => false
  {} === {}    // => false
  [1] === [1]  // => false
  [0] === [0]  // => false
I guess i never see the gains in the triple vs double equal sign wars.

None of those are true when using `==` either.

The NaN example comes directly from IEEE754

The others are based on the fact that the two sides are not referring to the same object. C "equivalents" of your examples:

    int x[0], y[0]; x == y; // false
    typedef struct {} empty_t; empty_t *x, *y; x == y; // false
    int x[] = { 1 }, y[] = { 1 }; x == y; // false
    int x[] = { 0 }, y[] = { 0 }; x == y; // false

[] and {} create new objects. === always compares by identity, which isn't a unique feature. It's equivalent to Java's ==, and two different objects aren't ever equal to each other. === is equivalent to Python's `is`, and you'll get false from `[] is []` in Python for example.

Those non equations are perfectly reasonable.

One array or object does not equal another, different one.

There are definitely gains - I strongly suggest following the 'moral' of the story.

At least the === paradigm is fairly consistent and mostly rational.

This notion of equality would make pattern matching on empty lists or objects impossible in languages such as Erlang or Haskell. Perhaps it makes sense with the knowledge that each array is a different object, but it is highly counterintuitive.

Do any of those return true if you use double equals? The distinction only really comes up when you have to different types on either side and then It will coerce one of the types to match the other.

That is correct. The canonical example is string-numeric coercion:

    "0" == 0 && "0" !== 0

You're comparing two expressions of the same type so it doesn't matter whether you use == or ===, but == can return true even if the expressions are of different types.

Find the exact combination of browser/OS that does more than show "return true to win" on a white background to win.

I got 'Sorry for the delay.'

> Find the exact combination of browser/OS that does more than show "return true to win" on a white background to win.

I see:

    return true to win
    (Come back in a few minutes.)
What do I win?

A moment in which to reflect.

Use patience.


I already saw this on lobste.rs, but it's still cool. I like ES just fine, but to think we could have had scheme instead. Gee, thanks Netscape:

Every time you win, everybody loses.

"it's because of you, motherfucker, that we're not all using lisp" @ 5:00 https://www.youtube.com/watch?v=bzkRVzciAZg

No, that's actually the fault of Netscape.

Anyways, that video is awful and totally wrong. Node code can be clean, threaded code can be ugly. Both can be fast, but the perf characteristics are different (for OS threads, anyways).

It loaded for me eventually. First one is pretty straightforward. After that they seem to require knowledge of JavaScript quirks.

I don't exactly know what I did, but it did say that I win.

A day like any other with Javascript ;-)

s/with Javascript/being alive/

Let me document all the reasons I dislike the HTML spec: it defines a willful violation of the ECMAScript standard.

Can you elaborate?

I'll use a link shortener to prevent spoilers. This link elaborates exactly which rules are abused: https://goo.gl/mu5xtr

"These requirements are a willful violation of the JavaScript specification current at the time of writing. The JavaScript specification requires that ToBoolean return true for all objects, and does not have provisions for objects acting as if they were undefined for the purposes of certain operators. This violation is motivated by a desire for compatibility..." with old Internet Explorer.

Well, it's kind of a hint for solving some of the more "that's impossible" problems on here. I don't want to give the whole thing away.

TypeError: NetworkError when attempting to fetch resource.

Maybe the challenge is to fix HTTP?

Does anybody really know why JS's type system was designed the way it was? It seems so out of whack with what people want out of a language, dynamically typed or otherwise.

It wasn't; the language was implemented from scratch in ten days.

That explains a lot. Source for others that are interested: https://www.w3.org/community/webed/wiki/A_Short_History_of_J...

It's because Eich was told to make JS C-like. In C, an empty array, an empty string, 0, false and null are all the same value: a word with all bits 0. So in JS, those are all are falsy and == to each other.

In C, empty strings are truthy, being a non-null pointer to a NUL character. Depending on what you mean by "an empty array" that might also be a non-null pointer to a zero-length region of memory, and thus also truthy in C.

I wish an empty string was not false.

In 'object' terms, an empty string is still a string! It's something.

I guess if you think about it from a memory perspective, it's 'nothing'.

But since JS is not actually like C, I really wish "" were true.

"" is actually true in C, but that's also because it represents something in memory. Consider how C encodes strings: an empty string is a _pointer_ to a 0 (or a '\0', if you want to think of it as a char). However, the pointer (being an address) is non-zero (since the address 0 is NULL).


This is a nice challenge to start the morning.

However, on mobile the input loses focus after each individual character typed which is quite frustrating.

I typed "true", without the quotes.

Did I do it wrong?

It's code golf. Try to do it in less than 4 characters.

There are more levels

The game shows us how ugly JS is.

Indeed, I refuse to believe there should be a solution to the 'reflexive' task.

So you disagree with the IEEE floating point specification, then? Javascript is directly following spec there.

Do you think that such rule for NaN state is useful?

Does that spec forces you to implement equality test between floating point numbers?

...yes? I'm not sure exactly what you're asking here, though.

I'm asking if it is really a good idea for a language to provide equality/inequality for floating point numbers when it's often mistake to do that.

So disallow the direct operator but allow equality to be deduced indirectly by usage of > < >= <= ?

That one isn't specific to Javascript, though. If you can find a mainstream language that doesn't have any values that aren't equal to themselves, I'll give you a cookie.

(Going from memory of the last time I tried this challenge, since I can't get it to load at the moment.)

The important property of evaluation is determinism defined by the equality of the output. Classically, id(x) != id(x) is logically inconsistent.

Boolean Logic and natural languages are pretty mainstream in my opinion. Do you mean programming languages? If IEEE whatsthenumber is implemented in the FPUs to provide fcmp (Floating-point Compare Instruction), the languages don't have much of a choice.

When there are different types of equality, ie. compare instructions, you have no equality. That's maybe a bit binary. I'm sorry, I thought this was Computer Science.

You seem to be splitting hairs and I'm not entirely sure why. Following the flow of conversation it should be pretty easy to infer the parent was referring to programming languages. Originally you said you don't think there should be a solution to the reflexive problem, and that in reply to a comment mentioning that Javascript was ugly (which is where the context of _programming_ language came from). I, and I believe the parent as well, took that to mean that you consider Javascript ugly because you don't believe it should operate the way it does. However, the point the parent was trying to make is that this is something common to all (programming) languages which follow the IEEE 754 standard and is therefore not some special case which makes Javascript any more ugly than another (programming) language.

It may not seem obvious and it may seem logically inconsistent but, like you said, this is computer science and things don't always work exactly the way we think they should. Usually because the obvious logical solution has problems when implemented so we change things around. In this case, NaN != NaN because of some of the limitations at the time IEEE 754 was proposed.

No, of course that was news to me. But I am not advocating any programming language. This looks like a wart, but a compelling one to commit to, because it's a simple solution.

> It may not seem obvious and it may seem logically inconsistent but, ...

An if an argument is made in defense of inconsistent logic, how could the argument be expected to be logically consistent?

Your argument by authority is not very good. There are involved explanations on stackoverflow.com, but I didn't bother to read, yet. Another solution would be to set the carry flag.

> Classically, id(x) != id(x) is logically inconsistent.

Equality is domain dependent. For example ∞!=∞ could be justified, as can (0/0)!=(0/0). In the domain of real numbers, equality can be an undecideable problem[1]. I guess the designers of these languages had to choose between tolerable defaults or throwing exceptions. I'm happy with JS doing this:

    % node
    > 1.0/-0
    > 1.0/0
    > 0/0
    > 0/NaN
    > 1+NaN
[1] https://math.stackexchange.com/questions/143727/determining-...

Swift. The Javascript of tomorrow, today!

PureScript. The Swift of today. Yesterday, today and tomorrow!

But it compiles to ES5. At this rate, we'll be deploying ES5 for the rest of human history while we all pretend we're writing ES451.

And it's whitespace significant, which is something only maniacs like in a programming language.

I'm half joking, don't get too offended...

But whitespace significance is madness.

My gosh, this is way harder than the alert(1) series. http://escape.alf.nu

Reminds me of "The Little Lisper" and coding koans; honestly thought it'd be harder to "win" the challenge.

Fri Aug 12 14:35:18 UTC 2016:

Page had message that the Hacker News 'hug' was likely to affect performance.

Took me a couple of tries... (Spoiler): Anyone anything shorter then 4 characters (two characters)?

How did you solve the reflexive? I'm not getting at anything :(

NaN != NaN. It's how you're supposed to test for NaN, apparently.

Or use isNaN

I'll give you one chance to guess how isNaN is implemented. https://github.com/v8/v8/blob/e6d1a80e790117dc27b20e9b14de4b...

Yeah, tricky one. NaN works though. Because NaN == NaN = false

Another version, also 3 characters: 0/0

Infinity - Infinity

reflexive( function() {return ++window.x;}() )

I don't think so

I broke things to do it

[] - {}


!0 - 2 chars 1>0 - 3 chars

Ah. 2 distinct characters now.

I used !!1

Yup. !0

For the first 5, I've got 2,3,8,14,7. Anybody got tighter solutions?

The counter one (level 4) can be done with 11 chars. Solution below, found on Reddit[1]. Also, I could not manage fewer than 9 characters for level 3. (Edit: thanks @ensard)

Spoiler here: x=>_=>x=-~x

And also in this link: [1]: https://www.reddit.com/r/programming/comments/4wd32v/return_...

I got 7 on the third challenge with that solution:


Does someone have a <52 char solution for the counter one ?


You can save one character by doing this:


the underscore is another variable but a single variable does not require parenthesis. So instead of two chars for the two parens, you use a single char for a single letter variable. JS FTW ;)

that's ascii art, not code

Holy crap, that's what I call refactoring !

One solution:

    function(c=1){return function(){return c++}}
44 characters


With games like these I feel like we all lose

This is true.

Pun intended!

Please more levels

You've already finished wat, undef, random3, and random4?

> wat, undef

Oh, undef is as easy as knowing HTML trivia. Getting a falsey value to return an arbitrary string when invoked as a function is at least a little harder...

> random3

... is almost as easy as random1

> random4

is exactly as impossible as it looks

What is with the User/Score/Browser table? I only did like 4 of the tests and that thing popped up. I would finish it but I have some other things to do.

Looks like once you successfully score, it shows you how many characters it took others to solve. For example, the first one you can trivially type in true to solve it, with four characters. But it's solvable with only two characters.

Yes but there is no where you can enter your screen name. I should have clarified that in my question because I got down voted for asking this.

The whole down voting thing imo really has to go. Just flag answers or up vote. The whole bro intellectual rudeness is sort of off putting.

I can't get past the first test.

I quite like this kind of challenge :)

▶ id(true ) // (4 chars)

▷ true

You win!

'Break JS to win!'

It doesn't seem to work for me on Firefox and Chrome..?

It wasn't working on either for me, so I came here to complain, went back and it was suddenly working. Dunno what the issue was but keep trying maybe

Yes, it seems to take quite a while to start up.

I had to go into the console and type "return true" for it to start working. I thought it was intentional.

This page only shows "return true to win" on a white background in Chrome?

seems to be down :/

It loads eventually

Does it?

ReturnTrue:1 Fetch API cannot load https://bigger.alf.nu/db/true/H5VmsyVCBD62113H5Slu. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://alf.nu' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

it does

I am so unhappy, because I can not play such games with Java... ;-)

What the hell am I reading.

The link points to a page that only contains the text "return true to win" in large type on a white background. As with most modern art, I don't get it.

Are you browsing with Javascript disabled?


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact