BRAIN TEASERS WITH CODING FOR DATA SCIENTIST

Copyright © 2020 Virag R Shah

All rights reserved.

For additional information, contact the author.

Virag R. Shah: viragbook@gmail.com

DISCLAIMER

Every effort has been made to avoid errors or omissions in the publication. In spite of this, some errors might have crept in. The publisher or author shall not be responsible for the same. Any mistake, error or discrepancy noted may be brought to our notice which shall be taken care of in the next edition. It is notified that neither the publisher nor the author will be responsible for any damage or loss of action of any one, of any kind, in any manner, therefore.

ACKNOWLEDGMENTS

First of all, I want to thank you for choosing this book, ‘Brain Teasers with Coding for Data Scientist’. I sincerely hope you will enjoy the brain teasers in this book.

The brain teasers are chosen from a collection of problems that I have encountered over the years in interviews, books, websites and blogs. They are represented in a generalized form in this book.

CONTENTS

Title

Page No.

INTRODUCTION

ii

Brain Teaser Titles

Page No.

1

HELLO WORLD

3

2

BASIC CODING

3

3

N ANTS

4

4

N STAIRS

4

5

DEATH RAT

4

6

BULLET CURVE

5

7

BIRTHDAY MATCH

5

8

FAIR COIN

5

9

N COINS FLIP

6

10

N BAGS

6

11

RAIN IN THE CITY

6

12

N PRISONERS & N BOXES

7

13

N TOWERS OF HANOI

7

14

CLOCK ANGLE

8

15

BALLS ON A PLANE

8

SOLUTION

10

ABOUT AUTHOR

51

INTRODUCTION

Brain teasers, kind of puzzles built for lateral thinking, can help to improve cognitive skills. Lateral thinking is a way of solving problems using an indirect and creative approach via reasoning that is not immediately obvious. It involves ideas that may not be obtainable using only traditional step-by-step logic.

Traditionally during software engineering or analytics positions hiring, some companies may ask brain teaser(s) to test how a candidate thinks and approaches a new problem when faced with one. Data Science started with statistics has evolved to include the concepts of software engineering and so does its hiring practices. Whether you are trying to improve your coding skills or preparing for a data science interview, you should at least try on them to test your critical thinking and logic. In data science, statistics is a great supplement to the traditional coding brain teasers.

In this book, you will find interesting brain teasers that are suitable for data scientists as well as software engineers. Solutions also have included coding where possible. So, get ready and jump into the world of fascinating and exciting brain teasers.

1 HELLO WORLD

Let’s start with basic coding. Python and R are the most widely used programming languages among others (for example, Java, Scala, Matlab) for data science.

Python code snippet is given below:

if <condition>:

print("Hello")

else:

print("World")

What’s the <condition> so that the code snippet prints “Hello World”?

2 BASIC CODING

Print ‘I am 10th’ in every computer language you know.

3 N ANTS

Imagine there are N ants in N different corners of an equilateral polygon, and each ant randomly picks a direction and starts traversing the edge of the polygon. What’s the probability that none of the ants collide? (Provided condition: N>2)

Write a code.

4 N STAIRS

There are n stairs; a person standing at the bottom wants to reach the top. The person can take any number k steps. How many distinct ways can the person reach the top of the staircase?

Write a code.

5 DEATH RAT

You have X wine bottles, one of which is poisoned. You want to determine which bottle is poisoned by feeding the wine to the rats. The poisoned wine takes Z hour to work. How many rats are necessary to find the poisoned bottle in Y hour? (Provided condition: Y is multiple of Z.)

Write a code.

6 BULLET CURVE

N persons are standing in a circle. They are labeled from 1 to N in clockwise order. Every one of them is holding a gun and can shoot a person on his left. Starting from person 1, they starts shooting in order e.g for N=100, person 1 shoots person 2, then person 3 shoots person 4, then person 5 shoots person 6……..then person 99 shoots person 100, then person 1 shoots person 3, then person 5 shoots person 7……and it continues till all are dead except one. What’s the index of that last person?

Write a code.

7 BIRTHDAY MATCH

There are X students in the class. What is the possibility that at least 2 students share the same day of birth? (Provided condition: No student is born in a leap year.)

Write a code.

8 FAIR COIN

Make a fair (unbiased) coin from an unfair (biased) coin.

Write a code.

