exercism

Exercism - Sum of Multiples

This post shows you how to get Sum of Multiples exercise of Exercism.

Stevinator Stevinator
8 min read
SHARE
exercism dart flutter sum-of-multiples

Preparation

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

Sum of Multiples Exercise

So we need to use the following concepts.

Lists

Lists are ordered collections of items. You can create lists, add elements, and iterate over them.

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];
  
  // Add elements
  numbers.add(6);
  print(numbers); // [1, 2, 3, 4, 5, 6]
  
  // Iterate over list
  for (var num in numbers) {
    print(num);
  }
}

List.filled with Growable Parameter

The List.filled() constructor creates a list with a specified length and initial value. The growable parameter determines if the list can grow beyond its initial size.

void main() {
  // Fixed-size list (growable: false)
  List<int> fixed = List<int>.filled(3, 0);
  // fixed.add(4); // Error: Cannot add to a fixed-length list
  
  // Growable list (growable: true)
  List<int> growable = List<int>.filled(1, 0, growable: true);
  growable.add(1);
  growable.add(2);
  print(growable); // [0, 1, 2]
  
  // Common pattern: start with one element, then add more
  List<int> results = List<int>.filled(1, 0, growable: true);
  results.add(10);
  results.add(20);
  print(results); // [0, 10, 20]
}

RemoveWhere Method

The removeWhere() method removes all elements from a list that satisfy a given condition. It modifies the list in place.

void main() {
  List<int> numbers = [0, 1, 2, 3, 0, 4, 5];
  
  // Remove all zeros
  numbers.removeWhere((e) => e == 0);
  print(numbers); // [1, 2, 3, 4, 5]
  
  // Remove all even numbers
  List<int> evens = [1, 2, 3, 4, 5, 6];
  evens.removeWhere((e) => e % 2 == 0);
  print(evens); // [1, 3, 5]
}

Nested For Loops

Nested for loops allow you to iterate through multiple collections or ranges simultaneously. This is useful for checking combinations of values.

void main() {
  // Outer loop: iterate through numbers 1 to 10
  for (var i = 1; i < 10; i++) {
    // Inner loop: iterate through multipliers
    List<int> multipliers = [3, 5];
    for (var j = 0; j < multipliers.length; j++) {
      if (i % multipliers[j] == 0) {
        print('$i is a multiple of ${multipliers[j]}');
      }
    }
  }
}

Modulo Operator

The modulo operator (%) returns the remainder of a division operation. It’s useful for checking divisibility.

void main() {
  // Check if a number is divisible by another
  int num = 15;
  
  print(15 % 3); // 0 (15 is divisible by 3)
  print(15 % 5); // 0 (15 is divisible by 5)
  print(15 % 4); // 3 (15 is not divisible by 4)
  
  // Check divisibility
  if (num % 3 == 0) {
    print('$num is divisible by 3');
  }
  
  // Find multiples
  for (int i = 1; i < 20; i++) {
    if (i % 3 == 0) {
      print(i); // 3, 6, 9, 12, 15, 18
    }
  }
}

Sets

Sets are collections of unique elements. Converting a list to a set automatically removes duplicates.

void main() {
  List<int> numbers = [1, 2, 2, 3, 3, 3, 4];
  
  // Convert list to set (removes duplicates)
  Set<int> unique = numbers.toSet();
  print(unique); // {1, 2, 3, 4}
  
  // Convert back to list
  List<int> uniqueList = unique.toList();
  print(uniqueList); // [1, 2, 3, 4]
  
  // Common pattern: remove duplicates from a list
  List<int> withDuplicates = [1, 2, 2, 3, 3, 4];
  List<int> withoutDuplicates = withDuplicates.toSet().toList();
  print(withoutDuplicates); // [1, 2, 3, 4]
}

Fold Method

The fold() method reduces a collection to a single value by iteratively combining elements. It takes an initial value and a combining function.

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];
  
  // Sum all numbers
  int sum = numbers.fold(0, (previous, element) => previous + element);
  print(sum); // 15
  
  // Product of all numbers
  int product = numbers.fold(1, (previous, element) => previous * element);
  print(product); // 120
  
  // Find maximum
  int max = numbers.fold(0, (previous, element) => 
    previous > element ? previous : element);
  print(max); // 5
}

Introduction

You work for a company that makes an online, fantasy-survival game.

