interview problems

This commit is contained in:
Mari Wahl 2014-10-27 20:30:47 -04:00
parent 0f559fa0d7
commit fda02ef3c8
31 changed files with 935 additions and 0 deletions

View File

@ -0,0 +1,35 @@
#!/usr/bin/python
''' Clear a bit in a binary number.
Like the reverse of set bit:
1) first create a number filled of 1s,
with 0 at i (can create 0001000 and ~)
2) AND the number so it clears the ith bit
'''
def clear_bit(num, i):
mask = ~ (1 << i) # -0b10001
return bin(num & mask)
def clear_all_bits_from_i_to_0(num, i):
mask = ~ ( (1 << (i+1)) - 1)
return bin(num & mask)
def clear_all_bits_from_most_sig_to_1(num, i):
mask = ( 1 << i) -1
return bin(num & mask)
if __name__ == '__main__':
num = int('10010000', 2)
print clear_bit(num, 4) # '0b10000000'
num = int('10010011', 2)
print clear_all_bits_from_i_to_0(num, 2) # '0b10010000'
num = int('1110011', 2)
print clear_all_bits_from_most_sig_to_1(num, 2) #'0b11'

View File

@ -0,0 +1,23 @@
#!/usr/bin/python
''' Find how many bits a int has:
1) Start with a mask of 1
2) Mask with AND
3) if result (if true): count += 1
(obs: to find the int of a bin do int('1001', 2)) and to show in bin do bin(int))
'''
def find_bit_len(int_num):
lenght = 0
while int_num:
int_num >>= 1
lenght += 1
return lenght
if __name__ == '__main__':
for i in range(17):
print(find_bit_len(i))
print i.bit_length()
print

View File

@ -0,0 +1,25 @@
#!/usr/bin/python
''' Get a bit in a binary number:
1) Shifts 1 over by i bits
2) make an AND with the number
3) all the other than the bit at i are clean, now compare to 0
4) if the new value is not 0, bit i is 1
'''
def get_bit(num, i):
mask = 1 << i
return num & mask != 0
if __name__ == '__main__':
num = int('0100100', 2)
get_bit(num, 0) # 0
get_bit(num, 1) # 0
get_bit(num, 2) # 1
get_bit(num, 3) # 0
get_bit(num, 4) # 0
get_bit(num, 5) # 1
get_bit(num, 6) # 0

View File

@ -0,0 +1,37 @@
#!/usr/bin/python
''' This method returns the number of bits that are necessary to change to convert two
numbers A and B:
1) XOR
2) count 1s
'''
def count_bits_swap2(a, b):
count = 0
m = a^b
while m:
count +=1
m = m & (m-1)
return count
def count_bits_swap(a, b):
m = a^b
return count_1s(m)
def count_1s(m):
count = 0
while m:
if m& 1 :
count +=1
m >>= 1
return count
if __name__ == '__main__':
a = int('10010000', 2)
b = int('01011010', 2)
print count_bits_swap(a, b) #4
print count_bits_swap2(a, b) #4

View File

@ -0,0 +1,25 @@
#!/usr/bin/python
''' Set a bit in a binary number:
1) Shifts 1 over by i bits
2) make an OR with the number, only the value at bit i will change and all the others bit
of the mask are zero so will not affect the num
'''
def set_bit(num, i):
mask = 1 << i
return bin( num | mask )
if __name__ == '__main__':
num = int('0100100', 2)
print set_bit(num, 0) #'0b100101'
print set_bit(num, 1) #'0b100110'
print set_bit(num, 2) # nothing change '0b100100'
print set_bit(num, 3) #'0b101100'
print set_bit(num, 4) #'0b110100'
print set_bit(num, 5) # nothing change '0b100100'

View File

@ -0,0 +1,20 @@
#!/usr/bin/python
''' This method merges set bit and clean bit:
1) first clear the bit at i using a mask such as 1110111
2) then shift the intended value v by i bits
3) this will create a number with bit i to v and all other to 0
4) finally update the ith bit with or
'''
def update_bit(num, i, v):
mask = ~ (1 << i)
return bin( (num & mask) | (v << i) )
if __name__ == '__main__':
num = int('10010000', 2)
print update_bit(num, 2, 1) # '0b10010100'

View File

@ -0,0 +1,5 @@
Given an english word in the form of a string, how can you quickly find all valid anagrams for that string?
First you go through each word in the dictionary, sort the letters of the word and use this as a key in a Hash Table. O(nln n).
The O(1) lookup is sorting the query word and searching for the key.

