Exercism - House
This post shows you how to get House exercise of Exercism.
Preparation
Before we click on our next exercise, let’s see what concepts of DART we need to consider

So we need to use the following concepts.
Lists
Lists are ordered collections of items. You can access elements by index, iterate over them, and perform various operations.
void main() {
List<String> items = ['house', 'malt', 'rat'];
// Access by index
print(items[0]); // 'house'
// Iterate over list
for (var item in items) {
print(item);
}
// Reverse iteration
for (int i = items.length - 1; i >= 0; i--) {
print(items[i]);
}
}
List.generate
The List.generate method creates a list of a specified length by calling a function for each index. It’s useful for creating lists dynamically.
void main() {
// Generate list of numbers
List<int> numbers = List.generate(5, (i) => i * 2);
print(numbers); // [0, 2, 4, 6, 8]
// Generate list of strings
List<String> verses = List.generate(3, (i) => 'Verse ${i + 1}');
print(verses); // [Verse 1, Verse 2, Verse 3]
// Generate with calculations
List<int> squares = List.generate(4, (i) => (i + 1) * (i + 1));
print(squares); // [1, 4, 9, 16]
}
String Joining
The join method combines all elements of a list into a single string, with an optional separator between elements.
void main() {
List<String> words = ['This', 'is', 'the', 'house'];
// Join with space
String sentence = words.join(' ');
print(sentence); // "This is the house"
// Join with newline
List<String> lines = ['Line 1', 'Line 2', 'Line 3'];
String text = lines.join('\n');
print(text);
// Line 1
// Line 2
// Line 3
// Join without separator
String combined = words.join('');
print(combined); // "Thisisthehouse"
}
For Loops with Decrement
You can use for loops to iterate backwards through a list by decrementing the index.
void main() {
List<String> items = ['a', 'b', 'c', 'd'];
// Iterate backwards
for (int i = items.length - 1; i >= 0; i--) {
print(items[i]); // d, c, b, a
}
// Iterate from specific index down to 0
int start = 2;
for (int j = start; j >= 0; j--) {
print(items[j]); // c, b, a
}
}
String Interpolation
String interpolation allows you to embed expressions inside strings using ${expression} or $variable for simple variable names.
void main() {
String subject = 'house';
String action = 'built';
// Simple interpolation
String sentence1 = 'This is the $subject';
print(sentence1); // "This is the house"
// Expression interpolation
String sentence2 = 'This is ${subject} that Jack ${action}';
print(sentence2); // "This is house that Jack built"
// With expressions
int count = 3;
String message = 'There are ${count + 1} items';
print(message); // "There are 4 items"
}
Final Variables
The final keyword declares a variable that can only be assigned once. For lists, this means the list reference is constant, but the contents can still be modified (unless it’s a const list).
void main() {
// Final list - reference cannot change, but contents can
final List<String> items = ['a', 'b', 'c'];
items.add('d'); // OK - modifying contents
// items = ['x', 'y']; // Error - cannot reassign
// Const list - both reference and contents are constant
const List<String> constant = ['a', 'b', 'c'];
// constant.add('d'); // Error - cannot modify
}
Conditional Logic in Loops
You can use conditional statements inside loops to handle different cases based on the current iteration.
void main() {
List<String> items = ['first', 'second', 'third'];
for (int i = 0; i < items.length; i++) {
if (i == 0) {
print('Start: ${items[i]}');
} else {
print('Next: ${items[i]}');
}
}
// Output:
// Start: first
// Next: second
// Next: third
}
Introduction
Recite the nursery rhyme ‘This is the House that Jack Built’.
The process of placing a phrase or clause within another phrase or clause is called embedding. It is through the processes of recursion and embedding that we are able to take a finite number of forms (words and phrases) and construct an infinite number of expressions. Furthermore, embedding also allows us to construct an infinitely long structure, in theory anyway.
Instructions
The nursery rhyme follows a recursive pattern where each verse builds upon the previous one by adding a new subject and action. Each verse starts with “This is” followed by a subject, then chains together all previous subjects with their corresponding actions.
The structure follows this pattern:
- Verse 1: “This is the house that Jack built.”
- Verse 2: “This is the malt that lay in the house that Jack built.”
- Verse 3: “This is the rat that ate the malt that lay in the house that Jack built.”
And so on, with each verse adding a new subject and action to the chain.
What is “This is the House that Jack Built”?
“This is the House that Jack Built” is a cumulative nursery rhyme. It is a classic example of recursive structure in language, where each verse adds a new element while repeating all previous elements. The rhyme demonstrates how language can create complex, nested structures from simple components.
The rhyme has been used in linguistics to illustrate concepts of recursion and embedding in natural language.
— Nursery Rhymes & Linguistics
How does the recursive structure work?
To generate a verse:
- Start with “This is” followed by the subject for that verse
- For each previous subject (in reverse order), add the corresponding action followed by the subject
- Continue until you reach the first subject (“the house that Jack built”)
- Join all parts together with spaces
For example, verse 3:
- Start: “This is the rat”
- Previous subjects in reverse:
- Verse 2: “that ate the malt”
- Verse 1: “that lay in the house that Jack built”
- Result: “This is the rat that ate the malt that lay in the house that Jack built.”
Solution
class House {
final _subjects = [
'the house that Jack built.',
'the malt',
'the rat',
'the cat',
'the dog',
'the cow with the crumpled horn',
'the maiden all forlorn',
'the man all tattered and torn',
'the priest all shaven and shorn',
'the rooster that crowed in the morn',
'the farmer sowing his corn',
'the horse and the hound and the horn',
];
final _actions = [
'',
'that lay in',
'that ate',
'that killed',
'that worried',
'that tossed',
'that milked',
'that kissed',
'that married',
'that woke',
'that kept',
'that belonged to',
];
String recite(int startVerse, int endVerse) {
return List.generate(endVerse - startVerse + 1, (i) {
final verseNum = startVerse + i - 1;
final lines = <String>[];
for (int j = verseNum; j >= 0; j--) {
if (j == verseNum) {
lines.add('This is ${_subjects[j]}');
} else {
lines.add('${_actions[j + 1]} ${_subjects[j]}');
}
}
return lines.join(' ');
}).join('\n');
}
}
Let’s break down the solution:
-
final _subjects- A list containing all 12 subjects in order, from “the house that Jack built” to “the horse and the hound and the horn” -
final _actions- A list containing all 12 actions corresponding to each subject. The first action is an empty string since the first verse doesn’t have a connecting action before “the house that Jack built” -
String recite(int startVerse, int endVerse)- Generates verses fromstartVersetoendVerse:- Uses
List.generateto create a list of verses - For each verse index
i, calculates the actual verse number:verseNum = startVerse + i - 1 - Creates an empty list
linesto store the parts of the verse
- Uses
-
Verse generation loop - Iterates backwards from
verseNumdown to 0:- If
j == verseNum: This is the first line, so add “This is” followed by the subject - Otherwise: Add the action (at index
j + 1) followed by the subject (at indexj) - The reverse iteration ensures we build the chain from the newest subject back to the house
- If
-
Joining - Joins all lines with spaces to form the complete verse, then joins all verses with newlines to return the final result
The solution elegantly handles the recursive structure by iterating backwards through the subjects and actions, building each verse from the newest element back to the original house.
A video tutorial for this exercise is coming soon! In the meantime, check out my YouTube channel for more Dart and Flutter tutorials. 😉
Visit My YouTube Channel