Structured Bottom Up - kevshouse/exam_quest GitHub Wiki
Continuing our structured revision plan, let's build upon the helper functions and implement the remaining assignments. I'll provide strategies and code templates that reuse helpers where possible, avoiding malloc and adhering to allowed functions.
Additional Helper Functions Implement these to support more complex assignments:
ft_putnbr (Number Printing)
Purpose: Output integers for fizzbuzz without printf
Allowed: write
Strategy:
void ft_putnbr(int n) {
if (n >= 10) ft_putnbr(n / 10);
char digit = '0' + (n % 10);
write(1, &digit, 1);
}
char_to_upper/lower (Case Conversion)
Purpose: Simplify ulstr logic
Strategy:
char char_to_upper(char c) {
return ('a' <= c && c <= 'z') ? c - 32 : c;
}
char char_to_lower(char c) {
return ('A' <= c && c <= 'Z') ? c + 32 : c;
}
Step 5: Remaining Assignments
- search_and_replace Helpers: Direct character replacement
Logic:
int main(int ac, char **av) {
if (ac != 4 || av[2][1] || av[3][1]) { // Verify single-char args
write(1, "\n", 1); return 0;
}
char find = av[2][0];
char replace = av[3][0];
for (int i = 0; av[1][i]; i++) {
char c = (av[1][i] == find) ? replace : av[1][i];
write(1, &c, 1);
}
write(1, "\n", 1);
}
- rot_13 (ROT13 Cipher) Helpers: char_rot13 from earlier
Logic:
int main(int ac, char **av) {
if (ac != 2) { write(1, "\n", 1); return 0; }
for (int i = 0; av[1][i]; i++) {
char c = char_rot13(av[1][i]);
write(1, &c, 1);
}
write(1, "\n", 1);
}
- ulstr (Case Reversal) Helpers: char_to_upper, char_to_lower
Optimization: Single pass with ternary logic
Logic:
int main(int ac, char **av) {
if (ac != 2) { write(1, "\n", 1); return 0; }
for (int i = 0; av[1][i]; i++) {
char c = av[1][i];
if ('a' <= c && c <= 'z') c = char_to_upper(c);
else if ('A' <= c && c <= 'Z') c = char_to_lower(c);
write(1, &c, 1);
}
write(1, "\n", 1);
}
Step 6: Edge Case Testing Plan Test each assignment with these scenarios:
Assignment Test Cases first_word "", " ", " single ", "\tmultiple\twords", "!@#" fizzbuzz Numbers 1, 3, 5, 15, 100; Verify "fizz", "buzz", "fizzbuzz" transitions repeat_alpha "", "a", "A", "ab!", "z", "Hello!" rev_print "", "a", "abc", " space ", "😊" (multi-byte chars) rotone/rot_13 "", "z", "Z", "a b", "Hello123!" search_replace "./prog" (no args), "./prog str" (2 args), "./prog str x y" (4 args) ulstr "", "aBc", "!@#", "MixED" Step 7: Optimization Strategies Loop Fusion: Combine operations in single passes Example: In ulstr, convert case while writing instead of separate steps
// Instead of:
// convert_case(buffer); then write(buffer);
// Do:
for (i=0; str[i]; i++) {
c = convert_and_output(str[i]); // Immediate write
}
Branch Reduction: Minimize conditionals in hot paths For fizzbuzz:
for (int i = 1; i <= 100; i++) {
int m3 = (i % 3 == 0);
int m5 = (i % 5 == 0);
if (m3 && m5) ft_putstr("fizzbuzz");
else if (m3) ft_putstr("fizz");
else if (m5) ft_putstr("buzz");
else ft_putnbr(i);
write(1, "\n", 1);
}
Stack Allocation Only: Never use heap memory
// GOOD: char buffer[100]; (if bounded)
// BAD: malloc(sizeof(char) * (len + 1));
Pointer Arithmetic: Faster than indexing
// In rev_print:
char *end = str;
while (*end) end++; // Find string end
while (end-- > str) write(1, end, 1); // Reverse output
Step 8: Revision Workflow Daily Practice:
Morning: Reimplement 2 core helpers from memory
Afternoon: Build 1 complex assignment using helpers
Evening: Test edge cases and compare with exam examples
Progression Path:
Diagram
graph TD
A[Core Helpers] --> B[ft_putstr/ft_strlen]
A --> C[ft_swap/ft_strcpy]
A --> D[char_rotone/rot13]
B --> E[first_word/rev_print]
C --> F[search_replace]
D --> G[rotone/rot_13]
E --> H[repeat_alpha/ulstr]
D --> I[fizzbuzz]
Speed Drills:
-
Time yourself implementing:
-
Basic helpers: ≤ 5 minutes each
-
Simple assignments: ≤ 15 minutes
-
Complex assignments: ≤ 25 minutes
-
Gradually reduce time targets by 20% each week
Key Insights
-
Pattern Recognition: Most string problems follow similar patterns:
-
Skip delimiters → Process token → Handle edges
-
Transform character → Output result
-
Validate input → Process data → Format output
-
Avoid Over-Engineering:
-
For Level 0, direct solutions are better than abstracted ones
-
Example: first_word doesn't need strtok-style tokenization
42 Exam Constraints:
-
Zero heap allocation
-
Minimal external dependencies
-
Strict output formatting
-
No error messages beyond newlines
This approach builds muscle memory for fundamental operations while teaching you to compose solutions from reliable components. The helper functions become your "standard library" for exam problems.