View File

@ -0,0 +1,6 @@
This is the classic "you have 8 balls/coins, which are the same weight, except for one which is slightly heavier than the others. You also have an old-style balance. What is the fewest number of weighings to find the heavy coin/ball?
Answer: 2! You need to use every information available:
Weight 3 x 3 balls/coins.
If they weight the same: weight the 2 balls/coins left outside.
Else, measure 2 of the 3 heavier balls/coins.

View File

@ -0,0 +1,54 @@
#!/bin/python
"""
Given an integer x and an unsorted array of integers, describe an algorithm to
determine whether two of the numbers add up to x.
1. Using hash tables.
2. Sorting the array and keeping two pointers in the array, one in the beginning and
one in the end. Whenever the sum of the current two integers is less than x, move the
first pointer forwards, and whenever the sum is greater than x, move the second pointer
backwards. O(nln n).
3. Create a BST with x minus each element in the array. Check whether any element of
the array appears in the BST. It takes O(nlog n) times two.
"""
def check_if_sum(arr, num):
seq = sorted(arr)
p1, p2 = 0, len(arr) - 1
while p1 < p2 and p2 < len(arr) and p1 >= 0:
sum_here = seq[p1] + seq[p2]
if sum_here == num:
return True, seq[p1], seq[p2]
elif sum_here < num:
p1 += 1
elif sum_here > num:
p2 -= 1
return False
from collections import Counter
def check_if_sum2(arr, num):
d = Counter()
for i in arr:
d[i] += 1
for i in arr:
other = num - i
d[i] -= 1
if d[other] == 1:
return True, other, i
return False
arr = [3, 1, 13, 7, 2, 10]
num1 = 11
num2 = 6
print(check_if_sum(arr, num1))
print(check_if_sum(arr, num2))
print
print(check_if_sum2(arr, num1))
print(check_if_sum2(arr, num2))

View File

@ -0,0 +1,53 @@
#!/usr/bin/python
""" find whether two words are anagrams. Since sets do not count occurency, and sorting is O(nlogn)
we will use hash tables. We scan the first string and add all the character occurences. Then we
scan the second tring and decrease all the caracther occurences. If all the counts are zero, it is
an anagram"""
import string
def verify_two_strings_are_anagrams(str1, str2):
ana_table = {key:0 for key in string.ascii_lowercase}
for i in str1:
ana_table[i] += 1
for i in str2:
ana_table[i] -= 1
if len(set(ana_table.values())) < 2: return True
else: return False
''' verify if words are anagrams by comparying hash functions'''
def hash_func(astring, tablesize):
sump = 0
for p in astring:
sump += ord(p)
return sump%tablesize
def find_anagram_hash_function(word1, word2):
tablesize = 11
return hash_func(word1, tablesize) == hash_func(word2, tablesize)
if __name__ == '__main__':
str1 = 'marina'
str2 = 'aniram'
str3 = 'anfaam'
print verify_two_strings_are_anagrams(str1, str2)
print verify_two_strings_are_anagrams(str1, str3)
print
print find_anagram_hash_function(str1, str2)
print find_anagram_hash_function(str1, str3)

View File

@ -0,0 +1,38 @@
#!/bin/python
''' Check if palindrome'''
def check_pal(string):
string = "".join(string.split(' '))
p1, p2 = 0, len(string)-1
pal = True
while p1 < p2:
if string[p1] != string[p2]:
pal = False
break
p1+=1
p2-=1
return pal
def check_pal2(string):
string = "".join(string.split(' '))
if len(string)<2:
return True
if string[0] != string[-1]:
return False
return check_pal2(string[1:-1])
if __name__ == '__main__':
string1 = "borrow or rob"
string2 = " draw ward"
string3 = "google is fun"
print(check_pal(string1))
print(check_pal(string2))
print(check_pal(string3))
print
print(check_pal2(string1))
print(check_pal2(string2))
print(check_pal2(string3))

View File

@ -0,0 +1,23 @@
#!/usr/bin/python
''' find and delete all the duplicate characters in a string '''
import string
def delete_unique_word(str1):
table_c = { key : 0 for key in string.ascii_lowercase}
for i in str1:
table_c[i] += 1
for key, value in table_c.items():
if value > 1:
str1 = str1.replace(key, "")
return str1
if __name__ == '__main__':
str1 = "google"
print delete_unique_word(str1) # == 'le'

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' understanding generators'''
def fib_generator():
a, b = 0, 1
while True:
yield b
a, b = b, a+b
if __name__ == '__main__':
fib = fib_generator()
print(next(fib))
print(next(fib))
print(next(fib))
print(next(fib))

