22
\$\begingroup\$

Challenge: Get the JavaScript string value containing only the "-" character using code only containing the following three symbols: +[]. Note: I'm not sure if this is possible.

Scoring criterion: The number of bytes of code used.

Why? I've set myself a challenge to be able to write code using only the above three characters that can evaluate to ANY JavaScript number. The only thing left I am missing is having access to the "-" character. Once I have this, everything else becomes possible. This question is what gave me inspiration for this.

Definitions

Here is a list of definitions I've so far come up with to write a JavaScript expression (on the left) using only the +[] symbols (on the right). Most definitions reuse existing definitions.

0: +[]
1: ++[[]][0]
(EXPR): [EXPR][0]
1: (1)
2: 1+1
3: 1+2
4: 1+3
5: 1+4
6: 1+5
7: 1+6
8: 1+7
9: 1+8
POSITIVE_INTEGER: +((DIGIT1+"")+DIGIT2+DIGIT3+...)
"": []+[]
EXPR+"": EXPR+[]
undefined: [][0]
"undefined": undefined+""
"undefined": ("undefined")
"u": "undefined"[0]
"n": "undefined"[1]
"d": "undefined"[2]
"e": "undefined"[3]
"f": "undefined"[4]
"i": "undefined"[5]
NaN: +undefined
"NaN": NaN+""
"N": "NaN"[0]
"a": "NaN"[1]
Infinity: +(1+"e"+3+1+0)
"Infinity": Infinity+""
"I": "Infinity"[0]
"t": "Infinity"[6]
"y": "Infinity"[7]
"function find() { [native code] }": ([]["f"+"i"+"n"+"d"]+"")
"c": "function find() { [native code] }"[3]
"(": "function find() { [native code] }"[13]
")": "function find() { [native code] }"[14]
"{": "function find() { [native code] }"[16]
"[": "function find() { [native code] }"[18]
"a": "function find() { [native code] }"[19]
"v": "function find() { [native code] }"[22]
"o": "function find() { [native code] }"[17]

Unfinished definitions

These definitions contain missing pieces, highlighted in red (never mind, I can't figure out how to change the color, I'll use italics for now).

Number: 0["constructor"]
OBJ.FUNC(): +{valueOf:OBJ.FUNC}
OBJ.FUNC(): {toString:OBJ.FUNC}+""
"-": (Number.MIN_SAFE_INTEGER+"")[0]
"-": (Number.NEGATIVE_INFINITY+"")[0]
"-": (Number.MIN_VALUE+"")[2]
"-": ("".indexOf()+"")[0]
".": (+"1e-1")[1]


Thanks to the amazing answers to this question, I've created a JSFiddle that can generate any JavaScript number using those 3 characters. Input a number, tap "Go!", and then copy and paste the JavaScript into your devtools console to see it in action. You can also hover over the generated output in the explanation section for details on how it works.

\$\endgroup\$
  • \$\begingroup\$ Despite our banner's ill-chosen subtitle, coding challenges are actually off-topic except in the sense that competitions are a type of challenge. All out competitions must have an objective scoring criterion. \$\endgroup\$ – Adám Jul 3 at 12:17
  • 2
    \$\begingroup\$ Just in case you'd like to update your script accordingly, 2 is ++[++[[]][+[]]][+[]], 3 is ++[++[++[[]][+[]]][+[]]][+[]], etc. That's what I'm doing in the last revision of my answer. \$\endgroup\$ – Arnauld Jul 3 at 14:52
  • 1
    \$\begingroup\$ @Arnauld Maybe I should update my script to only use +[] haha. Thanks I'll update the numbers. So n is ++[n-1][0] \$\endgroup\$ – David Callanan Jul 3 at 15:00
  • 1
    \$\begingroup\$ The undefined can be [][[]] instead of [][0]. Also, you've added the "a" twice to your list in the spoiler (one at NaN and one at the find native). And nice way to further golf the integers with the pre-increment @Arnauld. (I won't update my answer to do the same, since then we'll have the same solutions again.) \$\endgroup\$ – Kevin Cruijssen Jul 3 at 15:27
  • 1
    \$\begingroup\$ @DavidCallanan, you're list of ways to make things is amazing. \$\endgroup\$ – trinalbadger587 Jul 5 at 18:22
