Airbnb's phone screening question for an engineering position

This question I've heard from friend of mine who, recently, had a phone interview with AirBnB.

Here is the question:

Total booking price = base price + service fee + cleaning fee + ...

Create a function which satisfy following condition:
Input: An array of decimals ~ X
Output: An array of integers ~ Y

sum(Y) = round(sum(x))
minimize the value of (|y1-x1| + |y2-x2| +… + |yn-xn|)

Example 1:
input = [0.3, 0.5, 0.6, 0.8, 0.9, 2.1, 3.4]
output = [ 0, 1, 1, 1, 1, 2, 3 ]

Example 2:
input = [0.5, 7.6, 47.4]
output = [ 1, 8, 47 ]


I've decided to solve it in my free time using Javascript, here is my solution:



//let numbers = [0.3, 0.5, 0.6, 0.8, 0.9, 2.1, 3.4]; // input
//let numbers = [0.7, 0.7, 0.8];
//let numbers = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1];
//let numbers = [3.7, 1.7, 0.8];
let numbers = [0.5, 7.6, 47.4];

function roundNumbers(input) {
  let flooredNumbers = input.map(function(a){return Math.floor(a)});
  let sumLeft = Math.round(sum(input)) - sum(flooredNumbers);
  let sorted = [];
  input.forEach(function(a,i){
    sorted.push({
      idx: i,
      elm: (a-Math.floor(a))
    })
  });
  sorted.sort(function(a,b){ return b.elm - a.elm});
  let i = 0;
  while(i < sumLeft) {
    flooredNumbers[sorted[i].idx] += 1;
    i++;
  }
  return flooredNumbers;
}

function sum(arr) {
  return arr.reduce((a, b) => a + b, 0);
}

roundNumbers(numbers);

Getting CSS pseudo-element properties by Javascript

You probably wonder if you can access CSS pseudo-element's (like ::before or :: after) properties by Javascript.

The answer is yes, you can, but it's tricky :)

Let's assume you have following HTML/CSS


<p id="myid">some content</p>



#myid::after {
  display:block;
  width: 100px;
  height: 40px;
  color: blue;
  content: "Hello world";
}
#myid {
  color: red;
}


Apparently, "#myid::after" is not in the DOM tree, but following trick will allow you to get its properties:


var color = window.getComputedStyle(document.querySelector('#myid'), ':after').getPropertyValue('color')
var content = window.getComputedStyle(document.querySelector('#myid'), ':after').getPropertyValue('content')
console.log(color, content) // outputs the color and content of the pseudo-element

You might find it useful in test automation or some UI interaction manipulation.

URL parsing using native JS engine approach

The snippet bellow can come in handy when you need basic URL parsing


/**
 * @description URL parsing using native JS engine approach
 * @param {string} url - URL string
 * @returns {object} parsed data
 */

function parseURL(url) {
	var parser = document.createElement('a');
	parser.href = url;
	return {
		protocol : parser.protocol, // => "http:"
		hostname : parser.hostname, // => "domain.com"
		port : parser.port, // => "8000"
		pathname : parser.pathname, // => "/path/"
		search : parser.search, // => "?search=test"
		hash : parser.hash, // => "#hash"
		host : parser.host // => "domain.com:8000"
	}
}

console.dir(parseURL("http://domain.com:8000/path/?search=test&bar=1&bar=2&key1=val1#hash"));

How to check how many threads node.js is using on Linux?

We all know Node is single threaded, however, it's single threaded for a client (to you as a programmer), but the platform itself is multi-threaded (internally). In order to check how many threads your node is using on Linux machine you have 3 different options:

1.
cat /proc/`pidof node`/status | grep Threads

2.
ls /proc/19899/task/ | wc -l

3.
ps hH p `pidof node` | wc -l


Sometimes, it come in handy when you want to automate the load monitoring for example.

What If you want to to determine whether is 64bit or 32bit node executable installed?

You can try 3 following options:

1) Run node cli and type there:
require('os').arch()

3) Or type there:
process.arch

3) Or type there:
process.env.PROCESSOR_ARCHITECTURE