9 N COINS FLIP

You have an N coins laying flat on a table, each with a head side and a tail side. M of them are heads up, rest are tails up. You can’t feel, see or in any other way find out which M are heads up. Your goal: split the coins into two piles so there are the same numbers of heads-up coins in each pile.

Write a code.

10 N BAGS

You have N bags full of coins. In each bag are infinite coins. But one bag is full of forgeries, and you can’t remember which one. But you do know that genuine coins weigh 1 gram, but forgeries weigh 1.1 grams. You have to identify that bag in minimum readings. You are provided with a digital weighing machine.

11 RAIN IN THE CITY

You are about to get on a plane to Mumbai, you want to know whether you have to bring an umbrella or not. You call N of your random friends and ask each one of them if it’s raining. The probability that your any friend is telling the truth is 2/3 and the probability that (s)he is playing a prank on you by lying is 1/3. If all N of them tell that it is raining, then what is the probability that it is actually raining in Mumbai.

12 N PRISONERS & N BOXES

The director of a prison offers N death row prisoners, who are numbered from 1 to N, a last chance. A room contains a cupboard with N boxes. The director randomly puts one prisoner's number in each closed boxes. The prisoners enter the room, one after another. Each prisoner may open and look into N/2 boxes in any order. The boxes are closed again afterwards. If, during this search, every prisoner finds his number in one of the boxes, all prisoners are pardoned. If just one prisoner does not find his number, all prisoners die. Before the first prisoner enters the room, the prisoners may discuss strategy — but may not communicate once the first prisoner enters to look in the boxes. What is the prisoners' best strategy?

13 N TOWERS OF HANOI

There are N pegs. Each peg can hold discs in decreasing order of radius when looked from bottom to top of the peg. There are M discs which have radius 1 to M. You are required to do the transformations in minimal number of moves. A move consists of picking the topmost disc of any one of the pegs and placing it on top of any other peg. At any point of time, the decreasing radius property of all the pegs must be maintained.

Write a code to find the minimum number of moves for N pegs & M discs.

14 CLOCK ANGLE

Given HH:MM. Calculate the angle between the hour and the minute hand.

Write a code.

15 BALLS ON A PLANE

How many numbers of balls with radius 'r' can fit in an airplane of length L and interior radius R?

Write a code.

SOLUTIONS

1 HELLO WORLD

The below program prints “Hello World”

if print("Hello", end =" "):

print("Hello")

else:

print("World")

Explanation:

Here, <condition> = print("Hello", end =" ")

In Python : print() function doesn't return anything (so it's None).

By default Python’s print() function ends with a newline. You can end a print statement with any character/string using this parameter. Let's see

# default end parameter '\n'

print("Hello")

print("World")

-- Output is --

Hello

World

# Now change end parameter value

# ends the output with a <space>

print("Hello " , end = ' ')

print("World" , end = ' ')

-- Output is --

Hello World

Extra: what is the output of below code?

print(print())

print("***")

print(print("Hello World"))

print("***")

print(print(print("Hello World")))

Output you will get is shown below:

None

***

Hello World

None

***

Hello World

None

None

2 BASIC CODING

1. C

#include <stdio.h>

int main() {

printf("I am 10th");

return 0;

}

2. Python

print("I am 10th")

3. Java

public class HelloWorld{

public static void main(String []args){

System.out.println("I am 10th");

}

}

4. C++

#include <iostream>

int main()

{

printf("I am 10th");

return 0;

}

5. C#

using System.IO;

using System;

class Program

{

static void Main()

{

Console.WriteLine("I am 10th");

}

}

6. Visual Basic

Module VBModule

Sub Main()

Console.WriteLine("I am 10th")

End Sub

End Module

7. JavaScript

<!DOCTYPE html>

<html>

<body>

<p id="tenth"></p>

<script>

document.getElementById("tenth").innerHTML = "I am 10th"

</script>

</body>

</html>

8. PHP

<?php print("I am 10th"); ?>

9. R

print("I am 10th")

10. SQL

BEGIN TRANSACTION;

CREATE TABLE FORPRINT(Id integer PRIMARY KEY);

COMMIT;

SELECT 'I am 1'||count(*)||'th' FROM FORPRINT where 1=2;

3 N ANTS

There are only two possibilities in which collision can be occurred.

- All ants move in counterclockwise direction.

