MAN AHL interview
This commit is contained in:
72
puzzles/interviews/man_AHL/rand_num_next.py
Normal file
72
puzzles/interviews/man_AHL/rand_num_next.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import random
|
||||||
|
import bisect
|
||||||
|
|
||||||
|
class RandomGen(object):
|
||||||
|
|
||||||
|
def __init__(self, random_nums, probabilities):
|
||||||
|
assert len(random_nums), 'Random number list is empty.'
|
||||||
|
assert len(random_nums) == len(probabilities), 'Random numbers and probabilities do not match.'
|
||||||
|
assert abs(1. - sum(probabilities)) < 0.0000001, 'Probabilities do not sum to 1.'
|
||||||
|
|
||||||
|
# Values that may be returned by next_num()
|
||||||
|
self._random_nums = random_nums
|
||||||
|
# Probability of the occurence of random_nums.
|
||||||
|
# Actually we create range table here, such that all random numbers
|
||||||
|
# ranging from (tbl[i-1],tbl[i]] map to random_number[i]
|
||||||
|
self._range_table = probabilities
|
||||||
|
for i in range(1,len(self._range_table)):
|
||||||
|
self._range_table[i] += self._range_table[i-1]
|
||||||
|
# All random numbers which are not in any range will map
|
||||||
|
# to last _random_num. Therefore there is no point to have
|
||||||
|
# last _random_num probability range in the table.
|
||||||
|
self._range_table.pop()
|
||||||
|
|
||||||
|
|
||||||
|
def next_num(self):
|
||||||
|
"""
|
||||||
|
Returns one of the randomNums. When this method is called
|
||||||
|
multiple times over a long period, it should return the
|
||||||
|
numbers roughly with the initialized probabilities.
|
||||||
|
"""
|
||||||
|
r = random.random()
|
||||||
|
return self._random_nums[bisect.bisect_left(self._range_table, r)]
|
||||||
|
|
||||||
|
|
||||||
|
def test_init(random_nums, probabilities):
|
||||||
|
try:
|
||||||
|
rg = RandomGen(random_nums, probabilities)
|
||||||
|
except AssertionError as e:
|
||||||
|
return
|
||||||
|
assert False, "Had to be assert, but no assert could be detected."
|
||||||
|
|
||||||
|
|
||||||
|
def test(input, rep_count = 1000):
|
||||||
|
generate_stat = { _1 : 0 for _1,_ in input.items() }
|
||||||
|
rg = RandomGen([key for key in input.keys()], [val for val in input.values()])
|
||||||
|
for i in range(rep_count):
|
||||||
|
generate_stat[rg.next_num()] += 1
|
||||||
|
|
||||||
|
for rnum, rnum_stat in generate_stat.items():
|
||||||
|
stat_prob = rnum_stat/rep_count
|
||||||
|
orig_prob = input[rnum]
|
||||||
|
print('{}: orig: {} actual: {}'.format(rnum, orig_prob, stat_prob))
|
||||||
|
print('')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_init([], []) # Empty list of numbers not allowed
|
||||||
|
test_init([1, 2], [1. ]) # Probabilities don't match
|
||||||
|
test_init([1, 2], [ 0.1, 0.1]) # Probabilities don't sum to 1.
|
||||||
|
test({0 : 0.5,
|
||||||
|
1 : 0.25,
|
||||||
|
2 : 0.25 })
|
||||||
|
test({-1 : 0.01,
|
||||||
|
0 : 0.3,
|
||||||
|
1 : 0.58,
|
||||||
|
2 : 0.1,
|
||||||
|
3 : 0.01 }, 100)
|
||||||
|
test({-1 : 0.01,
|
||||||
|
0 : 0.3,
|
||||||
|
1 : 0.58,
|
||||||
|
2 : 0.1,
|
||||||
|
3 : 0.01 }, 100000)
|
||||||
23
puzzles/interviews/man_AHL/sql_query.txt
Normal file
23
puzzles/interviews/man_AHL/sql_query.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
I can imagine that the query should be something like this. But my SQL is not very good.
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
p.product_id as product_id,
|
||||||
|
p.name as name,
|
||||||
|
o.quantity as quantity
|
||||||
|
FROM
|
||||||
|
product p
|
||||||
|
JOIN (
|
||||||
|
SELECT
|
||||||
|
product_id,
|
||||||
|
SUM(quantity) as quantity
|
||||||
|
FROM
|
||||||
|
order
|
||||||
|
WHERE
|
||||||
|
dispatch_date > DATEADD(year, -1, GETDATE())
|
||||||
|
GROUP BY
|
||||||
|
product_id
|
||||||
|
) o ON o.product_id = p.product_id
|
||||||
|
WHERE
|
||||||
|
p.available_from < DATEADD(month, -1, GETDATE())
|
||||||
|
AND o.quantity < 10
|
||||||
|
|
||||||
Reference in New Issue
Block a user