Skip to content

Commit 99778f9

Browse files
committed
update challenges and checkpoint final quiz
1 parent 55b367a commit 99778f9

5 files changed

Lines changed: 558 additions & 277 deletions

File tree

src/chapters/combining-patterns/checkpoint.jsx

Lines changed: 143 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import { useAutoGradeQuiz } from "../../components/useAutoGradeQuiz";
22

33
export const combiningPatternsCheckpointChapter = {
44
id: 'combining-patterns-checkpoint',
5-
title: 'Final Self Assessment: Data Structures & Algorithms',
5+
title: 'Final Self Assessment',
66
sectionId: 'combining-patterns',
7-
previousChapterId: 'solving-complex-problems',
7+
previousChapterId: 'combine-patterns-four',
88
content: null,
99
quiz: {
1010
component: () => {
@@ -13,12 +13,6 @@ export const combiningPatternsCheckpointChapter = {
1313

1414
return (
1515
<main>
16-
<p className="assessment-intro">
17-
This comprehensive assessment covers all major concepts from the course.
18-
Take your time and demonstrate your understanding of data structures, algorithms,
19-
and their real-world applications.
20-
</p>
21-
2216
<form className="auto-graded-quiz">
2317
{/* Big O and Algorithmic Thinking */}
2418
<div className="question" data-answer="O(log n)">
@@ -65,16 +59,39 @@ export const combiningPatternsCheckpointChapter = {
6559
</div>
6660

6761
{/* Sliding Window */}
68-
<div className="question" data-answer="Sliding window maintains a subset of elements and efficiently updates as the window moves">
62+
<div className="question" data-answer="windowSum">
6963
<p>
70-
<strong>Sliding Window:</strong> Explain how the sliding window pattern works and why it&apos;s efficient for analyzing subarrays.
64+
<strong>Sliding Window:</strong> Complete this sliding window implementation to find the maximum sum subarray of size k:
7165
</p>
72-
<input type="text" required />
66+
<pre><code>{`function maxSumSubarray(arr, k) {
67+
let maxSum = 0;
68+
let windowSum = 0;
69+
let left = 0;
70+
71+
for (let right = 0; right < arr.length; right++) {
72+
windowSum += arr[right];
73+
74+
if (right >= k - 1) {
75+
maxSum = Math.max(maxSum, _____);
76+
windowSum -= arr[left];
77+
left++;
78+
}
79+
}
80+
return maxSum;
81+
}`}</code></pre>
82+
<p>What should be compared with maxSum?</p>
83+
<select required>
84+
<option value="">Choose the correct variable...</option>
85+
<option value="windowSum">windowSum</option>
86+
<option value="arr[right]">arr[right]</option>
87+
<option value="left">left</option>
88+
<option value="right">right</option>
89+
</select>
7390
<span className="feedback" />
7491
<div className="explanation">
7592
Sliding window maintains a subset of elements (the &quot;window&quot;) and efficiently updates the window state
76-
as it moves through the array. Instead of recalculating everything for each position, it adds new elements
77-
and removes old ones, achieving O(n) time complexity for problems that would otherwise be O(n²).
93+
as it moves through the array. We compare maxSum with windowSum to track the maximum sum found so far.
94+
This achieves O(n) time complexity by avoiding recalculation.
7895
</div>
7996
</div>
8097

@@ -148,15 +165,29 @@ export const combiningPatternsCheckpointChapter = {
148165
</div>
149166

150167
{/* Stacks and Queues */}
151-
<div className="question" data-answer="Stack uses LIFO (Last In, First Out), Queue uses FIFO (First In, First Out)">
168+
<div className="question" data-answer="pop,push,dequeue,enqueue">
152169
<p>
153-
<strong>Stacks & Queues:</strong> What is the key difference between stack and queue data structures?
170+
<strong>Stacks & Queues:</strong> Complete the stack and queue implementations:
154171
</p>
155-
<input type="text" required />
172+
<pre><code>{`class Stack {
173+
constructor() { this.items = []; }
174+
175+
_____() { return this.items.pop(); } // Remove from top
176+
_____(item) { this.items.push(item); } // Add to top
177+
}
178+
179+
class Queue {
180+
constructor() { this.items = []; }
181+
182+
_____() { return this.items.shift(); } // Remove from front
183+
_____(item) { this.items.push(item); } // Add to back
184+
}`}</code></pre>
185+
<p>Fill in the method names (comma-separated): <input type="text" placeholder="enqueue,pop,push,dequeue," required /></p>
156186
<span className="feedback" />
157187
<div className="explanation">
158-
Stacks follow LIFO (Last In, First Out) - the most recently added element is removed first, like a stack of plates.
159-
Queues follow FIFO (First In, First Out) - the first element added is the first removed, like a line of people waiting.
188+
Stacks follow LIFO (Last In, First Out) using pop() and push() methods.
189+
Queues follow FIFO (First In, First Out) using dequeue() and enqueue() methods.
190+
The correct answers are: pop, push, dequeue, enqueue.
160191
</div>
161192
</div>
162193

@@ -207,99 +238,135 @@ export const combiningPatternsCheckpointChapter = {
207238
</div>
208239

209240
{/* Pattern Recognition */}
210-
<div className="question" data-answer="Analyze the problem requirements and choose data structures that optimize for the most frequent operations">
241+
<div className="question" data-answer="Map,Set,Array,LinkedList">
211242
<p>
212-
<strong>Pattern Recognition:</strong> How do you choose the right data structure for a specific problem?
243+
<strong>Pattern Recognition:</strong> Choose the best data structure for each scenario:
213244
</p>
214-
<input type="text" required />
245+
<pre><code>{`// Fast key-value lookups
246+
const userCache = new _____([
247+
['user1', {name: 'Alice'}],
248+
['user2', {name: 'Bob'}]
249+
]);
250+
251+
// Unique items only
252+
const uniqueIds = new _____([1, 2, 2, 3, 3, 4]);
253+
254+
// Indexed access needed
255+
const temperatures = new _____([20, 22, 19, 25]);
256+
257+
// Frequent insertions/deletions from the front and back
258+
class _____ {
259+
constructor(data) {
260+
this.data = data;
261+
this.next = null;
262+
}
263+
}`}</code></pre>
264+
<p>Fill in the data structures (comma-separated): <input type="text" placeholder="LinkedList,Map,Set,Array" required /></p>
215265
<span className="feedback" />
216266
<div className="explanation">
217-
Choose data structures by analyzing the problem requirements: What operations will be performed most frequently?
218-
Do you need fast lookups (Maps), unique collections (Sets), ordered data (Arrays), or dynamic insertion/deletion (Linked Lists)?
219-
Optimize for your most common operations while considering trade-offs in time and space complexity.
267+
Choose data structures based on operations: Map for fast lookups, Set for uniqueness,
268+
Array for indexed access, LinkedList for dynamic insertion/deletion.
269+
The correct answers are: Map, Set, Array, LinkedList.
220270
</div>
221271
</div>
222272

223273
{/* Performance Trade-offs */}
224-
<div className="question" data-answer="time-space">
274+
<div className="question" data-answer="O(n)">
225275
<p>
226-
<strong>Performance Trade-offs:</strong> What is the most common trade-off in algorithm and data structure design?
276+
<strong>Performance Trade-offs:</strong> Complete this example of time vs space trade-off:
227277
</p>
228-
<label>
229-
<input type="radio" name="tradeoff" value="time-space" required />
230-
Time complexity vs. Space complexity (speed vs. memory usage)
231-
</label>
232-
<br />
233-
<label>
234-
<input type="radio" name="tradeoff" value="simplicity-performance" required />
235-
Code simplicity vs. Performance optimization
236-
</label>
237-
<br />
238-
<label>
239-
<input type="radio" name="tradeoff" value="read-write" required />
240-
Read performance vs. Write performance
241-
</label>
242-
<br />
243-
<label>
244-
<input type="radio" name="tradeoff" value="consistency-availability" required />
245-
Data consistency vs. System availability
246-
</label>
278+
<pre><code>{`
279+
function findDuplicates(arr) {
280+
const duplicates = [];
281+
for (let i = 0; i < arr.length; i++) {
282+
for (let j = i + 1; j < arr.length; j++) {
283+
if (arr[i] === arr[j] && !duplicates.includes(arr[i])) {
284+
duplicates.push(arr[i]);
285+
}
286+
}
287+
}
288+
return duplicates; // Time: O(n²), Space: _____
289+
}`}</code></pre>
290+
<p>What is the space complexity?</p>
291+
<select required>
292+
<option value="">Choose the correct complexity...</option>
293+
<option value="O(1)">O(1)</option>
294+
<option value="O(n)">O(n)</option>
295+
<option value="O(log n)">O(log n)</option>
296+
<option value="O(n²)">O(n²)</option>
297+
</select>
247298
<span className="feedback" />
248299
<div className="explanation">
249-
The most fundamental trade-off is time vs. space complexity - you can often make algorithms faster by using more memory
250-
(like caching or precomputed results) or save memory by accepting slower performance. Understanding this trade-off
251-
is crucial for making informed design decisions.
300+
This uses O(n) extra space but O(n²) time with nested loops.
252301
</div>
253302
</div>
254303

255-
{/* Climate AI Integration */}
256-
<div className="question" data-answer="Multiple specialized algorithms working together, each optimized for specific tasks">
257-
<p>
258-
<strong>System Integration:</strong> In the Global Cooling Intelligence Platform, what makes the system more powerful than using a single algorithm?
259-
</p>
260-
<input type="text" required />
304+
<div className="question" data-answer="Map">
305+
<pre><code>{`class CoolingIntelligencePlatform {
306+
constructor() {
307+
this.stationData = new _____(); // Fast station lookups
308+
this.temperatureWindow = []; // For sliding window analysis
309+
this.alertCache = new Map(); // Cache recent alerts
310+
}
311+
312+
processTemperatureStream(readings) {
313+
// 1. Fast lookup of station metadata
314+
const station = this.stationData.get(readings.stationId);
315+
316+
// 2. Sliding window for trend analysis
317+
this.updateWindow(readings.temperatures);
318+
319+
// 3. Sort for percentile calculations
320+
const sorted = [...readings.temperatures].sort();
321+
322+
// 4. Cache results to avoid recalculation
323+
this.alertCache.set(readings.stationId, this.analyzePattern(sorted));
324+
}
325+
}`}</code></pre>
326+
<p>What data structure should be used for fast station lookups?</p>
327+
<select required>
328+
<option value="">Choose the best data structure...</option>
329+
<option value="Map">Map</option>
330+
<option value="Array">Array</option>
331+
<option value="Set">Set</option>
332+
<option value="LinkedList">LinkedList</option>
333+
</select>
261334
<span className="feedback" />
262335
<div className="explanation">
263-
Complex systems like GCIP use multiple specialized algorithms working together - sliding windows for real-time cooling analysis,
264-
hash tables for fast lookups, sorting for data organization, pattern recognition for cooling anomaly detection, and caching for performance.
265-
Each algorithm is optimized for its specific role, creating a system more powerful than any single approach.
336+
Complex systems combine multiple specialized algorithms: Map for fast O(1) lookups, sliding window for real-time analysis,
337+
sorting for data organization, and caching for performance. Each algorithm is optimized for its specific role.
266338
</div>
267339
</div>
268340

269341
{/* Real-world Impact */}
270-
<div className="question" data-answers="Faster cooling predictions save lives,Better algorithms enable more accurate models,Efficient systems can process more data,Optimized performance supports global scale">
342+
<div className="question" data-answer="divide-conquer">
271343
<p>
272-
<strong>Real-world Impact:</strong> How do data structures and algorithms contribute to addressing global cooling challenges?
344+
<strong>Real-world Impact:</strong> Why is the optimal time complexity for comparison-based sorting O(n log n)?
273345
</p>
274346
<label>
275-
<input type="checkbox" value="Faster cooling predictions save lives" />
276-
⚡ Faster cooling predictions enable earlier cold weather warnings and save lives
277-
</label>
278-
<br />
279-
<label>
280-
<input type="checkbox" value="Better algorithms enable more accurate models" />
281-
🎯 Better algorithms enable more accurate cooling models and predictions
347+
<input type="radio" name="sort-complexity" value="divide-conquer" required />
348+
Divide-and-conquer algorithms split the problem into smaller subproblems, leading to O(n log n)
282349
</label>
283350
<br />
284351
<label>
285-
<input type="checkbox" value="Efficient systems can process more data" />
286-
📊 Efficient systems can process more sensor data for comprehensive cooling monitoring
352+
<input type="radio" name="sort-complexity" value="nested-loops" required />
353+
Sorting requires nested loops, which always results in O(n log n) complexity
287354
</label>
288355
<br />
289356
<label>
290-
<input type="checkbox" value="Optimized performance supports global scale" />
291-
🌍 Optimized performance supports global-scale cooling monitoring systems
357+
<input type="radio" name="sort-complexity" value="memory-limitation" required />
358+
Memory limitations prevent faster sorting algorithms from being implemented
292359
</label>
293360
<br />
294361
<label>
295-
<input type="checkbox" value="Algorithms automatically solve global cooling" />
296-
🤖 Algorithms automatically solve global cooling without human intervention
362+
<input type="radio" name="sort-complexity" value="comparison-limit" required />
363+
The number of comparisons needed is limited by the hardware architecture
297364
</label>
298-
<div className="feedback"></div>
365+
<span className="feedback" />
299366
<div className="explanation">
300-
Data structures and algorithms are tools that amplify human efforts to address global cooling challenges. They enable faster,
301-
more accurate predictions, support processing of massive datasets, and allow global-scale monitoring systems.
302-
However, they are tools that support human decision-making rather than automatically solving complex problems.
367+
Efficient comparison-based sorting algorithms like merge sort and heap sort use divide-and-conquer strategies.
368+
They recursively split the problem into smaller subproblems (log n levels) and process each level in O(n) time,
369+
resulting in O(n log n) total complexity. This is mathematically proven to be optimal for comparison-based sorting.
303370
</div>
304371
</div>
305372

src/chapters/combining-patterns/combine-patterns-four.jsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { TestResult } from "../../utils/test_utils";
22

33
export const combinePatternsFour = {
44
id: 'combine-patterns-four',
5-
title: 'Survival Data Detective — First Unsafe Ice (Binary Search)',
5+
title: 'Survival Data Detective',
66
sectionId: 'combining-patterns',
77
previousChapterId: 'combine-patterns-three',
88
content: `
@@ -87,8 +87,7 @@ function findFirstBelowThreshold(thicknesses, minSafe) {
8787
`,
8888
exercise: {
8989
starterCode: `
90-
// export so tests can access it
91-
export function findFirstBelowThreshold(thicknesses, minSafe) {
90+
function findFirstBelowThreshold(thicknesses, minSafe) {
9291
// Binary search for the first index where thickness < minSafe
9392
let lo = 0, hi = thicknesses.length - 1;
9493
let ans = -1;
@@ -99,7 +98,7 @@ export function findFirstBelowThreshold(thicknesses, minSafe) {
9998
`,
10099
solution: `
101100
// Reference Solution
102-
export function findFirstBelowThreshold(thicknesses, minSafe) {
101+
function findFirstBelowThreshold(thicknesses, minSafe) {
103102
let lo = 0, hi = thicknesses.length - 1;
104103
let ans = -1;
105104
@@ -121,15 +120,15 @@ export function findFirstBelowThreshold(thicknesses, minSafe) {
121120
test: (code) => {
122121
try {
123122
const testCode = code + `
124-
const a = findFirstBelowThreshold([12,11,9,9,7,7,4,2], 8); // first <8 is idx 6 (4)
123+
const a = findFirstBelowThreshold([12,11,9,9,7,7,4,2], 8); // first <8 is idx 4 (7)
125124
const b = findFirstBelowThreshold([10,9,9,8,8,8,8], 8); // first <8 is -1 (none)
126125
const c = findFirstBelowThreshold([9,7,7,7,6], 7.5); // first <7.5 is idx 1 (7)
127126
const d = findFirstBelowThreshold([], 5); // -1
128127
return { a, b, c, d };
129128
`;
130129
const { a, b, c, d } = new Function(testCode)();
131130

132-
if (a !== 6) return new TestResult({ passed: false, message: "Case a should be index 6" });
131+
if (a !== 4) return new TestResult({ passed: false, message: "Case a should be index 4" });
133132
if (b !== -1) return new TestResult({ passed: false, message: "Case b should be -1 (none unsafe)" });
134133
if (c !== 1) return new TestResult({ passed: false, message: "Case c should be index 1" });
135134
if (d !== -1) return new TestResult({ passed: false, message: "Case d should be -1 for empty input" });

0 commit comments

Comments
 (0)