- All ants move in anti-counterclockwise direction.

Since every ant has two choices (pick either of two edges going through the corner on which ant is initially sitting). So for N ants there are total 2N possibilities.

Probability that none of the ants collide = ( 2N  - 2)/ 2N

= ( 2N-1   - 1)/ 2N-1

import math

# Non Collide Probability for N ANTS

# N Number of Ants & N > 2

N = 3

# P Probability

P = (math.pow(2,N-1)-1)/math.pow(2,N-1)

print('Probability that none of', N, 'ants collide:', P)

Output:

Probability that none of 3 ants collide: 0.75

If you set N = 4 then output:

Probability that none of 4 ants collide: 0.875

If you set N = 10 then output:

Probability that none of 10 ants collide: 0.998046875

4 N STAIRS

- In case if you can take 2 steps then total ways to reach the 3’rd stair are 3

1 step  + 1 step  + 1 step

1 step  + 2 steps

2 steps + 1 step

- In case if you can take 3 steps then total ways to reach the 4’th stair are 7

1 step  + 1 step  + 1 step  + 1 steps

1 step  + 1 step  + 2 steps

1 step  + 2 steps + 1 step

1 step  + 3 steps

2 steps + 1 step  + 1 step

2 steps + 2 steps

3 steps + 1 step

- In case if you can take 4 steps then total ways to reach the 4’th stair are 8

1 step  + 1 step  + 1 step  + 1 steps

1 step  + 1 step  + 2 steps

1 step  + 2 steps + 1 step

1 step  + 3 steps

2 steps + 1 step  + 1 step

2 steps + 2 steps

3 steps + 1 step

4 steps

countWays(N, K) = countWays(N-1, K) + countWays(N-2, K) + ... countWays (N-K, K)

#  Stairs program

# count distinct ways

def distCountWays(n, k):

if n <= 1:

return n

res = 0

i = 1

while i<= k and i<= n:

res = res + distCountWays(n-i, k)

i = i + 1

return res

# Returns number of ways to reach N'th stair

def countWays(n, k):

return distCountWays(n + 1, k)

# N Number of Stairs

N = 4

# K STEPS AT A TIME

K = 3

if K > N : print('solution is not possible')

else: print ("Number of distinct ways =", countWays(N, K))

If N=4 & K=3 then output:

Number of distinct ways = 7

If N=4 & K=4 then output:

Number of distinct ways = 8

If N=8 & K=4 then output:

Number of distinct ways = 108

If N=3 & K=2 then output:

Number of distinct ways = 108

Number of distinct ways = 3

5 DEATH RAT

:

Where X = Number of wine bottles

Z = Hours for poison to effect

Y = Hours to find a poisoned bottle

import math

#X wine bottles

X=1000

#Z hour time after which the poison works

Z=24

#Y hour time to find the poisoned bottle

Y=48

T = Y/Z

print ("Number of rats required to find the poisoned bottle: ", end="")

print (math.ceil(math.log(X,T+1)))

Output:

Number of rats required to find the poisoned bottle: 7

Now if X=1000

Z=1

Y=1

Then output:

Number of rats required to find the poisoned bottle: 10

Now if X=240

Z=24

Y=48

Then output:

Number of rats required to find the poisoned bottle: 5

6 BULLET CURVE

If N is the number of people in circle and if K is the nearest power of 2 which is less than N, then

Last Person = 2 * (N - K) + 1

#Import math Library

import math

#N People

N = 100

#Largest Power of 2 <= Total Number

M = math.log(N,2);

#If Largest Power of 2 = Total Number

if(M.is_integer()):

print('1');

#Else Largest Power of 2 < Total Number

else:

P = math.floor(M);

K = pow(2,P)

Sol = 2 * (N - K) + 1

print('Surviving Person:', Sol)

If N = 100 then output:

Surviving Person: 73

If N = 5 then output:

Surviving Person: 3

7 BIRTHDAY MATCH

Where N = Number of Students in a Class

# N Number of Students in Class

N = 35

mul1 = 1

for x in range(365-N+1,366):

mul1 = mul1 * x

base = 365

exponent = N

mul2 = pow(base, exponent)

print('Probability of any two share same birthday:',1-(mul1/mul2))

If N=35 then output:

Probability of any two share same birthday: 0.8143832388747152

If N=23 then output:

Probability of any two share same birthday: 0.5072972343239854

If N=40 then output:

Probability of any two share same birthday: 0.891231809817949

8 FAIR COIN

John von Neumann described the procedure like this:

1. Toss the coin twice.

2. If the outcome of both coins is the same (HH or TT), start over and disregard the current toss.

3. If the outcome of both coins is different (HT or TH), take the first coin as the result and forget the second.

from random import randint

# Biased function that returns Heads with 60% probability and

# Tails with 40% probability

def toss_biased():

# generate random number between 1-100, both inclusive

r = randint(1, 100)

# return T if we got number between [1-40], else return T

return T if (r < 41) else H

def toss_unbiased():

# difference = 0 in case of HH or TT toss again

# difference > 0 in case of HT return  H

# difference < 0 in case of TH return T

difference = toss_biased() - toss_biased()

if difference > 0:

return H

if difference < 0:

return T

return toss_unbiased()

# Generate Fair Results from a Biased Coin

if __name__ == '__main__':

# Head

H = 1

# Tail

T = 0

head_count = tail_count = 0

for i in range(10000):

val = toss_unbiased()

if val == 1:

head_count += 1

else:

tail_count += 1

print("HEADS% ~", head_count / 100, "%")     # ~50%

print("TAILS% ~", tail_count / 100, "%")     # ~50%

Output :

HEADS% ~ 50.21 %

TAILS% ~ 49.79 %

Again run then output:

HEADS% ~ 49.95 %

TAILS% ~ 50.05 %

9 N COINS FLIP

1.) If there are M heads-up coins in N coins then pick randomly M coins from given coins and create two piles. (M coins, (N-M) coins)

2.) Flip all coins from a pile of M coins. You’re done.

from random import randint

import array as arr

# Random function that returns N Coins with M Heads

def random_coins():

# generate random number either 1 or 0

r = randint(0, 1)

# return Head if we got number 1, else return T

return H if (r == 1) else T

# Generate Two Piles with Same Number of Heads-up Coins

if __name__ == '__main__':

# Head

H = 1

# Tail

T = 0

head_count = tail_count = 0

#Number of coins, let's take 100

N = 100

coins = []

for i in range(N):

val = random_coins()

if val == 1:

head_count += 1

coins.append(1)

else:

tail_count += 1

coins.append(0)

print('Randomly Generated Coins')

print(coins)

print('In single pile of', N, 'coins:', head_count, 'are Heads and ', tail_count, ' are Tails')

print('***Solution for splitting the coins into two piles***')

pile1_coins = coins[0:head_count]

print('Size of 1st piles coins:', len(pile1_coins))

print('1st piles coins:', pile1_coins)

pile2_coins = coins[len(pile1_coins):N]

print('Size of 2nd piles coins:', len(pile2_coins))

print('2nd piles coins:', pile2_coins)

pile1_coins_head = pile2_coins_head = 0

print('flip all coins of 1st pile')

for g in range(len(pile1_coins)):

if pile1_coins[g] == 1:

pile1_coins[g] = 0

else:

pile1_coins[g] = 1

print('1st piles coins after a flip:', pile1_coins)

for j in range(len(pile1_coins)):

if pile1_coins[j] == 1:

pile1_coins_head += 1

for k in range(len(pile2_coins)):

if pile2_coins[k] == 1:

pile2_coins_head += 1

print('Number of coins with head in 1st pile:',  pile1_coins_head)

print('Number of coins with head in 2nd pile:',  pile2_coins_head)

Output:

Randomly Generated Coins

[0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1]

In single pile of 100 coins: 47 are Heads and  53  are Tails

***Solution for splitting the coins into two piles***

Size of 1st piles coins: 47

1st piles coins: [0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1]

Size of 2nd piles coins: 53

2nd piles coins: [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1]

flip all coins of 1st pile

1st piles coins after a flip: [1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0]

Number of coins with head in 1st pile: 29

Number of coins with head in 2nd pile: 29

Run again and output:

Randomly Generated Coins

[0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1]

In single pile of 100 coins: 50 are Heads and  50  are Tails

***Solution for splitting the coins into two piles***

Size of 1st piles coins: 50

1st piles coins: [0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1]

Size of 2nd piles coins: 50

2nd piles coins: [0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1]

flip all coins of 1st pile

1st piles coins after a flip: [1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0]