One of them will work for sure! (The latest one doesn't work on my Macbook but does on Win10 machine)

Mongoose 4.0.2 doesn't create indexes

Mongoose 4.0.2 doesn't create indexes automatically for some reason despite of its docs.
So I've found if you add {autoIndex: true} as it's shown bellow, it solves the issue.


var path = require('path');

module.exports = function (mongoose) {
    var Schema = new mongoose.Schema({
        name: {type: String, trim: true, required: true},
        uuid: {type: String, required: true, unique: true, index: true},
        device: {type: mongoose.Schema.Types.Mixed},
        updated_at: {type: Date, default: Date.now}
    }, {autoIndex: true});
    return mongoose.model(path.basename(module.filename, '.js'), Schema);
};

How JSONP works

JSONP is really a simple trick to overcome the XMLHttpRequest same domain policy. (As you know one cannot send AJAX (XMLHttpRequest) request to a different domain.)

So — instead of using XMLHttpRequest we have to use script HTML tags, the ones you usually use to load js files, in order for js to get data from another domain. Sounds weird?

Thing is — turns out script tags can be used in a fashion similar to XMLHttpRequest! Check this out:
script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data';


You will end up with a script segment that looks like this after it loads the data:
<script>
   {['some string 1', 'some data', 'whatever data']}
</script>


However this is a bit inconvenient, because we have to fetch this array from script tag. So JSONP creators decided that this will work better(and it is):

script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.someWebApiServer.com/some-data?callback=my_callback';


Notice the my_callback function over there? So — when JSONP server receives your request and finds callback parameter — instead of returning plain js array it'll return this:
my_callback({['some string 1', 'some data', 'whatever data']});


See where the profit is: now we get automatic callback (my_callback) that'll be triggered once we get the data.
That's all there is to know about JSONP: it's a callback and script tags.

NOTE: these are simple examples of JSONP usage, these are not production ready scripts.

Basic JavaScript example (simple Twitter feed using JSONP)
<html>
    <head>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
        <script>
        function myCallback(dataWeGotViaJsonp){
            var text = '';
            var len = dataWeGotViaJsonp.length;
            for(var i=0;i<len;i++){
                twitterEntry = dataWeGotViaJsonp[i];
                text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
            }
            document.getElementById('twitterFeed').innerHTML = text;
        }
        </script>
        <script type="text/javascript" src="http://twitter.com/status/user_timeline/padraicb.json?count=10&callback=myCallback"></script>
    </body>
</html>


Basic jQuery example (simple Twitter feed using JSONP)

<html>
    <head>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
        <script>
            $(document).ready(function(){
                $.ajax({
                    url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10',
                    dataType: 'jsonp',
                    success: function(dataWeGotViaJsonp){
                        var text = '';
                        var len = dataWeGotViaJsonp.length;
                        for(var i=0;i<len;i++){
                            twitterEntry = dataWeGotViaJsonp[i];
                            text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>'
                        }
                        $('#twitterFeed').html(text);
                    }
                });
            })
        </script>
    </head>
    <body>
        <div id = 'twitterFeed'></div>
    </body>
</html>

JSONP stands for JSON with Padding.

© ThatGuy

The "open with" context menu shows twice the same item fix

If you get something like:



The following command could help this issue, just copy paste this whole line into your terminal

/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -all s,l,u; killall Finder

Really crazy Javascript's Fibonacci implementation

Run it in console and see it's really working :)


  var fib = function (_) {
      for(_=[+[],++[[]][+[]],+[],_],_[++[++[++[[]][+[]]][+[]]][+[]]]=(((_[++[++[++[[]][+[]]][+[]]][+[]]]-(++[[]][+[]]))&(((--[[]][+[]])>>>(++[[]][+[]]))))===(_[++[++[++[[]][+[]]][+[]]][+[]]]-(++[[]][+[]])))?(_[++[++[[]][+[]]][+[]]]=++[[]][+[]],_[++[++[++[[]][+[]]][+[]]][+[]]]-(++[[]][+[]])):+[];_[++[++[++[[]][+[]]][+[]]][+[]]]--;_[+[]]=(_[++[[]][+[]]]=_[++[++[[]][+[]]][+[]]]=_[+[]]+_[++[[]][+[]]])-_[+[]]);
      return _[++[++[[]][+[]]][+[]]];
  }

  console.assert(fib(-1) === 0);
  console.assert(fib(0) === 0);
  console.assert(fib(1) === 1);
  console.assert(fib(2) === 1);
  console.assert(fib(3) === 2);
  console.assert(fib(4) === 3);
  console.assert(fib(5) === 5);
  console.assert(fib(6) === 8);
  console.assert(fib(7) === 13);
  console.assert(fib(32) === 2178309);
  console.assert(fib(46) === 1836311903);
  console.assert(fib(47) === 2971215073);
  console.assert(fib(63) === 6557470319842);

  console.log('done!');


More could be found at: wtfsjs

Twisted logic: understanding truthy and falsy

An upcoming article I'll be doing for Smashing Magazine will look at the oddities and gotchas of Javascript — and lordie does it have a few.

One of these is the concept of truthy and falsy. These are sort of like true/false-lite, which will anger you somewhat if you majored in logic or philosophy. You mean you didn't know true and false were in fact gradable, not absolute concepts!?

In Javascript, every value has an in-built flag denoting its boolean equivalent. This is called upon when you ask the value to behave like a boolean, e.g. by comparing it to a real boolean. Javascript coerces your value into a boolean, such that the comparison is possible (after all, you can't compare apples with pears). See below for more on data coercion. So:

var someVar = 0;
alert(someVar == false); //evaluates true

Since we are attempting to compare zero to a boolean, Javascript coerces the zero to its truthy/falsy equivalent — and zero is a falsy (along with null, undefined, NaN, empty strings and false — everything else is a truthy). So the expression effectively becomes:

alert(false == false); //evaluates true, of course


It's important to realise that this does not mean your value is a boolean — it simply means Javascript temporarily converts it to a boolean to make the comparison possible. If we did the same comparison with the === operator (which compares not only by value but also by type), the result would be different:

alert(someVar === false); //evaluates false - someVar is a number, not a legitimate boolean


It gets worse

Clear enough? It gets more complex.

A well known quirk of Javascript is that an empty array appears to be equal to false.


( Read more )