The Most Challenging Interview Question

D

David Mark

Ry said:
Ry said:
function removeThrees (a) {
var i= 0;
while (i < a.length) a === 3 ? a.splice(i, 1) : i++;
return a;
}

Terrible. Don't use the ternary operator in that fashion.


Yeah, the ternary operator was not designed to remove threes.


Don't be a twit. Ask your buddy what he thinks of the style.
 
D

David Mark

nick said:
[...]
Ry said:
[...]
function removeThrees (a) {
var i= 0;
while (i < a.length) a === 3 ? a.splice(i, 1) : i++;
return a;
}

Terrible. Don't use the ternary operator in that fashion.

Why not?


Bad style. One end splices an array, the other increments a variable.
That's really ugly.
I'm not trying to sound rude, I am genuinely curious. I have almost
never seen the ternary operator used other than to the right of an
assignment operator, with the exception of two times, both recently...
once just now, and once in VK's ggNoSpam.

I just double-checked whether this kind of thing works in C++; it
seems to work fine there too.

So, I'm curious why you say not to do it. Is it because it's an
unusual thing to do and therefor difficult to read, or for a more
technical reason? I think I would naturally avoid using it like that
(not as part of an assignment), but only because it's something you
just don't see a lot.

For sparse arrays, I like:

function removeThrees (a) {
for (var i=0; i<a.length;)
if (a===3) a.splice(i, 1); else i++;
return a;
}


There you go. :) Isn't that much easier on the eyes? You are missing
a few brackets though. Despite a few clunkers, most of what JSLint
tells you is good advice.
For dense arrays, this will also work:

function removeThrees (a) {
var i=0, e;
while (typeof (e=a)!='undefined')
if (e===3) a.splice(i, 1); else i++;
return a;
}


I don't care for that one (because of the way the assignment to e is done).
 
D

David Mark

Ry said:
Ry said:
Ry Nohryb wrote:
function removeThrees (a) {
var i= 0;
while (i < a.length) a === 3 ? a.splice(i, 1) : i++;
return a;
}
Terrible. Don't use the ternary operator in that fashion.
Yeah, the ternary operator was not designed to remove threes.

Don't be a twit. Ask your buddy what he thinks of the style.


"Ask your buddy" ? My buddy ? Who's my buddy ?


You sound like a parrot. :)

Who do you think your buddy is? Hint: lint.
 
R

Ry Nohryb

Ry said:
Ry Nohryb wrote:
function removeThrees (a) {
  var i= 0;
  while (i < a.length) a === 3 ? a.splice(i, 1) : i++;
  return a;
}
Terrible.  Don't use the ternary operator in that fashion.

Yeah, the ternary operator was not designed to remove threes.

Don't be a twit.  Ask your buddy what he thinks of the style.


"Ask your buddy" ? My buddy ? Who's my buddy ?
 
R

Ry Nohryb

Ry said:
Ry Nohryb wrote:
Ry Nohryb wrote:
function removeThrees (a) {
  var i= 0;
  while (i < a.length) a === 3 ? a.splice(i, 1) : i++;
  return a;
}
Terrible.  Don't use the ternary operator in that fashion.
Yeah, the ternary operator was not designed to remove threes.
Don't be a twit.  Ask your buddy what he thinks of the style.

"Ask your buddy" ?  My buddy ? Who's my buddy ?

You sound like a parrot.  :)

Who do you think your buddy is?  Hint: lint.


No no no. It would hurt my feelings!

I often do:

-Assignments in the test part of ifs and whiles: if (a=b)
-Flow control with boolean operators: !done && continue();
-whiles and ifs without blocks: while (cond) whatever();
-other heretical constructions.

So JSLint is not for me. Thanks but no, thanks.
 
D

David Mark

Ry said:
Ry said:
Ry Nohryb wrote:
Ry Nohryb wrote:
function removeThrees (a) {
var i= 0;
while (i < a.length) a === 3 ? a.splice(i, 1) : i++;
return a;
}
Terrible. Don't use the ternary operator in that fashion.
Yeah, the ternary operator was not designed to remove threes.
Don't be a twit. Ask your buddy what he thinks of the style.
"Ask your buddy" ? My buddy ? Who's my buddy ?

You sound like a parrot. :)

Who do you think your buddy is? Hint: lint.


No no no. It would hurt my feelings!


I was referring to Crockford of course. How can a Web page be your
buddy? :)
I often do:

-Assignments in the test part of ifs and whiles: if (a=b)

Add another set of parenthesis and I'll let it go.
-Flow control with boolean operators: !done && continue();

You would.
-whiles and ifs without blocks: while (cond) whatever();

How perfectly illegible of you.
-other heretical constructions.