View File

@ -0,0 +1,81 @@
#!/usr/bin/python
def find_permutations(s):
if len(s) < 2: return s
res = []
for i, c in enumerate(s):
for perm in find_permutations(s[:i] + s[i+1:]):
res.append(c + "".join(perm))
return res
def fpc(s):
return [s] if len(s)<2 else [c+p for i,c in enumerate(s) for p in fpc(s[:i]+s[i+1:])]
def find_permutations_stdlib(s):
from itertools import permutations
return [''.join(p) for p in permutations(s)]
def find_permutations2(s):
if len(s) < 2: return s
res = []
for i in range(len(s)):
for perm in find_permutations2(s[:i] + s[i+1:]):
res.append(s[i] + perm)
return res
def verify_if_perm(s1, s2):
if len(s1) != len(s2): return False
s1 = sorted(s1)
s2 = sorted(s2)
return s1 == s2
from collections import Counter
def verify_if_perm2(s1, s2): # like anagram
if len(s1) != len(s2): return False
dict_aux = Counter()
for c in s1:
dict_aux[c] += 1
for c in s2:
dict_aux[c] -= 1
for item in dict_aux:
if dict_aux[item]:
return False
return True
if __name__ == '__main__':
s1 = 'ufyfbufyfb'
s2 = 'buffybuffy'
s3 = 'uuyfbuuyfb'
s4 = ''
print(verify_if_perm(s1, s2))
print(verify_if_perm(s1, s3))
print(verify_if_perm(s1, s4))
print
print(verify_if_perm2(s1, s2))
print(verify_if_perm2(s1, s3))
print(verify_if_perm2(s1, s4))
print
s = 'hat'
print find_permutations(s)
print fpc(s)
print find_permutations_stdlib(s)
print find_permutations2(s)
print
print find_permutations(s4)
print fpc(s4)
print find_permutations_stdlib(s4)
print find_permutations2(s4)

View File

@ -0,0 +1,20 @@
#!/usr/bin/python
#
''' give all the combinations of a str or list '''
def comb_str(l1):
if len(l1) < 2:
return l1
result = []
for i, c in enumerate(l1):
result.append(c)
for comb in comb_str(l1[i+1:]):
result.append(c + "".join(comb))
return result
if __name__ == '__main__':
l1 = ['a', 'b', 'c']
print comb_str(l1)

View File

@ -0,0 +1,31 @@
#!/usr/bin/python
def isSubstr(s1, s2):
if s1 in s2 or s2 in s1: return True
return False
def find_substr(s1, s2):
pl, ps = 0, 0
if len(s1) > len(s2):
larger, smaller = s1, s2
else:
larger, smaller = s2, s1
while ps < len(smaller) and pl < len(larger):
if larger[pl] == smaller[ps]:
ps += 1
else:
ps = 0
pl += 1
if ps == len(smaller):
return True
return False
if __name__ == '__main__':
s1 = 'buffy is a vampire slayer'
s2 = 'vampire'
s3 = 'angel'
print find_substr(s2, s1)
print find_substr(s3, s1)

View File

@ -0,0 +1,45 @@
#!/usr/bin/python
from collections import defaultdict
def find_unique_number(arr):
table = defaultdict(int)
total = 0
for i in arr:
if table[i]:
total -= i
else:
total += i
table[i] +=1
return total
def find_unique_number_xor(arr):
xor = 0
for item in arr:
xor ^= item
return xor
def find_unique_char(s):
if len(s) < 2: return True
for i, c in enumerate(s):
for j in s[i+1:]:
if j == c:
return False
return True
if __name__ == '__main__':
arr = [1, 3, 5, 6, 1, 5, 6, 3, 7,]
print(find_unique_number(arr))
print(find_unique_number_xor(arr))
s1 = 'abcdefg'
s2 = 'buffy'
s3 = ''
print
print(find_unique_char(s1))
print(find_unique_char(s2))
print(find_unique_char(s3))

View File

@ -0,0 +1,26 @@
#!/usr/bin/python
def finding_gcd(a, b):
''' implements the greatest common divider algorithm '''
while(b != 0):
result = b
a, b = b, a % b
return result
def test_finding_gcd():
number1 = 21
number2 = 12
assert(finding_gcd(number1, number2) == 3)
print('Tests passed!')
if __name__ == '__main__':
test_finding_gcd()