34
\$\begingroup\$

 260 ... 210  205 bytes

Saved 5 bytes thanks to @user202729

[+[[+[++[[]][+[]]+[++[[]][+[]]]+[[+[][[]]]+[][[]]][+[]][++[[]][+[]]+[+[]]]+[++[[]][+[]]]+[+[]]+[+[]]]+[]][+[]][++[[]][+[]]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[++[[]][+[]]]]+[]][+[]][++[++[[]][+[]]][+[]]]

Try it online!

How?

We first generate the string "11e100" and coerce it to an number to get 1.1e+101. By coercing it back to a string and extracting the 2nd character, we obtain a "."

Using this ".", we can now generate the string ".0000001". When forced to a number, this gives 1e-7, which can be used to extract a "-".

Below is a slightly more readable version:

[+[[+['11' + [[NaN] + undefined][0][10] + '100'] + []][0][1] + '0000001'] + []][0][2]

Commented

[                           // singleton array:
  +[                        //   coerce to a number:
    [                       //     singleton array:
      +[                    //       coerce to a number:
        ++[[]][+[]] +       //         1 +
        [++[[]][+[]]] +     //         "1" +
        [                   //         singleton array:
          [+[][[]]] +       //           "NaN" +
          [][[]]            //           undefined
        ][+[]]              //         [0] -> "NaNundefined"
        [                   //         build [10]:
          ++[[]][+[]] +     //           1 +
          [+[]]             //           "0"
        ]                   //         -> "e"
        + [++[[]][+[]]]     //         + "1"
        + [+[]] + [+[]]     //         + "0" + "0" -> "11e100"
      ]                     //       -> 1.1e101
      + []                  //       coerce to a string
    ][+[]]                  //     [0] -> "1.1e101"
    [ ++[[]][+[]] ]         //     [1] -> "."
    + [+[]] + [+[]] + [+[]] //     + "0" + "0" + "0"
    + [+[]] + [+[]] + [+[]] //     + "0" + "0" + "0"
    + [++[[]][+[]]]         //     + "1" -> ".0000001"
  ]                         //   -> 1e-7
  + []                      //   coerce to a string
][+[]]                      // [0] -> "1e-7"
[                           // build [2]:
  ++[                       //   pre-increment:
    ++[[]][+[]]             //     1
  ][+[]]                    //   [0]
]                           // -> "-"
| improve this answer | |
\$\endgroup\$
  • 2
    \$\begingroup\$ No way you genius! How?? \$\endgroup\$ – David Callanan Jul 3 at 12:37
  • 1
    \$\begingroup\$ Hmm, you now use the exact same approach as my answer with "11e100" and ".0000001". I'll have to later check where you saved your 2 bytes. :) EDIT: Outgolfed you again. ;p \$\endgroup\$ – Kevin Cruijssen Jul 3 at 13:42
  • \$\begingroup\$ @KevinCruijssen I honestly have no idea. :-) But I've added a commented version. \$\endgroup\$ – Arnauld Jul 3 at 13:47
  • \$\begingroup\$ @Arnauld, I definitely didn't think this was possible. \$\endgroup\$ – trinalbadger587 Jul 5 at 18:12
  • 1
    \$\begingroup\$ [[+[][[]]]+[][[]]][+[]][++[[]][+[]]+[+[]]] \$\endgroup\$ – user202729 Jul 7 at 3:46
13
\$\begingroup\$

286 256 251 247 244 240 bytes