....and just look at the difference! :)
So JSLint is not for me. Thanks but no, thanks.

It has many configuration options. Find one that suits you (or find a
similar tool).
 
D

David Mark

RobG said:
Another try:
function removeThrees (a) {
var i=0;
while (i in a) {
if (a === 3) {
a.splice(i, 1);
} else {
i++;
}
}
return a;
}

That won't work for sparse arrays...

var arr = [1];
arr[2] = 3;
console.log(removeThrees(arr)); // [1, undefined, 3]

... because 1 is not "in arr", thus ending your while loop.


The problem is not clearly specified - what should be done with the
matching elements? Should they be removed, moving all subsequent
elements to a lower index? should they be set to undefined? Should
they be removed from the array in a manner that makes their index not
enumerable and keeps the same index for subsequent elements?

e.g. to keep sparseness and length and remove 3s (hasOwnProperty
filter removed for brevity):

function remove3s_sparse(a) {
var b = [];
for (var p in a) {
if (a[p] != 3) {
b[p] = a[p];
}
}
b.length = a.length;
return b;
}

To make the filtered array dense:

function remove3s_dense(a) {
var b = [];
for (var p in a) {
if (a[p] != 3) {
b.push(a[p]);
}
}
return b;
}

A simple for loop could be used, however I seem to remember from a
distant post that accessing undefined elements of a sparse array can
cause them to become enumerable in some UAs. If that is not an issue,
then the following will set filtered elements to undefined and
maintain position and length:

function remove3s_simple(a) {
var o, b = [];
for (var i=0, iLen=a.length; i<iLen; i++) {
if (a != 3) {
b.push(a);
} else {
b.push(o);
}
}
return b;
}

or using the dreaded ternary operator where some think it shouldn't:


If you mean me, then you misunderstood my objection to Ry's usage.
function remove3s_simple2(a) {
var o, t, b = [];
for (var i=0, iLen=a.length; i<iLen; i++) {
t = a;
b = (t == 3)? o : t;
}
return b;
}


Nothing wrong with that operation.
 
R

RobG

Another try:
function removeThrees (a) {
var i=0;
while (i in a) {
if (a === 3) {
a.splice(i, 1);
} else {
i++;
}
}
return a;
}


That won't work for sparse arrays...

var arr = [1];
arr[2] = 3;
console.log(removeThrees(arr)); // [1, undefined, 3]

... because 1 is not "in arr", thus ending your while loop.


The problem is not clearly specified - what should be done with the
matching elements? Should they be removed, moving all subsequent
elements to a lower index? should they be set to undefined? Should
they be removed from the array in a manner that makes their index not
enumerable and keeps the same index for subsequent elements?

e.g. to keep sparseness and length and remove 3s (hasOwnProperty
filter removed for brevity):

function remove3s_sparse(a) {
var b = [];
for (var p in a) {
if (a[p] != 3) {
b[p] = a[p];
}
}
b.length = a.length;
return b;
}

To make the filtered array dense:

function remove3s_dense(a) {
var b = [];
for (var p in a) {
if (a[p] != 3) {
b.push(a[p]);
}
}
return b;
}

A simple for loop could be used, however I seem to remember from a
distant post that accessing undefined elements of a sparse array can
cause them to become enumerable in some UAs. If that is not an issue,
then the following will set filtered elements to undefined and
maintain position and length:

function remove3s_simple(a) {
var o, b = [];
for (var i=0, iLen=a.length; i<iLen; i++) {
if (a != 3) {
b.push(a);
} else {
b.push(o);
}
}
return b;
}

or using the dreaded ternary operator where some think it shouldn't:

function remove3s_simple2(a) {
var o, t, b = [];
for (var i=0, iLen=a.length; i<iLen; i++) {
t = a;
b = (t == 3)? o : t;
}
return b;
}


The dense result could also be achieved using the sparse function
followed by a compressor that removes undefined elements (i.e. where
typeof a == 'undefined') whether they are enumerable or not.


The above issues arise with any array filtering function, like both
sparse and dense filters are required. The only problem remaining is
how to write them to be efficient (which doesn't necessarily mean less
code) and avoid implementation foibles (if any).
 
D

David Mark

Stefan said:
On 09/05/10 21:44, Garrett Smith wrote:

Another try:
function removeThrees (a) {
var i=0;
while (i in a) {
if (a === 3) {
a.splice(i, 1);
} else {
i++;
}
}
return a;
}
That won't work for sparse arrays...

var arr = [1];
arr[2] = 3;
console.log(removeThrees(arr)); // [1, undefined, 3]

... because 1 is not "in arr", thus ending your while loop.

