Exercism - Proverb
This post shows you how to get Proverb 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.
List.generate
The List.generate method creates a list of a specified length by calling a function for each index. It’s perfect for creating lists dynamically based on calculations.
void main() {
// Generate list of strings
List<String> items = List.generate(3, (i) => 'Item ${i + 1}');
print(items); // [Item 1, Item 2, Item 3]
// Generate with calculations using adjacent elements
List<String> pairs = ['a', 'b', 'c'];
List<String> combined = List.generate(
pairs.length - 1,
(i) => '${pairs[i]} and ${pairs[i + 1]}'
);
print(combined); // [a and b, b and c]
}
Spread Operator
The spread operator (...) allows you to expand a list into individual elements. This is useful for combining multiple lists or adding elements to a list.
void main() {
List<String> list1 = ['a', 'b'];
List<String> list2 = ['c', 'd'];
// Combine lists using spread
List<String> combined = [...list1, ...list2];
print(combined); // [a, b, c, d]
// Add elements to existing list
List<String> result = [
...List.generate(2, (i) => 'Item $i'),
'Final item'
];
print(result); // [Item 0, Item 1, Final item]
}
String Interpolation
String interpolation allows you to embed expressions inside strings using ${expression} or $variable for simple variable names.
void main() {
String item1 = 'nail';
String item2 = 'shoe';
// Simple interpolation
String sentence = 'For want of a $item1 the $item2 was lost.';
print(sentence); // "For want of a nail the shoe was lost."
// Expression interpolation
int index = 0;
String message = 'Item at index ${index + 1}';
print(message); // "Item at index 1"
}
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> lines = [
'Line 1',
'Line 2',
'Line 3'
];
// Join with newline
String text = lines.join('\n');
print(text);
// Line 1
// Line 2
// Line 3
// Join with space
String sentence = lines.join(' ');
print(sentence); // "Line 1 Line 2 Line 3"
}
List Indexing
You can access list elements by their index. Be careful to check bounds to avoid index out of range errors.
void main() {
List<String> items = ['nail', 'shoe', 'horse'];
// Access by index
print(items[0]); // 'nail'
print(items[1]); // 'shoe'
// Access adjacent elements
for (int i = 0; i < items.length - 1; i++) {
print('${items[i]} -> ${items[i + 1]}');
}
// nail -> shoe
// shoe -> horse
}
Conditional Logic
You can use if statements to handle edge cases, such as empty lists or special conditions.
void main() {
List<String> items = [];
// Check if list is empty
if (items.isEmpty) {
print('List is empty');
} else {
print('List has ${items.length} items');
}
// Early return pattern
String process(List<String> data) {
if (data.isEmpty) return '';
// Process data...
return 'result';
}
}
List Length
The length property returns the number of elements in a list. It’s useful for loops and boundary checks.
void main() {
List<String> items = ['a', 'b', 'c'];
print(items.length); // 3
// Generate one less than length
int count = items.length - 1;
print(count); // 2
// Iterate up to length - 1
for (int i = 0; i < items.length - 1; i++) {
print(items[i]);
}
}
Introduction
For want of a horseshoe nail, a kingdom was lost, or so the saying goes.
Given a list of inputs, generate the relevant proverb. For example, given the list ["nail", "shoe", "horse", "rider", "message", "battle", "kingdom"], you will output the full text of this proverbial rhyme:
For want of a nail the shoe was lost.
For want of a shoe the horse was lost.
For want of a horse the rider was lost.
For want of a rider the message was lost.
For want of a message the battle was lost.
For want of a battle the kingdom was lost.
And all for the want of a nail.
Note that the list of inputs may vary; your solution should be able to handle lists of arbitrary length and content. No line of the output text should be a static, unchanging string; all should vary according to the input given.
What is “For Want of a Nail”?
“For Want of a Nail” is a proverbial rhyme that demonstrates how small, seemingly insignificant events can lead to major consequences through a chain of cause and effect. The rhyme traces a series of events from the loss of a horseshoe nail to the loss of a kingdom, illustrating the butterfly effect in action.
The proverb has been used for centuries to teach the importance of attention to detail and the interconnectedness of events.
— Wikipedia
How does the proverb generation work?
To generate the proverb from a list of items:
- Generate pairs: For each adjacent pair of items in the list, create a line in the format “For want of a [first] the [second] was lost.”
- Add final line: Add a concluding line “And all for the want of a [first item].”
- Join lines: Combine all lines with newline characters
For example, with ["nail", "shoe", "horse"]:
- Pairs:
- “For want of a nail the shoe was lost.”
- “For want of a shoe the horse was lost.”
- Final line: “And all for the want of a nail.”
- Result: Three lines joined with newlines
The key insight is that we need n-1 lines for n items (one line for each adjacent pair), plus one final line referencing the first item.
Solution
class Proverb {
String recite(List<String> pieces) {
if (pieces.isEmpty) return '';
return [
...List.generate(
pieces.length - 1,
(i) => 'For want of a ${pieces[i]} the ${pieces[i + 1]} was lost.',
),
'And all for the want of a ${pieces[0]}.',
].join('\n');
}
}
Let’s break down the solution:
-
if (pieces.isEmpty) return ''- Handles the edge case where the input list is empty by returning an empty string immediately -
List.generate(pieces.length - 1, ...)- Creates a list ofn-1elements wherenis the length of the input list:- For each index
ifrom 0 topieces.length - 2, generates a string - The string format is:
'For want of a ${pieces[i]} the ${pieces[i + 1]} was lost.' - This creates one line for each adjacent pair of items
- For each index
-
Spread operator
...- Expands the generated list into individual elements within the outer list -
Final line - Adds
'And all for the want of a ${pieces[0]}.'to reference the first item in the list -
.join('\n')- Combines all elements of the list into a single string, separated by newline characters
The solution elegantly handles lists of any length by generating the appropriate number of lines dynamically, using string interpolation to insert the actual item names, and joining them with newlines to create the final proverb.
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