[+[[+[++[[]][+[]]+[++[[]][+[]]]+[[][[]]+[]][+[]][++[[]][+[]]+[++[[]][+[]]][+[]]+[++[[]][+[]]][+[]]]+[++[[]][+[]]]+[+[]]+[+[]]]+[]][+[]][++[[]][+[]]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]+[++[[]][+[]]]]+[]][+[]][++[[]][+[]]+[++[[]][+[]]][+[]]]

Did I just outgolf @Arnauld in his favorite language despite barely knowing JS?! ;) EDIT: Never mind, he just golfed it the moment I post it.. Of course. XD

Try it online.

Explanation:

Techniques used:

  • +[]: 0
  • ++[[]][+[]]: 1
  • [][[]]: undefined
  • [EXPRESSION]+[]: Cast to string
  • +[EXPRESSION]: Cast to a number
  • "STRING"[INDEX]: Get the INDEX'th character of the STRING
  • [EXPRESSION][+[]]: Wrap and extract to have access to the next command (necessary after we casted to a string, number, or concatted some strings together); a.k.a. it acts as wrapping the EXPRESSION in parenthesis: (EXPRESSION).

I first create the string "11e100". Casting this to a number and then back to a string will result in "1.1e+101". From this, I extract the ., and use it to create the string ".0000001". Casting this to a number and then back to a string will result in "1e-7", from which we can extract the -.

Of course I didn't come up with this myself, since I barely program in JavaScript nor JSFuck. The genius behind this is @Lynn, who posted the following in this answer of his/her for the JSF**k with only 5 symbols? challenge:

Also, we can make "11e100", cast to number and back to string, to get "1.1e+101", from which we extract . and +.

Using that ., in turn, we can make the string ".0000001", cast it to number and back, to get "1e-7", winning us -.

Code explanation:

Step 1: Create "11e100":

++[[]][+[]]            // Push 1
+[           ]         // Concat:
  ++[[]][+[]]          //  Another 1
+[...]                 // Concat:
   [][[]]              //  Push undefined
         +[]           //  Cast it to a string: "undefined"
  [         ][+[]]     //  Wrap it in a list, and extract it again
                  [3]  //  Get the (0-based) 3rd character of this string: "e",
                       //  where the 3 is created like this:
 ++[[]][+[]]           //   Push 1
 +                     //   Add:
   ++[[]][+[]]         //    Push another 1
  [           ][+[]]   //    Wrap it in a list, and extract it again
 +[++[[]][+[]]][+[]]   //   And do the same to add another 1
+[++[[]][+[]]]         // Concat another 1
+[+[]]                 // Concat a 0
+[+[]]                 // And concat another 0

Step 2: Convert it to "1.1e+101":

+[^]                   // Cast "11e100" to a number
    +[]                // And convert it back to a string

Step 3: Extract the .:

[^][+[]]               // Wrap it in a list, and extract it again
        [1]            // Get the (0-based) 1st character of this string: ".",
                       // where 1 is created as before:
         ++[[]][+[]]   //  Push 1

Step 4: Create ".0000001":

^+[+[]]                // Concat a 0 to the "."
+[+[]]+[+[]]+[+[]]+[+[]]+[+[]]
                       // And concat five more 0s
+[++[[]][+[]]]         // Concat a 1

Step 5: Convert it to "1e-7":

+[^]                   // Cast ".0000001" to a number
    +[]                // And convert it back to a string

Step 6: Extract the -:

[^][+[]]               // Wrap it in a list, and extract it again
        [2]            // Get the (0-based) 2nd character of this string: "-",
                       // where 2 is created like this:
 ++[[]][+[]]           //  Push 1
 +                     //  Add:
   ++[[]][+[]]         //   Push 1
  [           ][+[]]   //   Wrap it in a list, and extract it again
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I'm afraid @Arnauld just shortened his, hard luck! \$\endgroup\$ – David Callanan Jul 3 at 12:49
  • 4
    \$\begingroup\$ @DavidCallanan Yeah, I noticed. :) Should have known, since he's the JS god around here, and this is only my second JS answer ever, haha. \$\endgroup\$ – Kevin Cruijssen Jul 3 at 12:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.