Number of coins with head in 1st pile: 30

Number of coins with head in 2nd pile: 30

10 N BAGS

There is only 1 bag with forgeries, so take 1 coin from the first bag, 2 coins from the second bag . . . N coins from the Nth bag and simply weigh the picked coins together.

If there were no forgeries, you know that the total weight should be (1+2+...+n) = n*(n+1)/2 grams.

The number difference between them will give the bag number of fake coins.

# Finding Bag No filled with fake coins

from random import randint

# N Number of bags

N = 200

print('Total number of bags:', N)

# r Any random number between 1 & N

r = randint(1, N)

print('random bag number where to put fake coins:', r)

coinArr = []

sumCoin = 0.0

#Putting 1 g coins in each bag except r in which putting 1.1g fake coins

for x in range(1,N+1):

if x == r :

coinArr.append(1.1)

else:

coinArr.append(1)

print('Coin Bags:', coinArr)

#Finding fake coin bags

#Taking k numbers of coin from k bags & weighing them

for k in range(len(coinArr)):

sumCoin += (coinArr[k]) * (k+1)

print('Weight with fake coins:', sumCoin)

#Wanted weight if no coins are fake

actualSumCoin = N * (N+1) / 2;

#Difference between sumCoin and actualSumCoin

diff = sumCoin - actualSumCoin

#round function for correcting floating point difference in Python

fakeBagNo = round(diff,4)*10

print('Bag No. with fake coins:', round(fakeBagNo))

Output:

Total number of bags: 200

random bag number where to put fake coins: 195

Coin Bags: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.1, 1, 1, 1, 1, 1]

Weight with fake coins: 20119.5

Bag No. with fake coins: 195

Run again and output:

Total number of bags: 200

random bag number where to put fake coins: 12

Coin Bags: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Weight with fake coins: 20101.2

Bag No. with fake coins: 12

>

11 RAIN IN THE CITY

You only require one of the friends to be telling the truth.

The probability that at least one of them is telling the truth will be:

1 - (Probability that all of them Lied)

The probability that one of them lied is 1/N

So, the probability that all N lied is  1/N * 1/N * 1/N … * 1/N (N times multiplication of 1/N) = 1/(N^N)

So, now the probability that at least one of them told the truth is or there is a raining is: 1 – (1/(N^N))

# Probability of Raining

import math

# N Number of friends

N = 3

# P Probability =1 - (Probability that all of them Lied)

P = 1 - (1/pow(N,N))

print('Possibility of Raining', P*100,'%')

If N=3 output:

Possibility of Raining 96.2962962962963 %

If N=2 then output:

Possibility of Raining 75.0 %

If N=5 then output:

Possibility of Raining 99.968 %

12 N PRISONERS & N BOXES

There is a strategy that provides a better survival probability than randomly opening the boxes.

To describe the strategy, not only the prisoners, but also the boxes are also numbered from 1 to N. The strategy is now as follows:

1.) Each prisoner first opens the box with his own number.

2.) If that box contains his number then he is successful.

3.) Otherwise, the box contains the number of another prisoner and he next opens the box with this number.

4.) The prisoner repeats steps 2 and 3 until he finds his own number or has opened N/2 drawers.

from random import randint

# Flling N Boxes randomly

def fillBoxes(N, NBox):

r = randint(1, N)

if r in NBox:

fillBoxes(N, NBox)

else:

NBox.append(r)

if(len(NBox) <N):

fillBoxes(N, NBox)

return NBox

# Finding Own Number

def findingNumber(chosenOne, NBox, checkBoxNo, count, N):

if count >= N/2:

if(NBox[checkBoxNo-1] == chosenOne):

print('Number is found')

else:

print('Number is not found')

return

elif(NBox[checkBoxNo-1] == chosenOne):

print('Number is found')

return 1

else:

print('At Step:', count+1,': ','checked box number:', NBox[checkBoxNo-1])

findingNumber(chosenOne, NBox, NBox[checkBoxNo-1], count+1, N)

# N Number of Prisoners

N = 120

print('Total number of Prisoners', N)

# Fill N boxes randomly with numbers 1 to N

NBox = []

NBox = fillBoxes(N, NBox)

print('Arrangement of Boxes', NBox)

chosenOne = randint(1, N)

print('Prison No.', chosenOne,'is sent')

