exercism

Exercism - House

This post shows you how to get House exercise of Exercism.

Stevinator Stevinator
8 min read
SHARE
exercism dart flutter house

Preparation

Before we click on our next exercise, let’s see what concepts of DART we need to consider

House Exercise

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:

  1. Start with “This is” followed by the subject for that verse
  2. For each previous subject (in reverse order), add the corresponding action followed by the subject
  3. Continue until you reach the first subject (“the house that Jack built”)
  4. 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:

  1. 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”

  2. 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”

  3. String recite(int startVerse, int endVerse) - Generates verses from startVerse to endVerse:

    • Uses List.generate to create a list of verses
    • For each verse index i, calculates the actual verse number: verseNum = startVerse + i - 1
    • Creates an empty list lines to store the parts of the verse
  4. Verse generation loop - Iterates backwards from verseNum down 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 index j)
    • The reverse iteration ensures we build the chain from the newest subject back to the house
  5. 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
Stevinator

Stevinator

Stevinator is a software engineer passionate about clean code and best practices. Loves sharing knowledge with the developer community.