The problem is not clearly specified - what should be done with the
matching elements? Should they be removed, moving all subsequent
elements to a lower index? should they be set to undefined? Should
they be removed from the array in a manner that makes their index not
enumerable and keeps the same index for subsequent elements?


Yes, the problem is underspecified. That may be a good thing in an
interview situation - can the applicant see the problem? Does he know
what a sparse array is? Does he dare to question the requirements? How
will he communicate his dilemma? The problem itself is so simple that I
would guess Dmitry's example was more geared at this meta level. I find
it amusing that such a primitive task would be taken seriously by so
many people in this group, and would bring forward so many different
attempts at a solution. I guess most of us just love challenges :)


Attempts? Ambiguities aside, I stand by my solution.
In any case, one thing is certain: Dmitry wanted all threes removed
(whatever that means for the resulting array), and a function which
leaves a three in cannot be correct.

That's for sure. :)
 
D

Dmitry A. Soshnikov

On 11/05/10 03:12, RobG wrote:
[...]
The problem is not clearly specified - what should be done with the
matching elements? Should they be removed, moving all subsequent
elements to a lower index? should they be set to undefined? Should
they be removed from the array in a manner that makes their index not
enumerable and keeps the same index for subsequent elements?

Yes, the problem is underspecified. That may be a good thing in an
interview situation - can the applicant see the problem? Does he know
what a sparse array is? Does he dare to question the requirements? How
will he communicate his dilemma? The problem itself is so simple that I
would guess Dmitry's example was more geared at this meta level.

Yes, absolutely correct; and that's the main goal. The exact correct
solution even is not so essential as essential the way of thinking,
understanding and explanations provided by the applicant. By such simple
small tasks we can test _how_ an employee will solve the suggested
issue, what questions will he ask (and if will, if which form and so
on), and he's questions/suggestions can help to analyze his knowledge
level completely. E.g. he can only mention concept of sparse arrays (but
not to think how to apply this case also in the solutions) -- and it
will be enough. Etc.

Dmitry.
 
M

MikeMainFrame

Garrett Smith wrote:

[...]


How about a forward loop using splice?
function removeThrees(a) {
  for(var i = 0; i < a.length; i++) {
    if(a === 3) {
      a.splice(i,1);
    }
  }
  return a;
}


I just don't care to evaluate the length property each time through (or
to splice one member at a time), even in an example.  And though
slightly longer, I consider mine to be easier to understand at a glance.
 YMMV.

The strict comparison is a good idea in this case though.


I have followed your discussions and want to suggest this:

WScript.echo(removeThrees([1,2,3,4,5,6,7,8]));

function removeThrees(a) {
var jx=0;
for (var ix = 0; ix < a.length; ix++) {
if(a[ix] !== 3) {
a[jx] = a[ix]
jx++;

}
}
return a.splice(0,jx);
}

Bubbles up the ones you need to delete - then cut off on the way
back ...

I use to do mainframe programming and I was surprised the first time I
experienced the "living" length property - not used to OO ;o)

I was looking for some critisism on JQuery and the like. Found this -
and how nice it was to learn that a professional has to know the
concepts of the language ;o)
 
D

David Mark

MikeMainFrame said:
Garrett Smith wrote:

[...]


How about a forward loop using splice?
function removeThrees(a) {
for(var i = 0; i < a.length; i++) {
if(a === 3) {
a.splice(i,1);
}
}
return a;
}

I just don't care to evaluate the length property each time through (or
to splice one member at a time), even in an example. And though
slightly longer, I consider mine to be easier to understand at a glance.
YMMV.

The strict comparison is a good idea in this case though.


I have followed your discussions and want to suggest this:

WScript.echo(removeThrees([1,2,3,4,5,6,7,8]));

function removeThrees(a) {
var jx=0;
for (var ix = 0; ix < a.length; ix++) {
if(a[ix] !== 3) {
a[jx] = a[ix]
jx++;

}
}
return a.splice(0,jx);
}

Bubbles up the ones you need to delete - then cut off on the way
back ...


Interesting take. Definitely many ways to skin this cat.
I use to do mainframe programming and I was surprised the first time I
experienced the "living" length property - not used to OO ;o)

It's more of an ECMAScript thing than OO. And realize that in your
rendition the length property is unnecessarily evaluated on every
iteration. You are missing a semi-colon too.
I was looking for some critisism on JQuery and the like.

You shouldn't have to look very far around here. It takes a long time
to permeate to the mainstream though as many seem to see such (valid)
criticism as an indictment of open source in general (which it is not).
Found this -
and how nice it was to learn that a professional has to know the
concepts of the language ;o)

What a revelation. If only the library developers would take this to
heart. I'm sure some of them have learned over the years, but the
"major" efforts are trapped in their own initial, ill-advised designs
due to overwhelming early adoption.
 
