Here’s a little javascript quiz to help you limber up for JS1K. Each problem is solvable with one statement. **Answer with the shortest possible solution.**

This is not about writing the most readable or production-ready code. Its a fun test of versatility and language knowledge.

Answers should work on all major browsers except where denoted with “ECMA 5″ (in which case they should work on all browsers except IE<9) . The number in parentheses indicates how many characters were in my solution, including semicolons but omitting returns and extra spaces.

I’ll post my solutions on Monday. Good luck! (**Spoiler alert** – some solutions in comments)

1.Variable f is an array of functions. One of them takes no formal parameters: Invoke it. (53 characters)

2. Variable a is an array. Make an array of the non-falsey (i.e. not undefined, null, 0 etc.) values in a. (ECMA 5) (18)

3. Variables a, b and c reference numbers. Verify b is exclusively bound by a and c without using <,> or arithmetic operators (+, -, *, /) (21)

**edit: my answer fails for multi-digit numbers**4. Verify that x is true. Don’t use true, false or any other variable, value or function (apart from x) (12)

5. Swap the values of variables a and b without using another variable or property (13)

6. Is n an integer? (7)

7. x is an array of numbers. Get the maximum value in x (20)

8. If b is not a member of array a, add it to the end of the array (ECMA 5) (25)

9. Make a string consisting of string x repeated n times (23)

10. Concatenate arrays a and b without using concat (18)

/* only tested in Chrome, but should work in all “major” afaics */

1. i=f.length;while(i–)f[i].length||f[i]();

2. [2,'a','g',5]; // :)

3. with(Math)max(min(b,c),a)==b;

4. x==!!(x+’.’);

5. a=[b,b=a][0]; // credit to @abozhilov

6. Math.floor(n)==n;

7. Math.max.apply(1,x);

8. a.indexOf(b)<0&&a.push(b);

9. for(s='';n–;)s+='x';

10.a.push.apply(a,b);

1. Beat me by 12 – congrats!

2. cheating ;-) rephrased question

8. I squeezed out one more char with an evil hack

9. Very nice! – beat me by 4 – was wondering if you wrote the version I cribbed!

3. [a,b,c].sort().indexOf(b)==1

You can squeeze a few more bytes out of that idea – and make it work in IE ;-)

9. Actually kangax beat me by 6! – you put extra quotes around x that you don’t want

for(s=”;n–;)s+=x;

For #9, both of these are the same length (note that the latter doesn’t modify n)

for(s=”;n–-;)s+=x

Array(n+1).join(x)

– Cowboy

These answers, from the top of my head, untested, so some are probably bad :p

1: f[n]();

Why 54 chars? I must be misunderstanding the question.

2: a.filter(function(x){if(x)return x});

I’m guessing you’re using a different hack, can’t think of it though.

3: ?

No idea.

4: !!x==!!x;

An operator is no function. Without operators… I don’t know.

5: b=[a,a=b][0];

I’ve seen this trick elsewhere,7. SAme asnwer or a variant of it anyways.

6: n==+n;

Probably not sufficient.

7: Math.max.apply(0,x);

Possibly your answer.

8: if(!~a.indexOf(b))a.push(b);

Probably your answer.

9: new Array(n+1).join(x);

One of the very few things that stupid constructor is usefull for.

10: a.push.apply(a,b);

Probably a lot like your solution.

Oh, four is bad.

4: x&&(x===!!x);

1. Only one function has no formal parameters – you need to find it first

2.a gobsmacking hack awaits

6. No always returns true for any number

#1 (40 chars)

f.forEach(function(a){!a.length&&a();});

#2 (18 chars)

a.filter(Boolean);

#3 (38 chars)

Math.max(a,b,c)!=b&&Math.min(a,b,c)!=b

#4 (3 chars)

!!x

#5 (16 chars)

x^=y;y=x^y;x^=y;

#6 (9 chars)

n+’.’==n;

#7 (20 chars)

Math.max.apply(0,x);

#8 (26 chars)

a.indexOf(b)<0&&a.push(b);

#9 (23 chars)

new Array(n+1).join(x);

#10 (18 chars)

a.push.apply(a,b);

1. I guess I went for the more simple version of 1 – but you guys did much better

4. !!x will always return true for truthies, false for falseys. We want to detect pure true values

5. nice alternative! – though that would only work for numbers

7. everyone is getting this one!

8. still one character to shave off (love this one ;-) )

Arh yes, with a little bitwise trickery

#8 (25 chars)

~a.indexOf(b)||a.push(b);

;-)

1. for(j=0;k=f[j++];)k.length||k()

4. x===!!x&&x

6. ~~n===n

Note that solutions of #3 by something like:

[a,b,c].sort()[1]==b

does not work, because arrays are sorted lexicographically by default, not numerically.

Whoops – embarrassing mistake! OK going to have to rewrite my official solution. Thanks

