factorial(n) — base case: if n is 0 or 1, return 1. Recursive case: return n * factorial(n-1)factorial(4) → 4 × factorial(3) → 4 × 3 × factorial(2) → ... what's the final answer?count_ways(n) — base cases: n==0 or n==1 → return 1. Recursive: return count_ways(n-1) + count_ways(n-2)
Think: to reach step N, you came from step N-1 (took 1 step) OR step N-2 (took 2 steps)
count_ways, try n=3 by hand: ways(3) = ways(2) + ways(1) = (ways(1)+ways(0)) + 1 = (1+1) + 1 = 3. The pattern is identical to Fibonacci — each answer is the sum of the previous two!
sorted() and lambda functions as the sort key. Lambda is just a tiny throwaway function written in one line.
lambda m: m["rating"] is the same as writing def key(m): return m["rating"] — just shorter. reverse=True flips the order from low→high to high→low. For Task ④: [m["title"] for m in movies if m["rating"] > 8.5]
filter() to get only items that are in stock
filter(lambda p: p["in_stock"], cart) — wrap in list() to see the result
map() to apply a 10% discount to all in-stock prices
map(lambda p: p["price"] * 0.9, in_stock_items)
filter() and map() return lazy iterators — wrap them in list() to get a real list you can index or loop over. For Task ④, use max(in_stock, key=lambda p: p["price"]) on the original filtered list (before discount), then show the discounted price.
sorted() is great but how does sorting actually work? Bubble Sort is the simplest algorithm to understand: compare neighbouring elements, swap if the left one is bigger, and repeat. After each full pass, the largest unsorted element "bubbles up" to the end — like air bubbles rising in water.
arr[j] > arr[j+1], swap them
Python swap: arr[j], arr[j+1] = arr[j+1], arr[j] — no temp variable needed!
nums and scores — verify the output is sorted[1, 2, 3, 4, 5] — how many swaps does it make?n - i - 1 because after each outer pass, the last i elements are already sorted in place. No need to re-check them! This is what makes Bubble Sort slightly smarter than checking every pair every time.
Book class — constructor, borrow(), return_book(), and __str__ (which controls what print(book) shows)Library.add_book() and Library.search(keyword)
Search hint: keyword.lower() in book.title.lower() or keyword.lower() in book.author.lower()
__str__ is a special method — when you do print(book), Python automatically calls it. Inside it, use an f-string like: f"{self.title} ({self.author}, {self.year}) [{'Borrowed' if self.is_borrowed else 'Available'}]"
factorial(n) — base: if (n <= 1) return 1; recursive: return n * factorial(n-1);factorial(4) evaluate to step-by-step?countWays(n) — base: n==0 or n==1 → return 1. Recursive: return the sum of two callsif (n <= 1) return 1; — this handles both n==0 and n==1 with one line. Then: return countWays(n-1) + countWays(n-2);
if(a, b) -> ... returns a negative number if a comes first, positive if b comes first, zero if equal. Double.compare(b, a) automatically gives highest-first order. a[0].compareTo(b[0]) gives alphabetical order for Strings.
double discounted = Integer.parseInt(p[1]) * 0.9; for the discount. Track the max with a variable — same "update if bigger" pattern from Q1 of Day 1. For the total, add each discounted price to a running double total = 0;.
Collections.sort() is great but how does sorting actually work underneath? Bubble Sort is the most visual algorithm: compare two neighbouring elements, swap if needed, and repeat. After every full pass, the largest unsorted element "bubbles up" to its final position — just like air bubbles rising in water.
{1, 2, 3, 4, 5} — how many swaps does it make?a, b = b, a), Java needs a temp: int t = arr[j]; arr[j] = arr[j+1]; arr[j+1] = t;. This is because Java is strict — you can't assign to two variables simultaneously.
ArrayList<Book>. This is the standard Java pattern: one class models the data, another manages a collection of it — the same structure used in enterprise Java apps.
Book constructor, borrow(), returnBook(), and toString()Library.addBook(), search(), and availableBooks()
Search: book.title.toLowerCase().contains(keyword.toLowerCase())
main(): create a library, add 3 books, borrow one, print available bookstoString() works like Python's __str__ — when you call System.out.println(book), Java automatically calls book.toString(). Use the ternary operator for the status: isBorrowed ? "Borrowed" : "Available"
function name(){}, const name = () => {}, or even inline. Recursion works identically — the key concepts (base case, recursive case) are universal across all languages.
console.log() instead of print/println.let, const, or nothing.const factorial = (n) => { ... }
factorial(n) — same logic as Python/Java but JS syntaxcountWays(n) — base: if (n <= 1) return 1; recursive: sum of two callsfactorial as an arrow function: const factorial = (n) => { ... }const factorial = n => n <= 1 ? 1 : n * factorial(n-1);
The ternary operator ? : replaces if/else in one line
undefined is returned if your function has no return statement. Make sure BOTH the base case and the recursive case have explicit return. A common mistake: if (n <= 1) { 1; } — missing return!
.sort(), .filter(), and .map() — and they all take arrow functions as arguments. This is the most natural and common way to work with data in JS. Almost every real web app — Netflix, Spotify, IMDb — does exactly this kind of data manipulation.
a.year - b.yeara.title.localeCompare(b.title).filter() to get movies with rating > 8.5, then .map() to extract just their titles
Chain them: movies.filter(...).map(m => m.title)
.sort() mutates the original array — always copy first with the spread operator: [...movies].sort(...). Subtracting numbers in the comparator (b.rating - a.rating) is the JS idiom for numeric sort — positive means b comes first, negative means a comes first.
.filter(), .map(), .reduce() — are the backbone of frontend data processing. You'll use all three together in a method chain: filter out-of-stock items, map prices with a discount, then reduce to a total. This is exactly how modern React and Vue apps process data.
array.reduce((total, item) => total + item, 0).filter() to keep only in-stock items, log their names.map() on in-stock items to apply a 10% discount — return a new object with updated price
p => ({ ...p, price: p.price * 0.9 }) — the spread ...p copies all properties
.reduce() on discounted items to get the total bill.reduce()
(max, item) => item.price > max.price ? item : max
const discounted = cart.filter(p => p.inStock).map(p => ({...p, price: p.price * 0.9})); — then use .reduce() on discounted. The ({...p, price: ...}) syntax creates a NEW object with all old properties plus an updated price — original cart is untouched.
document.getElementById() grabs an element, .innerHTML changes its content. This is how Notion, Trello, and every interactive website works.
document.getElementById("myId") → grab an elementelement.innerHTML += "<li>text</li>" → add HTML inside itbutton.addEventListener("click", fn) → run fn when button clickedinput.value → get what the user typed
addTask(): get the input value, push it to the tasks array, clear the input, call renderTasks()
Guard: if the input is empty (after .trim()), do nothing
renderTasks(): loop through tasks, build a string of <li> elements, set it as taskList.innerHTMLdocument.getElementById("counter").textContent = "Tasks: " + tasks.length<li> — clicking it removes that task from the array and re-renders
Use tasks.splice(index, 1) to remove by index, then call renderTasks()
`<li>${task} <button onclick="deleteTask(${i})">✕</button></li>` and define function deleteTask(i) { tasks.splice(i, 1); renderTasks(); }. Template literals (backticks) let you embed variables with ${}.
class Name {} like Java, constructor() instead of __init__, and this like Java. JS classes are the backbone of every modern framework — React components are classes under the hood.
Book class — constructor, borrow(), returnBook(), toString()Library — addBook(), search(keyword) using .filter(), availableBooks() using .filter()
search: this.books.filter(b => b.title.toLowerCase().includes(keyword.toLowerCase()) || ...)
toString() is called automatically by console.log(book) ONLY if you call it explicitly: console.log(book.toString()). Otherwise console.log shows the object structure. Use template literals for clean output: `${this.title} (${this.author}, ${this.year}) [${this.isBorrowed ? 'Borrowed' : 'Available'}]`