D

David Mark

Johannes said:
David Mark :

[removeThrees]
Definitely many ways to skin this cat.

What about this one, assuming that no element of a has a ToString value
containing at least one comma (Numbers are safe) ?

a.toString().replace(/^3,/, '').replace(/,3$/, '').
replace(/,3,/g, ',').split(',');

There are several potential problems. For one, it will always end up as
a dense array of strings, which is something you could stipulate in the
documentation.

The first two replace calls can be consolidated as well.
 
G

Garrett Smith

MikeMainFrame said:
Garrett Smith wrote:
[...]

I have followed your discussions and want to suggest this:

[...]

That's clearer and more efficient.
Bubbles up the ones you need to delete - then cut off on the way
back ...

Shifts the set of good elements to the front and saves the length of
that set each iteration.
I use to do mainframe programming and I was surprised the first time I
experienced the "living" length property - not used to OO ;o)

So why did you use `slice` instead of setting `length = jx` the last
statement?

function removeThrees(a) {
var ix, jx=0, len = a.length;
for (ix = 0; ix < len; ix++) {
if(a[ix] !== 3) {
a[jx++] = a[ix];
}
}
a.length = jx;
return a;
}
I was looking for some critisism on JQuery and the like. Found this -
and how nice it was to learn that a professional has to know the
concepts of the language ;o)

Seems to be the opposite where I live. Endorsing a library has become
nearly a requirement for any professional jobs here. Not a jQuery fan?
Good luck.
 
R

Ry Nohryb

MikeMainFrame said:
I have followed your discussions and want to suggest this:

function removeThrees(a) {
 var jx=0;
   for (var ix = 0; ix < a.length; ix++) {
     if(a[ix] !== 3) {
       a[jx] = a[ix]
       jx++;

     }
   }
   return a.splice(0,jx);
}

That's clearer and more efficient.

No, genius, no.
Shifts the set of good elements to the front and saves the length of
that set each iteration.

No, it does not shift them it *duplicates* them, and in the process,
it makes sparse arrays dense :

a= [];
a[10]= 27;
for (p in a) console.log(p);
--> 10
5 in p
--> false

for (p in removeThrees(a)) console.log(p);
--> 0,1,2,3,4,5,6,7,8,9,10
5 in p
--> true
 
R

Ry Nohryb

MikeMainFrame said:
I have followed your discussions and want to suggest this:
function removeThrees(a) {
var jx=0;
for (var ix = 0; ix < a.length; ix++) {
if(a[ix] !== 3) {
a[jx] = a[ix]
jx++;
}
}
return a.splice(0,jx);
}

That's clearer and more efficient.

No, genius, no.
Shifts the set of good elements to the front and saves the length of
that set each iteration.

No, it does not shift them it *duplicates* them, and in the process,
it makes sparse arrays dense :

a= [];
a[10]= 27;
for (p in a) console.log(p);
--> 10
5 in a
--> false

for (p in removeThrees(a)) console.log(p);
--> 0,1,2,3,4,5,6,7,8,9,10
5 in a
--> true
 
D

David Mark

Garrett said:
Seems to be the opposite where I live. Endorsing a library has become
nearly a requirement for any professional jobs here. Not a jQuery fan?
Good luck.

So endorse your own and/or demonstrate why the shop is making a mistake
hiring "fans" of jQuery. Look at the results.
 
D

Dr J R Stockton

In comp.lang.javascript message <16586391-3d42-49f6-89a6-a2015b993d1a@k1
9g2000yqm.googlegroups.com>, Fri, 7 May 2010 05:27:23, Dmitry A.
Soshnikov said:
"Let there is an array. How to remove all elements with value 3 from
it?"

The first response should be to ask whether 3 is a Number value or a
String value.

Another is to ask whether the gaps must be closed up : if the array is
long, it could be better to replace the threes with null or undefined,
if the application using the array will not mind.

One should check whether order must be preserved - it is conceivable
that it might be best to use the default sort method, which should be
quick, then to remove the now-contiguous threes in one go. After all,
the intent may have been to sort the array next. And if the entries
look otherwise like current dates as seconds-from-epoch, then sorting
brings the threes to the front.


However, there can be no point in removing the threes unless the whole
of the purified array will be used later; and the speed of the
purification is unimportant as long as it does not significantly delay
the final result. Therefore, the simplest and most readily maintainable
method is probably best : scan the whole of the array, and push any
element which is not three into another array to be used for the rest of
the job (assumption : that there is enough memory for both arrays).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,079
Messages
2,570,574
Members
47,205
Latest member
ElwoodDurh

Latest Threads

Top