W3Week 3 of 4

Code Explanation

Explain unfamiliar programs in plain language. Read minds through their code.

The skill: Collaborative posture. Code is communication between minds. Reading it well means hearing what another mind was thinking.

Time: 5-6 hours total

This week uses: Variables · if/else · for loop · for...of · Arrays [] · Objects {} · obj.property · .push() · for...in

Covered in Lesson 2 & Lesson 3. If any feel unfamiliar, review before continuing.

Your progress0 / 15 complete

Estimated time remaining: 5-6 hours

The Format

  1. 1. Read the code cold (no explanation given)
  2. 2. Answer structured questions: WHAT, HOW, WHY
  3. 3. Explain to a collaborator — as if another mind asked "what does this do?"
  4. 4. Compare to model explanation
  5. 5. Reflect — what did you miss? What did you see that the model didn't?

The explanation is the artifact. If you can explain it, you understand it.

Exercise 3.1: Simple Functions

Functions have a purpose. Identify it from the code, not from the name.

1Exercise 3.1.1

The Counter

1 / 15
javascript
1function mystery(arr) {
2 let count = 0;
3 for (let i = 0; i < arr.length; i++) {
4 if (arr[i] > 0) {
5 count++;
6 }
7 }
8 return count;
9}

Read the code, then explain it. If you can explain it, you understand it.

2Exercise 3.1.2

The Transformer

2 / 15
javascript
1function process(text) {
2 let result = "";
3 for (let i = 0; i < text.length; i++) {
4 let char = text[i];
5 if (char === char.toUpperCase()) {
6 result += char.toLowerCase();
7 } else {
8 result += char.toUpperCase();
9 }
10 }
11 return result;
12}

Read the code, then explain it. If you can explain it, you understand it.

3Exercise 3.1.3

The Finder

3 / 15
javascript
1function locate(haystack, needle) {
2 for (let i = 0; i < haystack.length; i++) {
3 if (haystack[i] === needle) {
4 return i;
5 }
6 }
7 return -1;
8}

Read the code, then explain it. If you can explain it, you understand it.

Why -1? Returning -1 for "not found" is convention, not necessity. Some languages return null, others throw exceptions. Each choice has tradeoffs: -1 requires callers to check, null can propagate silently, exceptions force handling. JavaScript chose -1.

Exercise 3.2: Array Manipulation

Arrays are everywhere. Recognize common patterns: filter, transform, reduce, search.

4Exercise 3.2.1

The Filter

4 / 15
javascript
1function extract(items, threshold) {
2 let result = [];
3 for (let item of items) {
4 if (item >= threshold) {
5 result.push(item);
6 }
7 }
8 return result;
9}

Read the code, then explain it. If you can explain it, you understand it.

5Exercise 3.2.2

The Reverser

5 / 15
javascript
1function flip(arr) {
2 let result = [];
3 for (let i = arr.length - 1; i >= 0; i--) {
4 result.push(arr[i]);
5 }
6 return result;
7}

Read the code, then explain it. If you can explain it, you understand it.

6Exercise 3.2.3

The Deduplicator

6 / 15
javascript
1function unique(arr) {
2 let seen = [];
3 let result = [];
4
5 for (let item of arr) {
6 if (!seen.includes(item)) {
7 seen.push(item);
8 result.push(item);
9 }
10 }
11
12 return result;
13}

Read the code, then explain it. If you can explain it, you understand it.

Two arrays, two purposes: 'seen' is working memory — the machine's scratchpad for tracking state. 'result' is output — what the caller asked for. Separating internal state from external interface is a core principle: callers don't need to know how you computed the answer.

Exercise 3.3: Object Handling

Objects store related data together. Keys are names, values are data.

7Exercise 3.3.1

The Lookup

7 / 15
javascript
1function getValue(obj, key, fallback) {
2 if (obj[key] !== undefined) {
3 return obj[key];
4 }
5 return fallback;
6}

Read the code, then explain it. If you can explain it, you understand it.

8Exercise 3.3.2

The Counter Object

8 / 15
javascript
1function tally(words) {
2 let counts = {};
3
4 for (let word of words) {
5 if (counts[word] === undefined) {
6 counts[word] = 0;
7 }
8 counts[word]++;
9 }
10
11 return counts;
12}

Read the code, then explain it. If you can explain it, you understand it.

9Exercise 3.3.3

The Merger

9 / 15
javascript
1function combine(obj1, obj2) {
2 let result = {};
3
4 for (let key in obj1) {
5 result[key] = obj1[key];
6 }
7
8 for (let key in obj2) {
9 result[key] = obj2[key];
10 }
11
12 return result;
13}

Read the code, then explain it. If you can explain it, you understand it.

