Art of Codeartofcode
LLeeaarrnniinngg
BBlloogg
TToooollss
GGaammeess AArreennaa
JJoobbss
LLiivvee CCoouurrsseess

Courses

  • System DesignHigh-level system design, one everyday scene at a time: 30 concepts and 15 interview rounds.712 lessons
All coursesTutorialsMy Learning

Categories

  • 01AI & Tools
  • 02Tutorials
  • 03Engineering
  • 04Reviews
  • 05Build Logs
  • 06Tales of Misfits
  • 07Opinion
  • 08Career
  • 09News

Read & write

All storiesEvery post, newest first.Write for usPublish your stories and earn from what you write.Writer leaderboardsWho is writing the most read posts.

Categories

  • PDF Tools25
  • Development09
  • Utilities10
  • Design04
  • Converters04
  • Generators02

Featured

JSON FormatterFormat, validate and minify JSON.Regex TesterTest patterns against live text.Merge PDFCombine PDFs in your browser.JWT DecoderRead a token’s header and claims.Password GeneratorStrong passwords, generated locally.Gradient GeneratorBuild CSS gradients visually.
All 53 tools

Play a round

DevdleOne developer word a day, six guesses.Python RushClassic snake, with coding icons to eat.Blink or BreakA quick test of your reflexes.
Games Arena

Learn with us

Live CoursesInstructor-led courses. Join a waitlist and be first in when one starts.LearningStructured programming courses with AI assistance and certificates.

System Design

1. How to Approach a Design Question

Lesson 21 of 21

1. How to Approach a Design Question

1
The picture to keep in your head
2
1.1 What is a system design interview, and what isn't it?
3
1.2 What is the interviewer actually scoring?
4
1.3 What's the step-by-step framework?
5
1.4 How do you manage a 45-minute round?
6
1.5 What questions should you ask first?
7
1.6 What's the difference between functional and non-functional requirements?
8
1.7 What's an API, and why define it before drawing boxes?
9
1.8 How do you sketch the data model?
10
1.9 What does a good high-level design look like?
11
1.10 How do you choose what to deep dive into?
12
1.11 How do you talk about trade-offs?
13
1.12 What if you get stuck or don't know something?
14
1.13 What are the most common mistakes?
15
1.14 What does the bar look like: fresher vs SDE-2?
16
Memory card and where the analogy breaks
17
Practice: five levels
18
Interview questions
19
Solutions
20
Sources
21
Code lab
1. How to Approach a Design Question

Code lab

3 min read+10 XP

Code lab: Chapter 1

The full, tested code for this chapter. Press Run: every check should pass. Then change one number, run it again, and see which check breaks and why.

python

No tracks available

Lofi Player

artofcode

artofcode.in

The den of devs.

Stories, tools, games, and gear for developers.

Read the StoriesEExxpplloorree TToooollss
Art of Codeartofcode

Platform

  • BBlloogg
  • TToooollss
  • GGaammeess AArreennaa
  • CCoouurrsseess
  • LLeeaarrnniinngg
  • CCaammppuuss

Company

  • AAbboouutt UUss
  • JJoobbss && IInntteerrnnsshhiippss
  • CCoonnttaacctt

Legal

  • TTeerrmmss ooff SSeerrvviiccee
  • PPrriivvaaccyy PPoolliiccyy
  • RReeffuunndd PPoolliiccyy

Copyright © 2026 artofcode.in, All Rights Reserved.

IST·--:--

1"""Chapter 1 practice: a tiny in-memory URL shortener (Level 3 Build) and the
2random-code collision bug (Level 4 Debug). Run: python3 ch01_url_shortener.py"""
3import random
4import string
5
6ALPHABET = string.digits + string.ascii_lowercase + string.ascii_uppercase  # 62 characters
7
8
9def to_base62(n):
10    if n == 0:
11        return ALPHABET[0]
12    out = []
13    while n > 0:
14        n, r = divmod(n, 62)
15        out.append(ALPHABET[r])
16    return "".join(reversed(out))
17
18
19class Shortener:
20    """Counter-based shortener: every new link gets the next number, written in base62."""
21
22    def __init__(self, base_url="https://sho.rt/"):
23        self.base_url = base_url
24        self.next_id = 1
25        self.code_to_url = {}
26        self.url_to_code = {}  # so the same long URL gets the same short code
27
28    def shorten(self, long_url):
29        if not long_url.startswith(("http://", "https://")):
30            raise ValueError("not a valid URL")
31        if long_url in self.url_to_code:
32            return self.base_url + self.url_to_code[long_url]
33        code = to_base62(self.next_id)
34        self.next_id += 1
35        self.code_to_url[code] = long_url
36        self.url_to_code[long_url] = code
37        return self.base_url + code
38
39    def resolve(self, code):
40        return self.code_to_url.get(code)  # None means "404 Not Found"
41
42
43# ---- Level 4: the buggy version ------------------------------------------------
44
45class BuggyShortener:
46    """Picks a random code and never checks whether it's already taken."""
47
48    def __init__(self, code_length=6, seed=None):
49        self.code_length = code_length
50        self.rng = random.Random(seed)
51        self.code_to_url = {}
52
53    def shorten(self, long_url):
54        code = "".join(self.rng.choice(ALPHABET) for _ in range(self.code_length))
55        self.code_to_url[code] = long_url  # BUG: silently overwrites an existing code
56        return code
57
58
59class FixedShortener(BuggyShortener):
60    def shorten(self, long_url):
61        while True:
62            code = "".join(self.rng.choice(ALPHABET) for _ in range(self.code_length))
63            if code not in self.code_to_url:  # fix: only use a code nobody has
64                self.code_to_url[code] = long_url
65                return code
66
67
68def run_checks():
69    s = Shortener()
70
71    # 1. Shorten then resolve returns the original URL.
72    short = s.shorten("https://example.com/a/very/long/page?id=42")
73    code = short.rsplit("/", 1)[1]
74    assert s.resolve(code) == "https://example.com/a/very/long/page?id=42"
75
76    # 2. The same long URL gets the same code.
77    assert s.shorten("https://example.com/a/very/long/page?id=42") == short
78
79    # 3. Different URLs get different codes.
80    other = s.shorten("https://example.com/other")
81    assert other != short
82
83    # 4. An unknown code returns None (404).
84    assert s.resolve("zzzzzz") is None
85
86    # 5. Invalid input is rejected.
87    try:
88        s.shorten("not a url")
89        raise AssertionError("should have rejected")
90    except ValueError:
91        pass
92
93    # 6. Base62 lengths: 6 characters cover 62**6 = 56.8 billion codes.
94    assert to_base62(62**6 - 1) == "ZZZZZZ"
95    assert len(to_base62(62**6)) == 7
96
97    # Level 4: with only 2-character codes (3,844 possible), collisions show up fast.
98    buggy = BuggyShortener(code_length=2, seed=7)
99    urls = [f"https://example.com/{i}" for i in range(500)]
100    for u in urls:
101        buggy.shorten(u)
102    lost = len(urls) - len(buggy.code_to_url)
103    assert lost > 0, "expected the buggy version to lose links"
104
105    fixed = FixedShortener(code_length=2, seed=7)
106    for u in urls:
107        fixed.shorten(u)
108    assert len(fixed.code_to_url) == len(urls)
109
110    print(f"All checks pass. Buggy version lost {lost} of {len(urls)} links; fixed version lost 0.")
111
112
113if __name__ == "__main__":
114    run_checks()