View File

@ -0,0 +1,59 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import math
import random
def finding_prime(number):
''' find whether a number is prime in a simple way'''
num = abs(number)
if num < 4 : return True
for x in range(2, num):
if num % x == 0:
return False
return True
def finding_prime_sqrt(number):
''' find whether a number is prime as soon as it rejects all candidates up to sqrt(n) '''
num = abs(number)
if num < 4 : return True
for x in range(2, int(math.sqrt(num)) + 1):
if number % x == 0:
return False
return True
def finding_prime_fermat(number):
''' find whether a number is prime with Fermat's theorem, using probabilistic tests '''
if number <= 102:
for a in range(2, number):
if pow(a, number- 1, number) != 1:
return False
return True
else:
for i in range(100):
a = random.randint(2, number - 1)
if pow(a, number - 1, number) != 1:
return False
return True
def test_finding_prime():
number1 = 17
number2 = 20
assert(finding_prime(number1) == True)
assert(finding_prime(number2) == False)
assert(finding_prime_sqrt(number1) == True)
assert(finding_prime_sqrt(number2) == False)
assert(finding_prime_fermat(number1) == True)
assert(finding_prime_fermat(number2) == False)
print('Tests passed!')
if __name__ == '__main__':
test_finding_prime()

View File

@ -0,0 +1,35 @@
#!/usr/bin/python3
# mari von steinkirch @2013
# steinkirch at gmail
import math
import random
import sys
from finding_prime import finding_prime_sqrt
def generate_prime(number=3):
''' return a n-bit prime '''
while 1:
p = random.randint(pow(2, number-2), pow(2, number-1)-1)
p = 2 * p + 1
if finding_prime_sqrt(p):
return p
if __name__ == '__main__':
if len(sys.argv) < 2:
print ("Usage: generate_prime.py number")
sys.exit()
else:
number = int(sys.argv[1])
print(generate_prime(number))

View File

@ -0,0 +1,26 @@
#!/usr/bin/python
''' Given a real number between 0 and 1 (eg: 0.72), this method print the binary
representation. If the Number cannot be represented accurately in binary, with at
most 32 chars, print error:
'''
def get_float_rep(num):
if num >= 1 or num <= 0: return 'Error 1'
result = '.'
while num:
if len(result) >= 32: return 'Error 2', result
r = num*2
if r >= 1:
result += '1'
num = r - 1
else:
result += '0'
num = r
return result
if __name__ == '__main__':
print get_float_rep(0.72) #('Error 2', '.1011100001010001111010111000010')
print get_float_rep(0.1) # ('Error 2', '.0001100110011001100110011001100')
print get_float_rep(0.5) #'.1'

View File

@ -0,0 +1,80 @@
#!/usr/bin/python
__author__ = "Mari Wahl"
__email__ = "marina.w4hl@gmail.com"
''' using sets '''
def intersection_two_arrays_sets(seq1, seq2):
''' find the intersection of two arrays using set proprieties '''
set1 = set(seq1)
set2 = set(seq2)
return set1.intersection(set2) #same as list(set1 & set2
''' using merge sort '''
def intersection_two_arrays_ms(seq1, seq2):
''' find the intersection of two arrays using merge sort '''
res = []
while seq1 and seq2:
if seq1[-1] == seq2[-1]:
res.append(seq1.pop())
seq2.pop()
elif seq1[-1] > seq2[-1]:
seq1.pop()
else:
seq2.pop()
res.reverse()
return res
''' using binary search '''
def binary_search(seq, key, lo=0, hi=None):
''' binary search iterative algorithm '''
hi = hi or len(seq)
while lo < hi:
mid = (hi+lo) // 2
if seq[mid] == key:
return True
elif key > seq[mid]:
lo = mid + 1
else:
hi = mid
return None
def intersection_two_arrays_bs(seq1, seq2):
''' if A small and B is too large, we can do a binary search on each entry in B '''
''' only works if sorted and the small sequence has not larger nmbers!!!'''
if len(seq1) > len(seq2): seq, key = seq1, seq2
else: seq, key = seq2, seq1
intersec = []
for item in key:
if binary_search(seq, item):
intersec.append(item)
return intersec
def test_intersection_two_arrays(module_name='this module'):
seq1 = [1,2,3,5,7,8]
seq2 = [3,5,6]
assert(set(intersection_two_arrays_sets(seq1,seq2)) == set([3,5]))
assert(intersection_two_arrays_bs(seq1,seq2) == [3,5])
assert(intersection_two_arrays_ms(seq1,seq2) == [3,5])
s = 'Tests in {name} have {con}!'
print(s.format(name=module_name, con='passed'))
if __name__ == '__main__':
test_intersection_two_arrays()

