Skip to content

Commit d815ee5

Browse files
committed
Improve tone across all 65 problems
Mechanical cleanup: strip em/en-dashes site-wide, replace overused vocabulary (leverage, utilize, facilitate, etc.), drop throat-clearing phrases like 'It's worth noting that' and 'Furthermore'. Capitalize sentence starts after period-replacements. Note: the per-problem prose rewrite pass was started but hit a rate limit before completing for most problems. Em-dashes and AI-smell phrases are clean throughout, but the conversational-voice pass will need another round when limits reset.
1 parent 9d0e6ad commit d815ee5

116 files changed

Lines changed: 907 additions & 916 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CONTRIBUTION.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ Thanks for helping expand the Data Engineering Practice Problems collection. Thi
44

55
## Ways to Contribute
66

7-
- **New practice problems** add interview-style prompts, sample datasets, and reference solutions.
8-
- **Enhance existing solutions** improve performance, readability, resilience, or validation coverage.
9-
- **Improve documentation** clarify instructions, add diagrams or walkthroughs, fix typos.
10-
- **Quality assurance** add tests, linting, or automation that strengthens the developer experience.
7+
- **New practice problems**, add interview-style prompts, sample datasets, and reference solutions.
8+
- **Enhance existing solutions**, improve performance, readability, resilience, or validation coverage.
9+
- **Improve documentation**, clarify instructions, add diagrams or walkthroughs, fix typos.
10+
- **Quality assurance**, add tests, linting, or automation that strengthens the developer experience.
1111

1212
## Contribution Workflow
1313

@@ -19,16 +19,16 @@ Thanks for helping expand the Data Engineering Practice Problems collection. Thi
1919

2020
## Repository Structure Standards
2121

22-
- Every problem lives in `problems/NNN-kebab-case-title/` where `NNN` is a zero-padded id (`001`, `065`, ...). Pick the next free id.
22+
- Every problem lives in `problems/NNN-kebab-case-title/` where `NNN` is a zero-padded id (`001`, `065`,...). Pick the next free id.
2323
- Inside each problem directory:
24-
- `question.md`the problem prompt. **Must start with YAML frontmatter** (see below), followed by a single H1 `# Problem N Title`, then the body.
25-
- `solution.md` written walkthrough (preferred for design / discussion problems), **or** `solution.py` for runnable code problems. Pick one; the frontmatter declares which.
26-
- Optional subdirectories (`data/`, `tests/`) if the problem demands bespoke assets. Keep paths relative (e.g., `../../data/` for shared sample data).
24+
- `question.md`, the problem prompt. **Must start with YAML frontmatter** (see below), followed by a single H1 `# Problem N, Title`, then the body.
25+
- `solution.md`, written walkthrough (preferred for design / discussion problems), **or** `solution.py` for runnable code problems. Pick one; the frontmatter declares which.
26+
- Optional subdirectories (`data/`, `tests/`) if the problem demands bespoke assets. Keep paths relative (e.g., `../../data/` for shared sample data).
2727
- Shared datasets belong in the top-level `data/` directory. Provide a `README` snippet or inline comments describing their provenance if they are newly added.
2828

2929
### Required frontmatter
3030

31-
Every `question.md` begins with this block `PROBLEMS.md` is generated from it:
31+
Every `question.md` begins with this block, `PROBLEMS.md` is generated from it:
3232