print('At step: 1: checked box number:', chosenOne)

findingNumber(chosenOne, NBox, chosenOne, 1, N)

N=120 then Output:

Total number of Prisoners 120

Arrangement of Boxes [75, 33, 85, 83, 64, 108, 81, 100, 58, 15, 38, 92, 5, 36, 2, 13, 115, 49, 16, 63, 93, 99, 109, 67, 35, 29, 110, 30, 120, 86, 112, 9, 48, 21, 70, 111, 105, 89, 54, 8, 11, 84, 25, 101, 34, 44, 69, 72, 117, 4, 87, 102, 19, 103, 45, 39, 106, 119, 107, 95, 17, 91, 26, 51, 65, 73, 60, 1, 6, 82, 52, 94, 98, 97, 114, 12, 118, 10, 88, 79, 14, 24, 77, 61, 59, 96, 28, 57, 41, 7, 18, 78, 55, 74, 116, 90, 42, 3, 22, 40, 50, 31, 20, 113, 66, 76, 27, 62, 56, 80, 37, 68, 104, 53, 23, 47, 43, 71, 32, 46]

Prison No. 40 is sent

At step: 1: checked box number: 40

At Step: 2 :  checked box number: 8

At Step: 3 :  checked box number: 100

Number is found

N=100 then Output:

Total number of Prisoners 100

Arrangement of Boxes [63, 21, 19, 4, 94, 8, 3, 36, 11, 27, 80, 69, 2, 65, 24, 67, 92, 10, 82, 40, 39, 7, 87, 1, 14, 26, 78, 59, 43, 77, 51, 93, 31, 76, 32, 17, 41, 89, 29, 99, 73, 54, 52, 22, 6, 38, 98, 84, 66, 5, 70, 13, 46, 50, 68, 83, 15, 30, 74, 33, 18, 55, 62, 96, 56, 79, 16, 64, 75, 34, 42, 88, 85, 53, 48, 44, 95, 23, 20, 71, 12, 35, 28, 58, 9, 97, 57, 100, 47, 91, 49, 86, 90, 72, 25, 60, 81, 45, 61, 37]

Prison No. 3 is sent

At step: 1: checked box number: 3

At Step: 2 :  checked box number: 19

At Step: 3 :  checked box number: 82

At Step: 4 :  checked box number: 35

At Step: 5 :  checked box number: 32

At Step: 6 :  checked box number: 93

At Step: 7 :  checked box number: 90

At Step: 8 :  checked box number: 91

At Step: 9 :  checked box number: 49

At Step: 10 :  checked box number: 66

At Step: 11 :  checked box number: 79

At Step: 12 :  checked box number: 20

At Step: 13 :  checked box number: 40

At Step: 14 :  checked box number: 99

At Step: 15 :  checked box number: 61

At Step: 16 :  checked box number: 18

At Step: 17 :  checked box number: 10

At Step: 18 :  checked box number: 27

At Step: 19 :  checked box number: 78

At Step: 20 :  checked box number: 23

At Step: 21 :  checked box number: 87

At Step: 22 :  checked box number: 57

At Step: 23 :  checked box number: 15

At Step: 24 :  checked box number: 24

At Step: 25 :  checked box number: 1

At Step: 26 :  checked box number: 63

At Step: 27 :  checked box number: 62

At Step: 28 :  checked box number: 55

At Step: 29 :  checked box number: 68

At Step: 30 :  checked box number: 64

At Step: 31 :  checked box number: 96

At Step: 32 :  checked box number: 60

At Step: 33 :  checked box number: 33

At Step: 34 :  checked box number: 31

At Step: 35 :  checked box number: 51

At Step: 36 :  checked box number: 70

At Step: 37 :  checked box number: 34

At Step: 38 :  checked box number: 76

At Step: 39 :  checked box number: 44

At Step: 40 :  checked box number: 22

At Step: 41 :  checked box number: 7

Number is found

>

Again N=100 then Output:

Total number of Prisoners 100

