Skip to content

Commit 6a7403e

Browse files
committed
Misc
1 parent 8c21fb9 commit 6a7403e

18 files changed

+338
-0
lines changed

costExplorer/__init__.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
Ranjan Raghu to Everyone (4:34 PM)
3+
CostExplorer ->
4+
monthlyCostList(): Array/List of size 12 filled with cost incurred in each month of the unit year
5+
annualCost(): Total cost in a unit year
6+
// Atlassian pricing plans as tuple of {planId, monthlyCost}
7+
[
8+
{BASIC, 9.99},
9+
{STANDARD, 49.99},
10+
{PREMIUM, 249.99}
11+
]
12+
Ranjan Raghu to Everyone (4:35 PM)
13+
// Customer subscription information
14+
Customer -> C1
15+
Product ->
16+
Name -> Jira
17+
Subscription -> [ BASIC, "2022-03-10” ] // { planId, startDate }, date in YYYY-MM-DD format
18+
"""
19+

costExplorer/driver.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from costExplorer.entity.customer import Customer
2+
from costExplorer.entity.plan import Plan
3+
from costExplorer.entity.product_subscription import ProductSubscription
4+
from costExplorer.service.cost_service import CostService
5+
6+
if __name__ == '__main__':
7+
costService: CostService = CostService()
8+
customer: Customer = Customer("cust1")
9+
10+
costService.addCustomer(customer)
11+
costService.subscribeToPlan("cust1",
12+
ProductSubscription("prod1", 2, Plan("BASIC", monthlyCost=10.0))
13+
)
14+
15+
costService.subscribeToPlan("cust1",
16+
ProductSubscription("prod2", 2, Plan("BASIC", monthlyCost=20.0))
17+
)
18+
19+
print(costService.combinedMonthlyCost("cust1"))
20+
21+
# annualCost = costService.annualCost("cust1", "prod1")
22+
# print(annualCost)
23+
#
24+
# monthlyCost = costService.calculateMonthlyCost("cust1", "prod1")
25+
# print(monthlyCost)
26+
#
27+
# annualCost = costService.annualCost("cust1", "prod2")
28+
# print(annualCost)
29+
#
30+
# monthlyCost = costService.calculateMonthlyCost("cust1", "prod2")
31+
# print(monthlyCost)
32+
33+
34+
35+

costExplorer/entity/__init__.py

Whitespace-only changes.

costExplorer/entity/customer.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from costExplorer.entity.product_subscription import ProductSubscription
2+
from typing import List
3+
4+
class Customer(object):
5+
def __init__(self, name):
6+
self.name = name
7+
self.subscriptions: List[ProductSubscription] = []
8+
9+
def subscribeToProduct(self, productSub: ProductSubscription):
10+
# TODO - validation
11+
self.subscriptions.append(productSub)
12+
13+

costExplorer/entity/plan.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from enum import Enum
2+
3+
# class PlayType(Enum):
4+
# BASIC = 1
5+
# STANDARD = 2
6+
# PREMIUM = 3
7+
8+
class Plan(object):
9+
def __init__(self, planType: str, monthlyCost: float):
10+
self.planType = planType
11+
self.monthlyCost = monthlyCost
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from costExplorer.entity.plan import Plan
2+
3+
4+
class ProductSubscription(object):
5+
def __init__(self, name, monthNum: int, plan: Plan):
6+
self.name = name
7+
self.monthNum = monthNum
8+
self.plan = plan

costExplorer/service/__init__.py

Whitespace-only changes.

costExplorer/service/cost_service.py

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from costExplorer.entity.customer import Customer
2+
from typing import List
3+
from datetime import date
4+
from costExplorer.entity.product_subscription import ProductSubscription
5+
6+
7+
class CostService(object):
8+
9+
def __init__(self):
10+
self.customers: List[Customer] = []
11+
12+
def addCustomer(self, customer: Customer):
13+
# TODO - Validation
14+
self.customers.append(customer)
15+
16+
def subscribeToPlan(self, customerName: str, productSubscription: ProductSubscription):
17+
# TODO - Validation
18+
customer: Customer = list(filter(lambda cust: cust.name == customerName, self.customers))[0]
19+
customer.subscribeToProduct(productSubscription)
20+
21+
22+
def calculateMonthlyCost(self, customerName: str, productName: str) -> List[float]:
23+
customer: Customer = list(filter(lambda cust: cust.name == customerName, self.customers))[0]
24+
productSubscription: ProductSubscription = \
25+
list(filter(lambda sub: sub.name == productName, customer.subscriptions))[0]
26+
currMonth: int = date.today().month
27+
remainingMonths = 12 - (currMonth - productSubscription.monthNum) + 1
28+
return [0.0 for i in range(12-remainingMonths)] + [productSubscription.plan.monthlyCost for i in range(remainingMonths)]
29+
30+
31+
def annualCost(self, customerName: str, productName: str) -> float:
32+
totalCost = 0
33+
monthlyCost = self.calculateMonthlyCost(customerName, productName)
34+
for cost in monthlyCost:
35+
totalCost += cost
36+
return cost
37+
38+
def combinedMonthlyCost(self, customerName):
39+
customer: Customer = list(filter(lambda cust: cust.name == customerName, self.customers))[0]
40+
41+
totalCombinedCost: List[float] = [0.0 for i in range(12)]
42+
43+
for sub in customer.subscriptions:
44+
prodMonthyCost: List[float] = self.calculateMonthlyCost(customerName, sub.name)
45+
46+
for i, cost in enumerate(prodMonthyCost):
47+
totalCombinedCost[i] += cost
48+
49+
return totalCombinedCost
50+
51+
52+
53+
54+
55+
56+
57+
58+

interview.py

Whitespace-only changes.

interview/m.py

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
abcde'
3+
'Abcd'
4+
"""
5+
6+
from collections import defaultdict
7+
8+
def getDiffChar(s1: str, s2: str):
9+
larger, smaller = s1, s2
10+
if len(s1) < len(s2):
11+
larger = s2
12+
smaller = s1
13+
14+
hm = defaultdict(int)
15+
16+
for ch in larger:
17+
hm[ch] += 1
18+
19+
for ch in smaller:
20+
if ch in larger:
21+
hm[ch] -= 1
22+
23+
if hm[ch] == 0:
24+
hm.pop(ch)
25+
else:
26+
return ch
27+
28+
if len(hm) == 0:
29+
return None
30+
31+
return list(hm.keys())[0]
32+
33+
34+

interview/main/candidate.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Candidate(object):
2+
def __init__(self, name):
3+
self.name = name
4+
# self.score = 0
5+
6+
# def calucateScore(self):
7+
# pass

interview/main/main.py

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""
2+
Problem Description:
3+
4+
We are going to implement a function that determines the winner of a round of Shipit. Our function is going to look something like this:
5+
6+
7+
/**
8+
* For a list of votes, return an ordered set of candidate in descending order of their votes.
9+
*/
10+
List<String> findWinner(List<Vote> votes)
11+
We pass in a list of votes and we are returned a list of names in the descending order of the score that each candidate received.
12+
13+
Assume that we extract the candidates' names from the votes as we process them.
14+
15+
Assumption: A voter is allowed to vote for up to Max three different candidates (this should be configurable). The order of the votes is important. The first vote that a voter places is worth three points. The second vote is worth two points. The third vote is worth one point.
16+
17+
Check for all the boundary conditions before implementing the problem
18+
19+
Sample Input:
20+
21+
22+
leaderBoard = {
23+
"Mykola": 3
24+
Michale: 2,
25+
Marcin: 1
26+
}
27+
28+
O(n) + Klog(n)
29+
30+
votes = [
31+
Vote(["Mykola", "Michale", "Marcin"]),
32+
Vote(["Marcin", "Michale", "Mykola"]),
33+
Vote(["Michale", "Mykola", "Marcin"]),
34+
Vote(["Michale", "Marcin", "Mykola"]),
35+
Vote(["Mykola", "Michale", "Marcin"]),
36+
Vote(["Marcin", "Michale", "Mykola"]),
37+
Vote(["Michale", "Mykola", "Marcin"]),
38+
Vote(["Michale", "Marcin", "Mykola"]),
39+
Vote(["Mykola", "Michale", "Marcin"]),
40+
Vote(["Marcin", "Michale", "Mykola"]),
41+
Vote(["Michale", "Mykola", "Marcin"]),
42+
Vote(["Michale", "Marcin", "Mykola"]),
43+
Vote(["Mykola", "Marcin", "Michale"]),
44+
Vote(["Mykola", "Marcin"]),
45+
Vote(["Mykola"]),
46+
]
47+
"""
48+
from interview.main.vote import Vote
49+
from interview.main.voteUtility import VoteUtility
50+
51+
if __name__ == '__main__':
52+
votes = [
53+
Vote(["Mykola", "Michale", "Marcin"]),
54+
Vote(["Mykola", "Mykola", "Mykola"]),
55+
Vote(["Mykola", "Michale", "Marcin", "Raj"]),
56+
Vote(["Michale", "Marcin", "Mykola"]),
57+
Vote(["Mykola", "Michale", "Marcin"]),
58+
# Vote(["Marcin", "Michale", "Mykola"]),
59+
# Vote(["Michale", "Mykola", "Marcin"]),
60+
# Vote(["Michale", "Marcin", "Mykola"]),
61+
# Vote(["Mykola", "Michale", "Marcin"]),
62+
# Vote(["Marcin", "Michale", "Mykola"]),
63+
# Vote(["Michale", "Mykola", "Marcin"]),
64+
# Vote(["Michale", "Marcin", "Mykola"]),
65+
# Vote(["Mykola", "Marcin", "Michale"]),
66+
# Vote(["Mykola", "Marcin"]),
67+
# Vote(["Mykola"]),
68+
]
69+
voteUtility: VoteUtility = VoteUtility()
70+
for vote in votes:
71+
voteUtility.castVote(vote.candidates)
72+
73+
winners = voteUtility.leaderboard()
74+
print(winners)

interview/main/vote.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from typing import List
2+
3+
from interview.main.candidate import Candidate
4+
5+
6+
class Vote(object):
7+
def __init__(self, candidates: List[str]):
8+
self.candidates = candidates

interview/main/voteUtility.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from interview.main.candidate import Candidate
2+
from typing import Dict, List
3+
from collections import defaultdict
4+
5+
class VoteUtility(object):
6+
def __init__(self):
7+
self.MAX_VOTES = 3
8+
self.candidates: Dict[str, Candidate] = dict()
9+
self.candidatesScores: Dict[str, int] = defaultdict(int)
10+
11+
# [c1, c2, c3] -> len(candNames) - i
12+
def castVote(self, candidateNames: List[str]):
13+
voteCount = len(candidateNames)
14+
if voteCount == 0 or voteCount > self.MAX_VOTES:
15+
print("Invalid vote")
16+
return
17+
18+
for i, candidateName in enumerate(candidateNames):
19+
if candidateName is None:
20+
print("Invalid name")
21+
continue
22+
candidateName = candidateName.lower()
23+
if candidateName not in self.candidates:
24+
self.candidates[candidateName] = Candidate(candidateName)
25+
26+
currScore = voteCount - i
27+
self.candidatesScores[candidateName] = self.candidatesScores[candidateName] + currScore
28+
29+
def leaderboard(self) -> List[str]:
30+
print(self.candidatesScores) # TODO: Suyash - For testing, remove it later
31+
return list(sorted(self.candidatesScores.keys(), key=lambda cName: self.candidatesScores[cName], reverse=True))
32+
33+

url_shortener/__init__.py

Whitespace-only changes.

url_shortener/app.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from flask import Flask, request, redirect
2+
from .service.shorener_service import ShortenerService
3+
4+
app = Flask(__name__)
5+
shortener_service: ShortenerService = ShortenerService()
6+
7+
8+
@app.route("/")
9+
def hello_world():
10+
return "<p>Hello, World!</p>"
11+
12+
@app.route("/shorten", methods=["POST"])
13+
def shorten():
14+
print(request.json)
15+
# TODO - rqeuest param validation
16+
short_url = shortener_service.generate_short_url(request.json['raw_url'])
17+
return "localhost:5000/redirect/{}".format(short_url) # TODO -Need to get the base_url from config
18+
19+
@app.route("/redirect/<short_url>", methods=["GET"])
20+
def redirect_to_raw_url(short_url):
21+
raw_url = shortener_service.get_raw_url(short_url)
22+
return "<p><a href='{}'>Redirect</a></p>".format(raw_url)

url_shortener/service/__init__.py

Whitespace-only changes.
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import random
2+
3+
class ShortenerService(object):
4+
def __init__(self):
5+
self.urls_mapping = dict()
6+
7+
def generate_short_url(self, raw_url):
8+
shortened_url = ''.join(random.choice('0123456789ABCDEF') for i in range(6))
9+
# TODO - check for collision
10+
self.urls_mapping[shortened_url] = raw_url
11+
return shortened_url
12+
13+
def get_raw_url(self, shortened_url):
14+
# TODO - validate if it's a valid shortened url
15+
return self.urls_mapping[shortened_url]
16+

0 commit comments

Comments
 (0)