Priority through order: The second object wins conflicts because it's processed second. This isn't magic — it's just assignment. If you write result['x'] = 1 then result['x'] = 2, you get 2. Order is meaning.

Exercise 3.4: Combined Patterns

Real code combines multiple concepts. Recognize compound patterns.

10Exercise 3.4.1

The Summarizer

10 / 15
javascript
1function summarize(transactions) {
2 let total = 0;
3 let count = 0;
4
5 for (let t of transactions) {
6 if (t.amount > 0) {
7 total += t.amount;
8 count++;
9 }
10 }
11
12 return {
13 total: total,
14 count: count,
15 average: count > 0 ? total / count : 0
16 };
17}

Read the code, then explain it. If you can explain it, you understand it.

11Exercise 3.4.2

The Grouper

11 / 15
javascript
1function groupBy(items, key) {
2 let groups = {};
3
4 for (let item of items) {
5 let groupKey = item[key];
6
7 if (groups[groupKey] === undefined) {
8 groups[groupKey] = [];
9 }
10
11 groups[groupKey].push(item);
12 }
13
14 return groups;
15}

Read the code, then explain it. If you can explain it, you understand it.

12Exercise 3.4.3

The Validator

12 / 15
javascript
1function validate(user) {
2 let errors = [];
3
4 if (!user.email || !user.email.includes("@")) {
5 errors.push("Invalid email");
6 }
7
8 if (!user.password || user.password.length < 8) {
9 errors.push("Password must be at least 8 characters");
10 }
11
12 if (!user.age || user.age < 18) {
13 errors.push("Must be 18 or older");
14 }
15
16 return {
17 valid: errors.length === 0,
18 errors: errors
19 };
20}

Read the code, then explain it. If you can explain it, you understand it.

The validation gap: includes("@") accepts "@" as a valid email. Length >= 8 accepts "aaaaaaaa" as a password. Real validation uses regex patterns, checks against known bad passwords, and often involves external services. This code shows the structure, not production rules.

Exercise 3.5: Real-World-ish Programs

Longer code requires patience. Break it into parts. Trace the flow.

13Exercise 3.5.1

The Todo Filter

13 / 15

New syntax: arr.sort((a, b) => a - b) — sorts an array using a comparator function. Return negative to put a first, positive for b first, zero for equal.

javascript
1function getActiveTodos(todos) {
2 let active = [];
3
4 for (let todo of todos) {
5 if (!todo.completed) {
6 active.push({
7 id: todo.id,
8 text: todo.text,
9 priority: todo.priority || "normal"
10 });
11 }
12 }
13
14 active.sort(function(a, b) {
15 let priorityOrder = { high: 0, normal: 1, low: 2 };
16 return priorityOrder[a.priority] - priorityOrder[b.priority];
17 });
18
19 return active;
20}

Read the code, then explain it. If you can explain it, you understand it.

14Exercise 3.5.2

The Price Calculator

14 / 15
javascript
1function calculateTotal(cart, discountCode) {
2 let subtotal = 0;
3
4 for (let item of cart) {
5 subtotal += item.price * item.quantity;
6 }
7
8 let discount = 0;
9 if (discountCode === "SAVE10") {
10 discount = subtotal * 0.10;
11 } else if (discountCode === "SAVE20" && subtotal >= 100) {
12 discount = subtotal * 0.20;
13 }
14
15 let total = subtotal - discount;
16 let tax = total * 0.08;
17
18 return {
19 subtotal: subtotal,
20 discount: discount,
21 tax: tax,
22 total: total + tax
23 };
24}

Read the code, then explain it. If you can explain it, you understand it.

15Exercise 3.5.3

The Search Ranker

15 / 15

New syntax: arr.map(fn) — transforms each element using fn, returns a new array. Like a loop that builds a new array of transformed values.

javascript
1function search(items, query) {
2 let results = [];
3
4 let queryLower = query.toLowerCase();
5
6 for (let item of items) {
7 let titleLower = item.title.toLowerCase();
8 let score = 0;
9
10 if (titleLower === queryLower) {
11 score = 100;
12 } else if (titleLower.startsWith(queryLower)) {
13 score = 75;
14 } else if (titleLower.includes(queryLower)) {
15 score = 50;
16 }
17
18 if (score > 0) {
19 results.push({
20 item: item,
21 score: score
22 });
23 }
24 }
25
26 results.sort(function(a, b) {
27 return b.score - a.score;
28 });
29
30 return results.map(function(r) {
31 return r.item;
32 });
33}

Read the code, then explain it. If you can explain it, you understand it.

Scores encode assumptions: Why 100/75/50? Those specific numbers don't matter — only their order does. You could use 3/2/1. The designer assumed exact > prefix > substring. Different domains might weight differently: autocomplete favors prefixes, document search might favor frequency.