Arrangement of Boxes [78, 30, 52, 67, 56, 49, 15, 82, 4, 34, 16, 77, 25, 43, 8, 38, 88, 97, 76, 87, 93, 41, 42, 94, 62, 79, 18, 36, 47, 84, 100, 73, 27, 90, 7, 5, 11, 32, 3, 46, 69, 63, 6, 99, 72, 22, 74, 35, 50, 85, 20, 55, 10, 29, 14, 60, 53, 89, 96, 54, 21, 26, 1, 33, 37, 64, 66, 92, 39, 40, 28, 91, 45, 9, 81, 70, 58, 65, 13, 83, 86, 71, 17, 23, 19, 2, 75, 51, 48, 12, 61, 68, 59, 57, 95, 44, 31, 98, 24, 80]

Prison No. 16 is sent

At step: 1: checked box number: 16

At Step: 2 :  checked box number: 38

At Step: 3 :  checked box number: 32

At Step: 4 :  checked box number: 73

At Step: 5 :  checked box number: 45

At Step: 6 :  checked box number: 72

At Step: 7 :  checked box number: 91

At Step: 8 :  checked box number: 61

At Step: 9 :  checked box number: 21

At Step: 10 :  checked box number: 93

At Step: 11 :  checked box number: 59

At Step: 12 :  checked box number: 96

At Step: 13 :  checked box number: 44

At Step: 14 :  checked box number: 99

At Step: 15 :  checked box number: 24

At Step: 16 :  checked box number: 94

At Step: 17 :  checked box number: 57

At Step: 18 :  checked box number: 53

At Step: 19 :  checked box number: 10

At Step: 20 :  checked box number: 34

At Step: 21 :  checked box number: 90

At Step: 22 :  checked box number: 12

At Step: 23 :  checked box number: 77

At Step: 24 :  checked box number: 58

At Step: 25 :  checked box number: 89

At Step: 26 :  checked box number: 48

At Step: 27 :  checked box number: 35

At Step: 28 :  checked box number: 7

At Step: 29 :  checked box number: 15

At Step: 30 :  checked box number: 8

At Step: 31 :  checked box number: 82

At Step: 32 :  checked box number: 71

At Step: 33 :  checked box number: 28

At Step: 34 :  checked box number: 36

At Step: 35 :  checked box number: 5

At Step: 36 :  checked box number: 56

At Step: 37 :  checked box number: 60

At Step: 38 :  checked box number: 54

At Step: 39 :  checked box number: 29

At Step: 40 :  checked box number: 47

At Step: 41 :  checked box number: 74

At Step: 42 :  checked box number: 9

At Step: 43 :  checked box number: 4

At Step: 44 :  checked box number: 67

At Step: 45 :  checked box number: 66

At Step: 46 :  checked box number: 64

At Step: 47 :  checked box number: 33

At Step: 48 :  checked box number: 27

At Step: 49 :  checked box number: 18

At Step: 50 :  checked box number: 97

Number is not found

>

13 N TOWERS OF HANOI

Steps of the Frame–Stewart Algorithm:

* Let n be the number of disks.

* Let r be the number of pegs.

* Define T(n,r) to be the minimum number of moves required to transfer n disks using r pegs.

The algorithm can be described recursively:

1. For some k, 1<= k < n, transfer the top k disks to a single peg other than the start or destination pegs, taking T(k,r) moves.

2. Without disturbing the peg that now contains the top k disks, transfer the remaining n-k disks to the destination peg, using only the remaining r-1 pegs, taking T(n-k,r-1) moves.

3. Finally, transfer the top k disks to the destination peg, taking T(k,r) moves.

The entire process takes 2T(k,r)+T(n-k,r-1) moves. The count k should be picked for which this quantity is least.

#Frame-Stewart Algorithm For Multi-pegs Tower of Hanoi

def nHanoi(mdisks,npegs):

if mdisks ==0: #zero disks require zero moves

return 0

if  mdisks == 1 and npegs > 1: #if there is only 1 disk it will only take one move

return 1

if npegs == 3:#3 pegs is well defined optimal solution of 2^n-1

return 2**mdisks - 1

if npegs >= 3 and mdisks > 0:

potential_solutions = (2*nHanoi(kdisks,npegs) + nHanoi(mdisks-kdisks,npegs-1) for kdisks in range(1,mdisks))

return min(potential_solutions) #the best solution

#all other cases where there is no solution (namely one peg, or 2 pegs and more than 1 disk)

return float("inf")

# N PEGS

N = 3

# M DISCS

M = 3

print ('Number of moves:',nHanoi(M, N))

If N =3, M=3 then output:

Number of moves: 7

If N=3, M=1 then output:

Number of moves: 1