When a player finishes a level, they are awarded energy points. The amount of energy awarded depends on which magical items the player found while exploring that level.

Instructions

Your task is to write the code that calculates the energy points that get awarded to players when they complete a level.

The points awarded depend on two things:

  1. The level (a number) that the player completed.
  2. The base value of each magical item collected by the player during that level.

The energy points are awarded according to the following rules:

  1. For each magical item, take the base value and find all the multiples of that value that are less than the level number.
  2. Combine the sets of numbers.
  3. Remove any duplicates.
  4. Calculate the sum of all the numbers that are left.

Example

Let’s look at an example:

The player completed level 20 and found two magical items with base values of 3 and 5.

To calculate the energy points earned by the player, we need to find all the unique multiples of these base values that are less than level 20.

  • Multiples of 3 less than 20: {3, 6, 9, 12, 15, 18}
  • Multiples of 5 less than 20: {5, 10, 15}

Combine the sets and remove duplicates: {3, 5, 6, 9, 10, 12, 15, 18}

Sum the unique multiples: 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 = 78

Therefore, the player earns 78 energy points for completing level 20 and finding the two magical items with base values of 3 and 5.

What is a multiple?

A multiple of a number is the product of that number and any integer. For example, the multiples of 3 are 3, 6, 9, 12, 15, 18, 21, etc. In other words, if a number n is a multiple of m, then n % m == 0 (the remainder when dividing n by m is zero).

— Mathematics

How can we calculate the sum of multiples?

To calculate the sum of multiples:

  1. Remove invalid multipliers: Filter out any zero values from the list of multipliers (since division by zero is undefined)
  2. Find all multiples: For each number from 1 to (level - 1), check if it’s divisible by any of the multipliers
  3. Collect multiples: Add each multiple found to a results list
  4. Remove duplicates: Convert the list to a set (which automatically removes duplicates), then back to a list
  5. Sum the results: Use fold() to sum all the unique multiples

The key insight is using nested loops: the outer loop iterates through potential multiples, and the inner loop checks each multiplier to see if the number is divisible by it.

Solution

class SumOfMultiples {
  int sum(List<int> listOfMultiplies, int highestNumber) {
    List<int> listOfResults = List<int>.filled(1, 0, growable: true);

    listOfMultiplies.removeWhere((e) => e == 0);

    for (var i = 1; i < highestNumber; i++) {
      for (var j = 0; j < listOfMultiplies.length; j++) {
        if (i % listOfMultiplies[j] == 0) {
          listOfResults.add(i);
        }
      }
    }

    return listOfResults.toSet().toList().fold(0, (p, e) => p + e);
  }
}

Let’s break down the solution:

  1. List<int> listOfResults = List<int>.filled(1, 0, growable: true) - Creates a growable list initialized with one element (0):

    • List.filled(1, 0) creates a list with one element set to 0
    • growable: true allows the list to grow beyond its initial size
    • This initial 0 will be included in the sum, but since we’re summing multiples (which are all positive), it doesn’t affect the result
  2. listOfMultiplies.removeWhere((e) => e == 0) - Removes all zero values from the multipliers list:

    • Zero multipliers would cause division issues
    • Modifies the list in place
  3. Nested loops to find multiples:

    • Outer loop (for (var i = 1; i < highestNumber; i++)): Iterates through all numbers from 1 to highestNumber - 1
    • Inner loop (for (var j = 0; j < listOfMultiplies.length; j++)): Checks each multiplier to see if the current number is divisible by it
    • Condition (if (i % listOfMultiplies[j] == 0)): If the number is divisible by the multiplier (remainder is 0), it’s a multiple
    • Add to results: Adds the number to listOfResults if it’s a multiple of any multiplier
  4. listOfResults.toSet().toList() - Removes duplicates:

    • Converts the list to a set (which only contains unique values)
    • Converts back to a list for the fold operation
  5. .fold(0, (p, e) => p + e) - Sums all unique multiples:

    • Starts with initial value 0
    • For each element e, adds it to the previous sum p
    • Returns the total sum of all unique multiples

The solution efficiently finds all multiples by checking each number against all multipliers, then removes duplicates and sums the results.


You can watch this tutorial on YouTube. So don’t forget to like and subscribe. 😉

Watch on YouTube
Stevinator

Stevinator

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