View File

@ -0,0 +1,31 @@
def beating_stock(array):
imin = 0
i = 1
deal = [array[i] - array[imin], imin, i]
while i < len(array):
deal_here = array[i] - array[imin]
if deal_here > deal[0]:
deal = [deal_here, imin, i]
elif array[i] < array[imin]:
imin = i
i += 1
return deal[0], array[deal[1]], array[deal[2]]
array = [7, 2, 3, 6, 5, 8, 5, 3, 4]
print(array)
print("The best profit is %d, buying at %d, selling at %d." %(beating_stock(array)))

View File

@ -0,0 +1,9 @@
How to know how many 0 are in 100!
You look for the primes that multiply to 10, i.e. 2 and 5.
There are more 5 than 2s so you can count the fives.
there is 100/5 = 20, so 20 5s. However, there are two 5s in 25, 50, 75 and 100.
result: 20+4 = 24

View File

@ -0,0 +1,28 @@
from collections import Counter
def check_if_ransom_note(magazines, note):
count = Counter()
pm, pn = 0, 0
while pn < len(note) and pm < len(magazines):
char_note = note[pn]
if count[char_note]>0:
count[char_note] -= 1
pn += 1
else:
char_magazine = magazines[pm]
count[char_magazine] += 1
pm +=1
return pn == len(note)
magazines1 = "avfegthhgrebvkdsvnijnvyijfdmckdsmovkmmfvskumvl;cdkmioswckofjbkreenyukjemjgnmkmvkmnvdkmvkr g gmvdvmldm vldfkmbldkmlvdkm"
magazines2 = "adfsfa"
note = "you should disobey"
print(check_if_ransom_note(magazines1, note))
print(check_if_ransom_note(magazines2, note))

View File

@ -0,0 +1,12 @@
#!/bin/python
''' Reverting a string '''
def revert(string):
return string[::-1]
if __name__ == '__main__':
string = "Google is fun!"
print(revert(string))

View File

@ -0,0 +1,43 @@
#!/usr/bin python
def reversing_words_setence_py(s):
words = s.split()
return ' '.join(reversed(words))
def reversing_words_setence_py2(s):
words = s.split(' ')
words.reverse()
return ' '.join(words)
def reversing_words_setence_py3(s):
p1 = 0
word = ''
arr = []
while p1 < len(s):
if s[p1] != ' ':
word += s[p1]
else:
arr.append(word)
word = ''
p1 += 1
arr.append(word)
new = ''
while arr:
new += arr.pop()
new += ' '
return new
if __name__ == '__main__':
s = "Buffy is a Vampire Slayer"
print reversing_words_setence_py(s)
print reversing_words_setence_py2(s)
print reversing_words_setence_py3(s)

View File

@ -0,0 +1,3 @@
How to shuffle an array or a deck of cards so each shuffle has the same probability?
go thru the array shuffling each element with any random element after that.

View File

@ -0,0 +1,17 @@
#!/bin/python
''' Quick sort an array '''
def quick_sort(arr):
if len(arr) < 2: return arr
piv = len(arr)//2
left = [x for i, x in enumerate(arr) if x <= arr[piv] and i != piv]
right = [x for i, x in enumerate(arr) if x > arr[piv] and i != piv]
return quick_sort(left) + [arr[piv]] + quick_sort(right)
if __name__ == '__main__':
arr = [8, 5, 2, 6, 1, 2, 9, 4]
print(quick_sort(arr))

View File

@ -0,0 +1,24 @@
#!/usr/bin/python
import collections
import string
import sys
def count_unique_word_file():
if len(sys.argv) < 2:
print "Usage: python count_unique_word.py NAMEFILE"
words = collections.defaultdict(int)
strip = string.whitespace + string.punctuation + string.digits + "\"'"
for filename in sys.argv[1:]:
with open(filename) as file:
for line in file:
for word in line.lower().split():
word = word.strip(strip)
if len(word) > 2:
words[word] = +1
for word in sorted(words):
print("'{0}' occurs {1} times.".format(word, words[word]))
if __name__ == '__main__':
count_unique_word_file()