4. x===!0

3. [a,b,c].sort()[0]!=b

ack

3. [a,b,c].sort()[1]==b

1:for(i=-1;f[++i].length;);f[i]();

6:!(n%1)

9:for(a=x;–n;a+=x);

1. 32

2. 12

3. ambiguous (what about =, % etc.?)

4. ambiguous (truthy or `true`?)

9. 19

Same bytes for the rest.

3. % is allowed – just the stated operators are not

4. truthy implies not undefined, null, 0 etc.

> 3. % is allowed – just the stated operators are not

Exclusive or inclusive? <= and >= (got eaten above) are ok right?

> 4. truthy implies not undefined, null, 0 etc.

Yeah, so which…?

4. 4 (truthy)

4. 10 (`true`)

3. they are allowed

4. I rephrased the question – no falseys allowed

edit: oh wait – question 4 has to be pure true, not truthy

> edit: my answer fails for multi-digit numbers

Inclusive I guess.

> 3. they are allowed

3. 20

Quizzes of this kind can get pretty awkward without proper test cases. ;)

Update:

2. 18

(12 was `a.map(Date);`. I interpreted the problem as “Make an array of non-falsy values with the same length as a.”)

4. 9

@kangax, in #3 you assume a < b < c, but what about if c < b < a

a=3; b=2; c=1; with(Math)max(min(b,c),a)==b;

false

Good point. Then something like this: `[a,b,c].sort(function(a,b){return b-a})[1]==b`

Sure, but Angus doesn’t allow subtraction for this one :-)

3. Math.min(a, b, c) != b && Math.max(a, b, c) != b;

Again this works in: (a, c)

I like. I put my answers in a gist.

link not working?

anony is in the lead for #3 now that I realized I messed up with default sort

Math.max(a,b,c)!=b&&Math.min(a,b,c)!=b (38)

anony’s #3 says 2 is not bound by 1 and 2. I guess you didn’t say exclusive or inclusive.

sorry – was assuming exclusive – will update

Weird. https://gist.github.com/79ac5918d9c31fd935b7

01. i=f.length;while((n=f[--i]).length);n()

02. a.filter(function(i){return i})

03. x=Math.max,n=Math.min,x(a,n(b,c))==b||n(a,x(b,c))==b

04. x===!!x

05. a=[b,b=a][0]

06. n===(n|0)

07. Math.max.apply(x,x)

08. a.indexOf(b)<0&&a.push(b)

09. Array(n+1).join(x)

10. a.push.apply(a,b)

1. f.map(function(_)_.length||_()) //31 – works on FF3+

4. x===!!x //7

6. n%n+n //5 – result is (int) n only if n is int

7. a.sort().pop() //14

8. a.indexOf(b)?a.push(b):0 //24

1. Nice but not allowed (ECMA 5, FF)

2. Would work for false too

6. result needs to be true or false

7. won’t work for multi-digit numbers (nice though)

8. logic fails – not found will return -1

5. [a,b]=[b,a] //11 – works on FF – needs destruct. assignment

9. while(n–)_+=’_’ //16

like I said – all browsers unless stated

5. Saw it too late :)

1. just needs {} but satyr already stated to have 32

What’s wrong with 7., 8. and 9.?

(I’m omitting trailing semicolons because they aren’t really part of the expression in question)

1. for(i=0;j=f[i++];){j.length||j()}

2. a.filter(Boolean)

3. with(Math)min(max(a,b),c)==b

4. x&&x===!!x

5. a=[b,b=a][0]

6. !(n%1) or n%1==0

7. Math.max.apply(1,x)

8. ~a.indexOf(b)||a.push(b)

9. Array(n+1).join(x)

10. a.push.apply(a,b)

– Cowboy

If you want to see some more minification fun: http://bit.ly/Organ1k

Oops, I totally spaced on #1. After reading the comments I realize I could’ve lost the curly braces. Damn you, Crockford!

1. for(i=0;j=f[i++];)j.length||j()

Now that I’ve seen clarification of #3:

3. with(Math)max(a,b,c)!=b&&min(a,b,c)!=b

– Cowboy

All answers at least as good as mine – very cool

I just realized that for #4, while x&&x===!!x returns a truthy answer, x===!!x&&x returns an actual boolean value, so that should be preferred!

– Cowboy

Another possible (albeit longer) approach for #5:

with({t:a})a=b,b=t

Pingback: Tweets that mention A JS1K Byte-Saver Quiz! « JavaScript, JavaScript -- Topsy.com

1)

i=f.length;while(i–)f[i].length||f[i]();

f.map(function(z){z.length||z()}); // ECMA 5

4)

var x = ‘0’, y = true, z = ‘0’;

y&!y!=y; // True

x&&x===x; // Truthy

z&&z===z; // truthy ‘0’????

6) n%1===0

1.

1.

Here are my solutions:

1. (50 characters)

