Down the Rabbit Hole – coding challenge

I’ve been looking to level up my Javascript coding skills, and I came across this “mock” coding interview with Dan Abramov by Ben Awad.

I got the first question right (sortof) which asked about the difference between var, let and, const in Javascript. Short answer:

Variables declared with var are hoisted to the top of the function scope.

So if you declare a function with var like this:

function greet() { 
  console.log(x);
  var x = "hello";
  console.log(x);
}

You will not get a compile error. But it will print “undefined” the first time. Because the var declaration is “hoisted” before executing so the function ends up executing something like this:

function greet() { 
  var x;
  console.log(x); // this will print "undefined"
  x = "hello";
  console.log(x); // this will print "hello"
}

But if you declare your variable with let like this:

function greet() { 
  console.log(x);
  let x = "hello";
  console.log(x); 
}

The variable ‘x’ will not be hoisted, and you will get an error:

Uncaught ReferenceError: Cannot access 'x' before initialization

Oh, and const isn’t really a constant. Unless you’re talking primitives like numbers and strings. It only means you cannot reassign the variable — only modify it’s contents. Like this works:

const x = {a:1, b:2};
x.a = 3; // this works, x ==> {a:3, b:2}

const y = [1, 2, 3];
y[0]; = "changed" // this works y ==> ["changed", 2, 3]


I was feeling fairly good about myself, especially when I was able to fairly easily (mostly) solve the CSS question which asked to center a React component vertically and horizontally on the page because I’d recently been playing with display: flex.

body {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
}

Only it didn’t center vertically.

But I got it to work by setting the body height to 100vh (not 100%).

body {
  height: 100vh;
}

Except it was off by a few pixels because of the borders I added to check:

body {
  border: 1px solid red;
}
.App {
  border: 1px solid green;
}

So I compensated:

body {
  width: calc(100vw - 2px);
  height: calc(100vh - 2px );
}

And then I watched how they did it.

Turns out you need to specify: html, body { /* style */ } — but I considered that to be good enough because it’s one of those browser quirks.

html, body {
  width: 100%;
  height: 100% 
}

I was feeling pretty good at that point. And even better when a React contributor essentially said “Don’t use Redux.” Which was what turned me off right at first (ok, after JSX).

I was totally blown out of the water about how to reverse a B-Tree — but it turns out that it was fairly easy using recursion. (I don’t do recursion well).

But the answer is fairly simple once you see it (and trust the recursion):

function invertTree(node) {
  var temp = node.left;
  node.left = node.right;
  node.right = temp;
  invertTree(node.left);
  invertTree(node.right);
}

At least I got the part about only using 1 temp variable.

Next was a real brain teaser … about how to guess which hole a rabbit is in. Out of 100 holes. And it moves every time by 1 hole, either plus or minus 1.

Watch the explanation here:

I was happy to see that Dan Abramov, like myself, considered this be possibly non-deterministic.

The best I could come up with was to either:

1) Guess randomly until I got it right (odds of 1% each try, probably get it in a few hundred tries)

2) Guess the same number (eg. 50) until it lands on that number.

The problem with either of these methods is that it is entirely possible that it never gets it right.

Then Ben Awad gave a hint about how it will always be even or odd.
So here is my solution, unoptimized. I will have to watch to see if there is a better one.

# rabbit.js

function random (n) { return Math.floor(n * Math.random()) } // (generate a random number between 0 and n-1)
function left_or_right() { return random(2) ? -1 : +1 } // (randomly) return -1 or +1 

// rabbit's initial position 
let rabbit = random(100)

function move() {
	rabbit += left_or_right()

	if (rabbit < 0) {
		rabbit == 1
	}
	if (rabbit > 99) {
		rabbit == 98
	}

	console.log(`The rabbit moved to ${rabbit}`)
	return rabbit
}

function look(hole) {
	if (rabbit != hole) {
		console.log(`wrong! (The rabbit was in ${rabbit}`)
		move()
		return false;
	}
	else {
		console.log(`right! (You found the rabbit in ${rabbit}`)
		return true;
	}
}


let hole = 0
let found = false
let guesses = []

while (! found)
{
	guesses.push(hole)
	found = look(hole)

	// finish if we found the rabbit
	if (found) { break }

	// test each hole twice to make sure the rabbit doesn't pass us ( 0, 0, 1, 1, ...)
	guesses.push(hole)
	found = look(hole)

	// check the next hole
	hole += 1
}

console.log(guesses)
console.log(`It took ${guesses.length} guesses to find the rabbit`)
/**
* rabbithole.js
*
* There are 100 holes, all in a row, and a long tunnel connecting them.
* A rabbit lives down there, and you're trying to catch him.
* The rabbit starts down 1 one of the holes, but you don't know which.
* Every time you look down into a hole the rabbit moves.
* But he only moves one hole — either left or right.
* How can you find the rabbit? And how long will it take?
*
* Here is my solution to the problem.
* It takes at most 200 tries, (2 * O(n)
*/
function random (n) { return Math.floor(n * Math.random()) } // generate a random number between 0 and n-1
function left_or_right() { return random(2) ? -1 : +1 } // (randomly) return -1 or +1
// rabbit's initial position
let rabbit = random(100)
function move() {
rabbit += left_or_right()
// rabbit can't go left from first hole
if (rabbit < 0) { rabbit = 1 }
// rabbit can't go right from last hole
if (rabbit > 99) { rabbit = 98 }
console.log(`The rabbit moved to ${rabbit}`)
return rabbit
}
function look(hole) {
if (rabbit != hole) {
console.log(`wrong! The rabbit was in ${rabbit}`)
move() // the rabbit moves whenever you look
return false;
}
else {
console.log(`right! You found the rabbit in ${rabbit}`)
return true;
}
}
let hole = 0 // start at the first hole
let found = false
let guesses = []
while (! found & hole < 100)
{
guesses.push(hole)
found = look(hole)
// finish if we found the rabbit
if (found) { break }
// test each hole twice to make sure the rabbit doesn't pass us ( 0, 0, 1, 1, …)
guesses.push(hole)
found = look(hole)
// check the next hole
hole += 1
}
console.log(guesses)
console.log(`It took ${guesses.length} guesses to find the rabbit`)
view raw rabbithole.js hosted with ❤ by GitHub

Leave a comment