3333
```yaml
3434
---

PROBLEMS.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A quick overview of every problem in this repo. Use the **Category** and **Topic
44

55
> This file is generated by `scripts/build_index.py` from the frontmatter in each problem's `question.md`. Do not edit by hand.
66
7-
| # | Problem | Category | Topics | Difficulty | Question | Solution |
7+
| # | Problem | Category | Topics | Difficulty | Question | Solution |
88
|----|---------|----------|--------|------------|----------|----------|
99
| 1 | Log File Error Analysis | Logs and Monitoring | file streaming, counters, top-N, IoT logs | Easy | [Question](problems/001-log-file-error-analysis/question.md) | [Solution](problems/001-log-file-error-analysis/solution.py) |
1010
| 2 | Rolling Average of Sensor Readings | Streaming | rolling window, deque, IoT sensors, real-time | Easy | [Question](problems/002-rolling-average-of-sensor-readings/question.md) | [Solution](problems/002-rolling-average-of-sensor-readings/solution.py) |
@@ -95,8 +95,8 @@ A quick overview of every problem in this repo. Use the **Category** and **Topic
9595

9696
### Difficulty Guide
9797

98-
* **Easy** A focused warm-up. Solvable or explainable in under an hour.
99-
* **Medium** Realistic interview question. Has edge cases that matter.
100-
* **Hard** Multi-step or system-design heavy. Closer to a take-home task.
98+
* **Easy**. A focused warm-up. Solvable or explainable in under an hour.
99+
* **Medium**. Realistic interview question. Has edge cases that matter.
100+
* **Hard**. Multi-step or system-design heavy. Closer to a take-home task.
101101

102102
> New problems are added regularly. If you want to contribute, see the [Contribution Guide](CONTRIBUTION.md).

README.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# 🧩 Data Engineering Practice Problems
22

3-
> After solving 1,500+ problems on LeetCode and Codeforces, I realized
3+
> After solving 1,500+ problems on LeetCode and Codeforces, I realized,
44
> **none of them prepared me for broken CSVs, delayed Kafka messages, or JSONs that lie.**
55
6-
This repo is for engineers who’ve had enough of toy problems. It’s a collection of **real-world data engineering scenarios** — short, practical exercises inspired by what actually breaks in production.
6+
This repo is for engineers who’ve had enough of toy problems. It’s a collection of **real-world data engineering scenarios**. Short, practical exercises inspired by what actually breaks in production.
77

88
---
99

@@ -12,7 +12,7 @@ This repo is for engineers who’ve had enough of toy problems. It’s a collect
1212
Most practice problems test logic.
1313
Production tests resilience.
1414

15-
In production, problems don’t come with test cases they come with missing data, bad assumptions, and time pressure.
15+
In production, problems don’t come with test cases, they come with missing data, bad assumptions, and time pressure.
1616

1717
So I started collecting real scenarios I’ve seen:
1818

@@ -26,15 +26,15 @@ So I started collecting real scenarios I’ve seen:
2626

2727
## What’s Inside
2828

29-
| Category | Scenario | What You’ll Practice |
30-
| :----------------------- | :----------------------------------------------- | :------------------------------------------- |
31-
| **Late Data** | 10 GB of IoT logs arriving out of order | Handle streaming delays without duplication |
32-
| **Schema Drift** | JSON events adding new fields mid-release | Validate and evolve safely |
33-
| **ETL Reliability** | Long-running jobs silently skipping records | Detect silent corruptions before they spread |
34-
| **Data Hygiene** | Partner CSVs with missing headers and fake nulls | Clean data in one pass and log every fix |
35-
| **Rolling Analytics** | Continuous sensor feeds with infinite rows | Keep rolling metrics in memory without dying |
29+
| Category | Scenario | What You’ll Practice |
30+
|:----------------------- |:----------------------------------------------- |:------------------------------------------- |
31+
| **Late Data** | 10 GB of IoT logs arriving out of order | Handle streaming delays without duplication |
32+
| **Schema Drift** | JSON events adding new fields mid-release | Validate and evolve safely |
33+
| **ETL Reliability** | Long-running jobs silently skipping records | Detect silent corruptions before they spread |
34+
| **Data Hygiene** | Partner CSVs with missing headers and fake nulls | Clean data in one pass and log every fix |
35+
| **Rolling Analytics** | Continuous sensor feeds with infinite rows | Keep rolling metrics in memory without dying |
3636

37-
And many more coming ...
37+
And many more coming...
3838

3939
> Each problem is small enough to solve in hours, but real enough to prepare you for production.
4040
@@ -76,7 +76,7 @@ PROBLEMS.md # generated index — do not edit by hand
7676
If you’ve debugged a broken pipeline,
7777
caught a silent bug before it spread,
7878
built a clever patch that saved a release
79-
or found a way to clean a 5 GB CSV in one pass
79+
or found a way to clean a 5 GB CSV in one pass,
8080
your story belongs here.
8181

8282
Add a new scenario, or improve an existing one.
@@ -85,6 +85,6 @@ See the [Contribution Guide](CONTRIBUTION.md) for details.
8585
---
8686

8787
> **The goal isn’t to practice coding.**
88-
> It’s to practice *judgment* the kind that keeps systems running when logic alone isn’t enough.
88+
> It’s to practice *judgment*, the kind that keeps systems running when logic alone isn’t enough.
8989
9090
⭐ Star the repo if you’ve ever learned more from production than from tutorials.

problems/001-log-file-error-analysis/question.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ difficulty: Easy
77
solution: solution.py
88
---
99

10-
# Problem 1 Log File Error Analysis
10+
# Problem 1, Log File Error Analysis
1111

1212
**Scenario:**
13-
You have a huge log file from an IoT platform. Each line follows this structure:
13+
You have a huge log file from an IoT platform. Each line looks like this:
1414

1515
```
1616
2025-10-11T13:45:20Z sensor_12 OK
@@ -20,23 +20,23 @@ You have a huge log file from an IoT platform. Each line follows this structure:
2020
...
2121
```
2222

23-
Each line contains:
23+
Each line has:
2424

2525
* A timestamp (ISO format)
2626
* A sensor ID
2727
* A status (`OK` or `ERROR`)
2828

29-
The file can be **very large (10+ GB)**so you **cannot load it fully into memory**.
29+
The file can be very large (10+ GB), so you cannot load it fully into memory.
3030

3131
---
3232

3333
### Task:
3434

35-
Write a **Python program** that:
35+
Write a Python program that:
3636

37-
1. Reads the log file efficiently (without loading the entire file).
37+
1. Reads the log file efficiently, without loading the whole file.
3838
2. Counts how many times each sensor reported `ERROR`.
39-
3. Prints the **top 5 sensors** with the highest error counts.
39+
3. Prints the top 5 sensors with the highest error counts.
4040

4141
**Bonus (Optional):**
4242

@@ -45,10 +45,10 @@ Write a **Python program** that:
4545

4646
---
4747

48-
💡 **Tips:**
48+
**Tips:**
4949

50-
* Think about streaming/iterative processing.
51-
* Consider using `Counter`, `heapq`, or generator patterns.
52-
* Clean and readable code matters as much as correctness.
50+
* Think streaming, not batch.
51+
* Look at `Counter`, `heapq`, or generator patterns.
52+
* Clean, readable code matters as much as correctness.
5353

5454
---

problems/002-rolling-average-of-sensor-readings/question.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ difficulty: Easy
77
solution: solution.py
88
---
99

10-
# Problem 2 Rolling Average of Sensor Readings
10+
# Problem 2, Rolling Average of Sensor Readings
1111

1212
**Scenario:**
1313
You are building a data pipeline for IoT sensors (like BESS, PV inverters, weather stations).
14-
Each sensor sends temperature data every few seconds to your system in this format:
14+
Each sensor sends temperature data every few seconds in this format:
1515

1616
```
1717
2025-10-11T13:45:20Z sensor_1 25.4
@@ -22,49 +22,49 @@ Each sensor sends temperature data every few seconds to your system in this form
2222
...
2323
```
2424

25-
Each line contains:
25+
Each line has:
2626

2727
* timestamp (ISO8601)
2828
* sensor_id
29-
* temperature (float, °C)
29+
* temperature (float, degrees C)
3030

31-
The stream never ends (you can assume input comes from a file, MQTT, or Kafkabut treat it as **continuous input**).
31+
The stream never ends. Input could be a file, MQTT, or Kafka, but treat it as continuous input.
3232

3333
---
3434

3535
### Task:
3636

3737
Write a Python program that:
3838

39-
1. Continuously reads incoming sensor data (line by line).
40-
2. For **each sensor**, maintains a rolling average temperature over the **last 3 readings**.
41-
3. Each time a new reading arrives, print:
39+
1. Continuously reads incoming sensor data, line by line.
40+
2. For each sensor, keeps a rolling average temperature over the last 3 readings.
41+
3. Each time a new reading arrives, prints:
4242

43-
```
44-
<timestamp> <sensor_id> <rolling_average>
45-
```
43+
```
44+
<timestamp> <sensor_id> <rolling_average>
45+
```
4646

47-
Example:
47+
Example:
4848

49-
```
50-
2025-10-11T13:45:35Z sensor_1 26.17
51-
```
49+
```
50+
2025-10-11T13:45:35Z sensor_1 26.17
51+
```
5252

5353
---
5454

5555
### Bonus Challenges:
5656

57-
* Make it **memory efficient** (don’t store all history).
58-
* Handle **multiple sensors** dynamically.
59-
* Handle malformed lines gracefully.
60-
* Ensure the code could be easily extended to a real streaming consumer (e.g., Kafka/MQTT).
57+
* Make it memory efficient. Don't store all history.
58+
* Handle many sensors dynamically.
59+
* Handle malformed lines without crashing.
60+
* Make the code easy to extend to a real streaming consumer (Kafka, MQTT).
6161

6262
---
6363

64-
💡 **Tips:**
64+
**Tips:**
6565

66-
* Think about how to store only the **last 3 values per sensor**.
67-
* You’ll probably want to use a **deque** or a simple list with slicing.
68-
* Focus on **clean, production-like structure** not just working code.
66+
* Think about how to store only the last 3 values per sensor.
67+
* A `deque` works well here, or a list with slicing.
68+
* Aim for clean, production-like structure, not just working code.
6969

7070
---

problems/003-transform-and-clean-raw-data-for-analytics/question.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ difficulty: Medium
77
solution: solution.py
88
---
99

10-
# Problem 3 Transform and Clean Raw Data for Analytics
10+
# Problem 3, Transform and Clean Raw Data for Analytics
1111

1212
**Scenario:**
13-
You receive raw user activity data from a partner API in a messy CSV file. The company wants to load it into a data warehouse (e.g., BigQuery or PostgreSQL) for analytics.
13+
You receive raw user activity data from a partner API as a messy CSV file. The company wants to load it into a data warehouse (BigQuery, PostgreSQL) for analytics.
1414

15-
Here’s what the CSV looks like:
15+
Here is what the CSV looks like:
1616

1717
```
1818
user_id,name,email,signup_date,last_login,total_purchases
@@ -22,29 +22,29 @@ user_id,name,email,signup_date,last_login,total_purchases
2222
104,,maria@example.com,2025-02-10,,30
2323
```
2424

25-
But it’s full of **dirty and inconsistent data**:
25+
But it is full of dirty, inconsistent data:
2626

2727
* Missing `name` or `email`
2828
* Invalid email format
2929
* Non-numeric values in `total_purchases`
3030
* Empty `last_login`
31-
* Dates in wrong order (e.g., signup_date > last_login)
31+
* Dates in wrong order (signup_date > last_login)
3232

3333
---
3434

3535
### Your Task:
3636

3737
Write a Python program that:
3838

39-
1. Reads the CSV file line by line (assume it’s large — can’t load into memory at once).
40-
2. **Validates and cleans** the data:
39+
1. Reads the CSV file line by line. Assume it is large and won't fit in memory.
40+
2. Validates and cleans the data:
4141

42-
* Skip rows with missing `email` or invalid email format.
43-
* Replace missing `name` with `"Unknown"`.
44-
* Replace missing `last_login` with `"N/A"`.
45-
* Convert `total_purchases` to integer — if invalid, set it to `0`.
46-
* If `signup_date` is **after** `last_login`, mark a new column `is_date_valid` as `False`, else `True`.
47-
3. Writes the cleaned data into a **new CSV file** called `cleaned_users.csv`.
42+
* Skip rows with missing `email` or invalid email format.
43+
* Replace missing `name` with `"Unknown"`.
44+
* Replace missing `last_login` with `"N/A"`.
45+
* Convert `total_purchases` to integer. If invalid, set it to `0`.
46+
* If `signup_date` is after `last_login`, mark a new column `is_date_valid` as `False`, else `True`.
47+
3. Writes the cleaned data into a new CSV file called `cleaned_users.csv`.
4848

4949
**Example Output (cleaned_users.csv):**
5050

@@ -57,19 +57,19 @@ user_id,name,email,signup_date,last_login,total_purchases,is_date_valid
5757

5858
---
5959

60-
### Bonus (if you want to go deeper like a senior engineer):
60+
### Bonus (if you want to go deeper):
6161

6262
* Log how many rows were skipped and why.
6363
* Keep a separate file (`invalid_rows.csv`) for skipped rows.
6464
* Use a `pydantic` model for validation.
6565

6666
---
6767

68-
💡 **Hints for Interview Thinking:**
68+
**Hints for Interview Thinking:**
6969

70-
* Think about **streaming-style reads** (`csv` module or `DictReader`).
71-
* Use **regex for email validation**.
72-
* Be robust — assume bad inputs will appear often.
73-
* Make your solution easy to extend (e.g., add more validation rules later).
70+
* Think streaming reads (`csv` module or `DictReader`).
71+
* Use regex for email validation.
72+
* Assume bad inputs will show up often.
73+
* Make the solution easy to extend (more rules later).
7474

7575
---

0 commit comments

Comments
 (0)