Password Generator
What: A password generator builds a secure string by guaranteeing at least one character from each required set — one uppercase, one lowercase, one digit, one special — filling the rest from the combined pool, then shuffling so the pattern is not predictable. Why it matters: It is the canonical example of "constraint satisfaction": you enforce business rules (complexity requirements) before randomisation, just like you enforce schema constraints before writing to a Delta table. How to remember: Pick the mandatory four first, fill to length, shuffle last — if you shuffle before filling, the guarantee is lost.
random from pool → shuffle() → A7@kQ9pL2!x
upper + lower + digits + special | Without shuffle the first 4 chars would always be Upper-lower-special-digit (predictable!)import random, string
def gen_password(length=10):
upper = string.ascii_uppercase
lower = string.ascii_lowercase
digits = '0123456789'
special = '!@#$%^&*'
pwd = [random.choice(upper), random.choice(lower), random.choice(special), random.choice(digits)]
pool = upper + lower + digits + special
pwd += [random.choice(pool) for _ in range(length - len(pwd))]
random.shuffle(pwd)
return ''.join(pwd)
print(gen_password(10))
print(gen_password(12))
# Example outputs (random, yours will differ):
# A7@kQ9pL2!x / Z3^mPq8&bL1!A7@kQ9pL2!x
Z3^mPq8&bL1!Banking CLI — 7 operations (bug fixed)
What: The banking CLI is a miniature core-banking system built on a dictionary — bankaccount = {accNo: {name, balance}} — exposing seven operations: create, view, deposit, withdraw, transfer, list, and number generation. Why it matters: It forces you to handle the classic distributed-systems bug: transfer must debit one account and credit another atomically, with balance checks before mutation, otherwise a concurrent transfer can leave money duplicated or lost. How to remember: The fixed transfer bug is the lesson — check existence of both accounts, check sufficient funds on the sender, then mutate both in one step.
unique check
or "not exist"
then -=
sender ≥ amt? →
sender-=, receiver+=
or "none yet"
bankaccount = { 443402: {name:'praveen', balance:10000}, 499572: {name:'kumar', balance:3000} } — dict of dicts, like Spark JSON rows.fr not in bankaccount or to not in bankaccount before touching balances.import random
bankaccount = {}
def generateaccountnumber():
while True:
n = random.randint(100000,999999)
if n not in bankaccount: return n
def createaccount(name, initialbalance=0):
n = generateaccountnumber()
bankaccount[n] = {'name': name, 'balance': initialbalance}
print(f'account created, your number is {n}')
return n
def viewbalance(n):
print(f'balance is {bankaccount[n]["balance"]}' if n in bankaccount else 'account does not exist')
def depositmoney(n, amt):
if n in bankaccount:
bankaccount[n]['balance']+=amt; print('deposited')
else: print('account does not exist')
def withdrawmoney(n, amt):
if n not in bankaccount: print('account does not exist')
elif bankaccount[n]['balance'] < amt: print('insufficient funds')
else: bankaccount[n]['balance']-=amt; print('withdrawn')
def transfermoney(fr,to,amt):
if fr not in bankaccount or to not in bankaccount:
print('account does not exist'); return
if bankaccount[fr]['balance'] < amt:
print(f'insufficient funds, balance is {bankaccount[fr]["balance"]}'); return
bankaccount[fr]['balance']-=amt; bankaccount[to]['balance']+=amt
print(f'funds transferred, your balance is {bankaccount[fr]["balance"]}')
def listaccounts():
print(list(bankaccount.items()) if bankaccount else 'No account yet')
# Demo (numbers random)
# a = createaccount('praveen', 10000) # 443402
# b = createaccount('kumar', 1000) # 499572
# viewbalance(a) # balance is 10000
# depositmoney(a, 5000) # deposited → 15000
# withdrawmoney(a,3000) # withdrawn → 12000
# transfermoney(a,b,2000) # funds transferred → a:10000 b:3000account created, your number is 443402
account created, your number is 499572
balance is 10000
deposited
withdrawn
funds transferred, your balance is 10000Bubble Sort
What: Bubble sort repeatedly walks the list, comparing each adjacent pair and swapping if they are out of order — the largest element "bubbles" to the end each pass, so the next pass can ignore the last sorted element. Why it matters: You will rarely sort in Python (use sorted() or Spark's orderBy), but bubble sort is the interview standard for proving you understand nested loops, the shrinking window range(n-i-1), and in-place swapping a,b = b,a. How to remember: Outer loop = number of passes, inner loop = window that shrinks by i each time because the last i elements are already sorted.
for i in range(n): for j in range(n-i-1): if x[j] > x[j+1]: x[j],x[j+1]=x[j+1],x[j] — n-i-1 is the shrinking windowpalindrome
s == s[::-1] — reverse and compare. 'mom' → True.count chars
out[c] = out.get(c,0)+1 — same pattern as word count in Spark.fibonacci
a,b = b,a+b — parallel assignment generates sequence iteratively.xlist = [100,32,5,6,12,9,60]
n = len(xlist)
for i in range(n):
for j in range(n-i-1): # shrinks — last i elements already sorted
if xlist[j] > xlist[j+1]:
xlist[j], xlist[j+1] = xlist[j+1], xlist[j]
print(xlist) # [5, 6, 9, 12, 32, 60, 100]
def countofoccurence(s):
out={}
for c in s:
out[c] = out.get(c,0)+1
return out
print(countofoccurence('aaabbaccddeeef'))
# {'a':4,'b':2,'c':2,'d':2,'e':3,'f':1}
def ispalindrome(s): return s == s[::-1]
print(ispalindrome('mom')) # True
print(ispalindrome('praveen')) # False
def fibonacci(n):
a,b, fib = 0,1,[]
for _ in range(n): fib.append(a); a,b = b, a+b
return fib
print(fibonacci(8)) # [0, 1, 1, 2, 3, 5, 8, 13][5, 6, 9, 12, 32, 60, 100]
{'a': 4, 'b': 2, 'c': 2, 'd': 2, 'e': 3, 'f': 1}
True
False
[0, 1, 1, 2, 3, 5, 8, 13]Turtle Race — GUI
What: The turtle race is a playful GUI simulation — six turtles (red, orange, yellow, green, blue, purple) start at x=-230 on six lanes, then each step moves a random 0-10 forward until one crosses x ≥ 230. Why it matters: It is not a PySpark project but a teachable event loop: while is_race_on: with random progress and a single winner — the same pattern as polling a queue until a job finishes. How to remember: It needs a display (Screen + Turtle), so it only runs locally; on a headless cluster the loop still illustrates non-deterministic racing and bet comparison.
t.forward(random.randint(0,10)) | Winner: first with t.xcor() >= 230 → compare to user_betfrom turtle import Turtle, Screen
import random
screen = Screen(); screen.setup(width=500, height=400)
user_bet = screen.textinput(title="make your bet", prompt="Which turtle will win? Enter a colour: ")
colors = ["red","orange","yellow","green","blue","purple"]
y_positions = [-70,-40,-10,20,50,80]
all_turtles = []
for i in range(6):
t = Turtle(shape="turtle"); t.color(colors[i]); t.penup()
t.goto(x=-230, y=y_positions[i]); all_turtles.append(t)
is_race_on = bool(user_bet)
while is_race_on:
for t in all_turtles:
if t.xcor() >= 230:
winning = t.pencolor()
print("You've won!" if winning==user_bet else f"winning is {winning}, you lost")
is_race_on=False; break
t.forward(random.randint(0,10))
screen.exitonclick()
# → (GUI) prints: You've won! or: winning is blue, you lost(GUI — run locally)
You've won! # if bet matched winner
winning is blue, you lost