If N=3, M=5 then output:

Number of moves: 31

If N=4 M=6 then output:

Number of moves: 17

If N=7 M=15 then output:

Number of moves: 47

If N=4 M=15 then output:

Number of moves: 129

14 CLOCK ANGLE

Let's take 12:00 (h = 12, m = 0) as a reference and do below steps.

1. Calculate the angle made by hour hand with respect to 12:00 in h hours and m minutes.

2. Calculate the angle made by minute hand with respect to 12:00 in h hours and m minutes.

3. The difference between the two angles is the angle between the two hands.

The hour hand moves 360 degrees in 12 hours (or 0.5 degrees in 1 minute) and minute hand moves 360 degrees in 60 minute (or 6 degrees in one minute).

In h hours and m minutes, the hour hand would move (60 (h % 12) + m )*0.5 and minute hand would move 6*m.

So required angle = (60 (h % 12) + m )*0.5 - 6*m

= 30 * (h % 12) + 0.5*m - 6*m

= 30 * (h % 12) + 5.5*m

def clock_angle(time):

hour, minutes = map(int, time.split(':'))

angle = abs(30 * (hour % 12) - 5.5 * minutes)

return min(angle, 360 - angle)

# T TIME

T='3:30'

print('Angle :', clock_angle(T), 'degree')

If T=’12:00’ then output:

Angle : 0.0 degree

If T=’3:30’ then output:

Angle : 75.0 degree

15 BALLS ON A PLANE

Generally, people will think the number of balls = (volume of plane) / (volume of a ball), but they forget about density index.

If there is a cube and we have to fit a sphere into it then,

Left-out volume = volume of cube – volume of sphere

= (2a) 3 – ((4/3) * pi * a 3 )

= a 3 * ( 8 – ( (4/3) * pi))

~ 3.81 a 3

Filled-out volume = volume of cube – Left-out volume

= 8a 3  – 3.81 a 3

~ 4.19a 3

Density index = Filled-out volume / Volume of Cube

= 4.19a 3 /  8a 3

~ 0.53

But while arranging the balls optimally the density index increase, see the next image.

As you can see, the left-out volume is decreased.

A random packing of equal spheres generally has a density around 64%. So let's set our density index as 0.64

So our final equation is:

Number of Balls = Density Index * Volume of Plane

Volume of Ball

Let’s take an example of a tennis ball with radius of 6.54 cm and a Boeing 747 plane with length of 71m and interior radius of 6m.

# Balls packing

import math

#r Radius of a ball in cm

r = 6.54

#R Interior radius of a plane in cm

R = 600

#L length of a plane in cm

L = 7100

#Volume of a ball

vBall = 4 * math.pi * (pow(r,3)) /3;

#Volume of a plane

vPlane = math.pi * L * (pow(R,2));

#p Packing Density

p = 0.64

#N Number of Balls

N = math.ceil(p*vPlane/vBall)

print('Possible number of balls to fit into a plane', N)

Output:

Possible number of balls to fit into a plane 4386003

ABOUT AUTHOR

“I'm a computer engineer and a software consultant. I'm extremely fond of anything that is related to mathematics, computer science and creative ideas. You can contact me at viragbook@gmail.com ”

-           VIRAG R. SHAH

Table of Contents

Brain Teasers with Coding for Data Scientist

DISCLAIMER

ACKNOWLEDGMENTS

CONTENTS

INTRODUCTION

1 HELLO WORLD

2 BASIC CODING

3 N ANTS

4 N STAIRS

5 DEATH RAT

6 BULLET CURVE

7 BIRTHDAY MATCH

8 FAIR COIN

9 N COINS FLIP

10 N BAGS

11 RAIN IN THE CITY

12 N PRISONERS & N BOXES

13 N TOWERS OF HANOI

14 CLOCK ANGLE

15 BALLS ON A PLANE

Solutions

1 HELLO WORLD

2 BASIC CODING

3 N ANTS

4 N STAIRS

5 DEATH RAT

6 BULLET CURVE

7 BIRTHDAY MATCH

8 FAIR COIN

9 N COINS FLIP

10 N BAGS

11 RAIN IN THE CITY

12 N PRISONERS & N BOXES

13 N TOWERS OF HANOI

14 CLOCK ANGLE

15 BALLS ON A PLANE

ABOUT AUTHOR