4. (10 characters)

9. (20 characters)

10. (18 characters)

I couldn’t work out the other answers in a reasonable size!

Nice Quiz!

Angus apologizes for my multi comments :))

4.

typeof x == ‘boolean’ && x;

Isnt ‘boolean’ an value?

yep – disallowed ;-)

1.l=f.length;while(f[--l].length);f[l]() (38)

(f.filter(function(i){return !i.length}))[0]() – ES5 and not only (46)

2. a.filter(Boolean) (17)

3. Didn’t understand first question at all (maybe because of English formulation). But then cheated a bit from kangax answer (of what is asking) ;D (there were no other cheatings. really :|)

m=Math;m.max(a,m.min(b,c))==b

Oh, and moreover, it’s not correct :D No more cheating ;)

4. x===!””

5. a=[b,b=a][0] (12) (C) from c.l.js, don’t remember @abozhilov or somebody else

6. ~~n===n (7) – not for all numbers

Math.floor(n)==n (16)

7. Math.max.apply(0,x) (19)

8. a.indexOf(b)<0&&a.push(b) (25)

9. Array(n+1).join(x) (18)

10. (a+","+b).split() (17)

10. seems to be wrong

var a = [1], b = [2];

(a+","+b).split(); // ["1,2"] its an string instead of an array

(a+","+b).split(',') //[1,2]

(a+","+[","]).split(','); // doesnt work either ["1", "", ""]

Yep, forgot “,”, should be .split(“,”). But that’s crappy quick solution which won’t work with other values.

Also there is a typo in 6, should be ===: Math.floor(n)===n.

4. Could be rewritten as x===!0 to save a byte

10. Wouldn’t work if the array had anything besides simple numbers…

Yeah, absolutely correct. That was just quick first-in-mind solution. Good approach is mentioned here a.push.apply(a,b).

This was fun but many of the initial questions were unclear and ambiguous and the test changed after people had already answered. You may want to run the test by a few people first before you post it next time, but thanks just the same.

(I’d be happy to review any future tests)

I would also like to volunteer.

Actually I did have a reviewer and 90-95% of folks understood questions without ambiguity. Question 3 “bounded by” (inclusive or exclusive) was the one thing that was genuinely ambiguous (and I changed that wording after my reviewer saw it – so thats my fault :-) )

But offers appreciated anyway ;-)

Cool idea, we should gather some more simliar questions, before we get bored

//#1

while(a=f.pop())a.length||a();

//#2

a.filter(Boolean);

//#3

with(Math)max(a,b,c)!=b&&min(a,b,c)!=b;

//#4 Something wrong with this?

x===(x==x);

//#5

a=[b,b=a][0];

//#6

~~x===x;

//#7

Math.max.apply(0,x);

//#8

~a.indexOf(b)||a.push(b);

//#9

Array(++n).join(x);

//#10

a.push.apply(a,b);

typo

#1

while(a=f.pop())a.length&&a();

Your logic is incorrect. Your loop calls EVERY function that has one formal parameter. It actually won’t call the function we want it to (the one with no params). The code you were correcting was already correct. :)

A slight variation can fix that (same length):

`while(a=f.pop(),a.length);a()`

Two things I think I will take away from this quiz:

* using Boolean to filter

* ~a.indexOf(b) is 1 byte shorter than a.indexOf(b)<0

yes and these were the hardest two for folks to crack.

There are other cool variations on the filter([[Type]]) idea

e.g.

[1, 'foo', 90.3, {bar:1}, 54].filter(Number)

As a bonus, mine stops the loop when it finds the function. Your solution continues looping until the loop is complete.

You are right, i kinda fooled my self. So for what the new version you proposed?

The only functional difference with my proposed answer is it stops when it finds the solution.

I snuck away the trailing semicolons. Really liked Cowboy’s solution for #8, though.

1. [39 bytes] for(i=f.length;i–;)f[i].length||f[i]()

2. [17 bytes] a.filter(Boolean)

3. [28 bytes] Math.min(Math.max(a,b),c)==b

4. [10 bytes] x&&x===!!x

5. [12 bytes] a=[b,b=a][0]

6. [7 bytes] ~~n===n

7. [19 bytes] Math.max.apply(0,x)

8. [24 bytes] ~d.indexOf(b)||d.push(b)

9. [18 bytes] for(s=”;n–;)s+=x

10. [17 bytes] a.push.apply(a,b)

@1 :

i=0;while(f[i++].length);f[i-1]()

33 chars

Lots of cool answers. Just one thing: if the functions inside the array are anonymous, you can order them using the sort method, that will sort them according to the number of arguments they accept.

1) f = [function(x){console.log('one')},function(y, z){console.log('two');},function(){console.log('zero');}];

f.sort()[0]() //13 characters

Unfortunately, if the functions are not anonymous, the sort method will sort them elements by their names.

Yep – thats a really neat trick!