This article outlines how to solve programming problems by using Launch School’s PEDAC process. There are many ways to solve coding problems, and PEDAC is but one. The purpose of this article isn’t to proclaim PEDAC as the best or only approach but provide it as one of the tools you can turn to when you begin working on a problem. You may not need PEDAC in every problem, but you’ll find a lot of advantages to employing some system when working on more sophisticated problems. The more complex the coding problem, the more you need a rigorous process like PEDAC. This approach is especially useful for beginners learning to code because many beginners have never been forced to employ a system of thinking before. It’s also a gateway concept for more formal algorithmic techniques to problem solving.
What is PEDAC? 🔗
PEDAC stands for “[Understand the] Problem, Examples / Test Cases, Data Structure, Algorithm, and Code.” PEDAC has two primary objectives: process the problem (PEDA) and **c**ode with intent (C).
Processing the problem consists of 4 steps that lead you from the initial problem statement to a solid understanding of what is required. The result is the Algorithm, which you will use to implement the solution.
Once you have understood the problem, chosen an appropriate data structure, and have an algorithm to approach the problem, all you need to do is convert the algorithm into the programming language of your choice. We call this final step coding with intent, and the final result is the implementation.
Why Use PEDAC? 🔗
For problems of a certain sophistication, PEDAC saves time. It may seem counterintuitive that a laborious process like PEDAC can save time, but that’s exactly what it does when the problem is complicated. That’s not to say that going straight to coding is always slower; in fact, it is sometimes faster for simple problems. However, the more complex the problem, the more likely that going straight to coding will lead to what we call “hack and slash” coding, a derogatory term used to describe code written without intent or context. Hack and slash coding often fails to meet the requirements and handle the edge cases, and produces programs that are hard to understand, maintain, and scale. A disciplined approach, such as PEDAC, helps you identify and avoid the pitfalls you may encounter when you don’t code with intent.
Common pitfalls of hack and slash or coding without intent are:
 Missed requirements
 Unforeseen Edge Cases
 Hard to understand code
 Code that’s difficult to maintain
Example Problem 🔗
Let’s work through PEDAC using an example.
For instance, if the target is 20, and the factors are 3 and 5, that gives us the list of multiples 3, 5, 6, 9, 10, 12, 15, 18. The sum of these multiples is 78.
If no factors are given, use 3 and 5 as the default factors.
Understand the Problem 🔗
It’s tempting to jump into a REPL and type out some code real quick. Resist this temptation. The first critical step of PEDAC is to digest the problem to gain a holistic and wellrounded understanding of what the entire problem is asking. Don’t rush. Read the problem statement carefully; don’t miss any details. In most problem statements, there are no wasted words, so don’t read it like you would a magazine article. Every word and every detail matters. Your brain tends to fill in the gaps if you skip any details, but it may not do so correctly, as demonstrated by the following:
Let’s first identify the inputs and outputs for our problem. Reading the problem statement, we can see that we have two inputs, and one output:
target number
the set of factors
output:
sum of multiples
Unless you’re familiar with the problem domain, there’s also a subtle implicit concept that’s introduced in the problem: multiples
.
Problem Domain
A problem domain is the area of expertise or application that needs to be examined to solve a problem. It limits the scope of the problem.To make the requirements/terms explicit, we must understand the terms as they apply to the problem domain. These aren’t limited to words you’re unfamiliar with, but also words that have multiple meanings. For instance, “balance” can mean different things depending on whether we use it in an accounting or a supply chain context.
Going back to the term “multiples,” assume that this is a “mathematical term” that means “a number that can be divided by another number without a remainder.” (Normally, you would not want to assume something if you’re unfamiliar with the problem domain but would seek clarification first. Here, we’re the problem giver, so we’re going to confirm that this assumed definition is correct.) Using the example in the second paragraph, we can confirm this:
20
multiples of 3:
3, 6, 9, 12, 15, 18 (all have no remainder when divided by 3)
multiples of 5:
5, 10, 15 (all have no remainder when divided by 5)
Implicit Requirements 🔗
This problem statement also conveys a few rules that we must keep in mind:
 The multiples to be summed must be unique. The number
15
is present as a multiple of3
and5
, but we add it just once when computing the sum(3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 = 78
). Note that we learn this implicitly from the example: the uniqueness requirement is not stated explicitly.  The target value is the limit, but it is not considered a multiple. In the example, the target,
20
, is not included in the sum even though it’s a multiple of5
. As with the first rule, this requirement is implicit.  All numbers are natural numbers: they are the set of integers greater than or equal to
0
or1
(see this definition from mathworld.wolfram.com). Since adding0
to any number doesn’t change it, it doesn’t matter which definition we use. For simplicity, we’ll assume that the natural numbers start with1
.
Now that we’ve processed the problem, we should try to identify anything that needs clarification. For instance, here are some questions you might ask about this problem, and one set of possible answers.
Clarifying Questions 🔗
 What are the possible values for the target number? Are negative numbers allowed? Any natural number greater than
0
. There will always be a target value.  How will the factors be provided to the program? As an array.
 What happens if only one number is provided as a factor? Should the program assume that a second factor that is either 3 or 5 is needed? No. Default to 3 and 5 only if no factors are provided.
Do these answers agree with any assumptions you were about to make? Maybe; maybe not. That’s the point of asking questions. Ensure you’re solving the right problem by getting clarification, even if you think you understand the problem.
We now have a thorough understanding of the problem. To help round it off, though, let’s perform an optional processing step and come up with a mental model that describes it.
We can think of the mental model as our summary view of the “entire problem.” In other words, it is our perspective on what the problem requires. Be sure to note that we’re not yet interested in how to solve the problem (the algorithm).
Here’s a simple mental model for this problem:
Here’s another mental model:
Note that we came up with two mental models in this example. We did this to highlight that there are multiple perspectives to generate a sound mental model; as a general rule, you don’t need to come up with more than one model as long as it fully and accurately captures the requirements.
Examples / Test Cases 🔗
That was a lot, but it was only the first step — the “P” in PEDAC. We’re now ready to move on to the “E”, which stands for “Examples or Test Cases”. In this step, our objective is to come up with examples that validate our understanding of the problem and confirm that we are working in the right direction. The confirmation will typically come from a person or documentation of a process: we can ask the person to confirm the output given the input, or we can follow the process to check the output given the input.
Going back to the example problem, let’s come up with some examples. Our examples will be in the form of tests that show the expected outputs given certain inputs:
Validation 🔗
Example 1 🔗
Inputs:
 Target number: 20
 Factors: [3, 5]
Output
 78
Example 2 🔗
Inputs:
 Target number: 20
 Factors: [3]
Output
 63
Example 3 🔗
Inputs:
 Target number: 20
 Factors: [5]
Output
 30
Example 4 🔗
Inputs:
 Target number: 20
 Factors: []
Output
 78
Example 5 🔗
Inputs:
 Target number: 1
 Factors: []
Output
 0
Note that we derived our examples from our rules. Those are typically an excellent place to find test cases.
In addition to test cases based on our rules, we should also provide test cases that handle any edge cases we can find. Edge cases are inputs at the “edges” of the problem description that may be mishandled if we aren’t careful. For instance, problems that involve iterating over numbers have edge cases at one or both ends of the range. If you’re not careful, you may get incorrect answers at these edges. Typical edge cases can involve working with negative numbers, the number zero, or extremely high values (if performance is a requirement). When working with collections, it’s normally a good idea to find test cases that deal with zero, one or multiple elements in the collection.
This example problem has one significant edge case: what happens if the last number before the target value is a multiple of one or more of the factors?
In each of our test cases above, the last number added to the sum is either 18
or 15
. That leaves 19
(the last value checked) out of the sum, which is the right thing to do. Suppose, though, that 19
should be included in the sum, which it should if 19
is one of the factors. Since 19 is the last possible number to check (given a target of 20
), it’s at the “edge” of the range of values that get summed. To be certain we include 19
in the sum, we need to provide a test case that handles it.
Validation 🔗
Example 6 🔗
Inputs:
 Target number: 20
 Factors: [19]
Output
 19
Data Structure 🔗
We’re now ready to move on to the third step in the PEDAC approach, the “D”. With our test cases ready, the next thing to do is to determine what data structures we will work with to convert the input to the output. The chief considerations here are our intended programming language and our mental model.
Using either of our mental models, we need to collect the values that are multiples of our factors, and then add them up. An array seems like a good fit for this collection of multiples. The only difference between our models lies in how and when we filter those numbers, but we’ll worry about that later.
One thing to take note of is that the data structure will influence your algorithm. For this reason, we typically pair the “Data Structure” and “Algorithm” steps together.
Algorithm 🔗
Where to Start?
In this step, if you have a mental model, you can start there. Otherwise, start with the “Data Structure” step and think of how you’d build and manipulate it to get the output. For instance, if it’s an array, you’d probably focus on constructing or iterating over a collection.Our chief objective here is to determine a series of instructions that will transform the input to the desired output. The challenge is to get the right level of detail; we want something that we can readily convert to code without actually writing code.
The reason you don’t want it written at the programming language level is that you will lose flexibility during implementation. Programming languages often provide several ways to achieve a given result, but each of those approaches can affect other parts of the program. If you make an implementation choice too soon by making it part of your algorithm, then later discover you should have chosen something else, you may need to go back and modify both the code and the algorithm. If you don’t address the changes at both levels, you may encounter the pitfalls we discussed earlier.
That said, it is not uncommon to change an algorithm once coding starts; don’t feel constrained to stick with what you’ve initially written. In fact, two individuals working on the same problem will often come up with different algorithms, especially if each individual has formulated different mental models. To demonstrate this, here are the algorithms using both mental models from our example:
First Mental Model 🔗
Determine a list of all multiples of a set of factors up to a target value, then filter the list of multiples to the unique values. Finally, compute and return the sum of the unique multiples.
 Create an empty array called
multiples
that will contain the multiples.  Check whether the list of factors is empty. If there are no factors, set the list to
[3, 5]
 For every
factor
in thefactors
list: Set the
current_multiple
tofactor
to keep track of the multiples offactor
.  While
current_multiple
<target
 Append the
current_multiple
tomultiples
.  Add
factor
tocurrent_multiple
.
 Append the
 Set the
 Filter duplicate numbers from
multiples
.  Compute and return the sum of the numbers in
multiples
.
Second Mental Model 🔗
Incrementally build a list of numbers that are multiples of a set of one or more factors. Add a multiple to the list only if it is not yet on the list. Finally, compute and return the sum of the numbers on the list.
 Create an empty array called
multiples
that will contain the list of multiples  Check whether the list of factors is empty. If there are no factors, set the list to
[3, 5]
 For every
factor
in thefactors
list: Set the
current_multiple
tofactor
to keep track of the multiples offactor
.  While
current_multiple
<target
 Is the
current_multiple
inmultiples
already? Yes  do nothing
 No  Append the
current_multiple
tomultiples
.
 Add
factor
tocurrent_multiple
.
 Is the
 Set the
 Compute and return the sum of the numbers in
multiples
.
Before implementing your algorithm, you should test it manually with your test cases. You don’t need to check all of the test cases, just enough to be confident that the algorithm works.
Let’s try it using the first example from our first mental model:
Example 1 🔗
Inputs:
 Target number: 20
 Number to get multiples: [3, 5]
Output
 78
Algorithm

Create an empty array called
multiples
that will contain the list of multiplesmultiples = []

Check whether the list of factors is empty. If there are no factors, set the list to
[3, 5]
[3, 5]
obtained from supplied factors. 
For every
factor
in thefactors
list:[3, 5]

Set the
current_multiple
tofactor
to keep track of the multiples offactor
.current_multiple = 3 current_multiple = 5

While
current_multiple
<target

Append the
current_multiple
tomultiples
.multiples = [3] multiples = [3, 6] multiples = [3, 6, 9] ... multiples = [3, 6, 9, 12, 15, 18, 5, 10, 15]

Add
factor
tocurrent_multiple
.current_multiple = 6 current_multiple = 9 ... current_multiple = 18 current_multiple = 21 current_multiple = 5 current_multiple = 10 current_multiple = 15 current_multiple = 20



Filter duplicate numbers from
multiples
.multiples = [3, 6, 9, 12, 15, 18, 5, 10]

Compute and return the sum of the numbers in
multiples
.78
After verifying that a few of our test cases gives the expected output, it’s time to put our algorithm to code.
Code 🔗
This is the last step in PEDAC — the “C”, which stands for “code with intent”. This stage is all about implementing the solution in your language of choice. The major benefit of investing time in the previous steps (the PEDA) is that it reduces the implementation to a simple translation of the algorithm into programming language syntax.
Don’t be alarmed if, after doing all the steps above, you still have to circle back to your algorithm. That can and will happen often. After all, you’re human, and you may have missed something. PEDAC, however, aims to minimize those mistakes, so you don’t miss major requirements and even if you are circling back to previous steps, it’s mostly for finetuning the approach.
Here’s a Ruby implementation of the algorithm we designed for the first mental model:
def sum_of_multiples(target, factors)
multiples = []
factors = [3, 5] if factors.length == 0
factors.each do factor
current_multiple = factor
while current_multiple < target
multiples << current_multiple
current_multiple += factor
end
end
multiples.uniq.inject(0, :+)
end
sum_of_multiples(20, [3, 5]) # returns 78
sum_of_multiples(20, [3]) # returns 63
sum_of_multiples(20, [5]) # returns 30
sum_of_multiples(20, []) # returns 78
sum_of_multiples(1, []) # returns 0
sum_of_multiples(20, [19]) # returns 19
Here’s the JavaScript implementation using the algorithm we designed for the second mental model:
function sumOfMultiples(targetNumber, factors) {
var multiples = [];
if (factors.length === 0) {
factors = [3, 5];
}
factors.forEach(function(factor) {
var currentMultiple;
for (currentMultiple = factor; currentMultiple < targetNumber; currentMultiple += factor) {
if (multiples.indexOf(currentMultiple) === 1) {
multiples.push(currentMultiple);
}
}
});
return multiples.reduce(function(sum, value) {
return sum + value;
}, 0);
}
sumOfMultiples(20, [3, 5]); // returns 78
sumOfMultiples(20, [3]); // returns 63
sumOfMultiples(20, [5]); // returns 30
sumOfMultiples(20, []); // returns 78
sumOfMultiples(1, []); // returns 0
sumOfMultiples(20, [19]); // returns 19
Either Ruby or JavaScript would work for both mental models. However, the first model is slightly better suited for Ruby since Ruby has a method for returning unique values in an Array; JavaScript does not.
Summary 🔗
We hope that this demonstration of the PEDAC process has made a case for using it. Though it was on the verbose side of things to give each step ample coverage, this type of verbosity isn’t always needed for every problem. You also don’t need to follow the PEDA sequence strictly. The key ideas are to process the problem so that you come up with an algorithm and then code with intent. It may seem like a lot of work at first, but once you get used to employing it, you’ll be surprised at how fast and effective PEDAC is in assisting your problem solving ability.
FAQ 🔗
 What problems can I solve using PEDAC? PEDAC isn’t well suited for many abstract operations like “designing a UI.” It works well with procedural coding problems since it leads you to a series of steps/instructions that you can follow to produce a deterministic result.
 When should I use PEDAC? Should I use it even if the problem is small? If you don’t have prior experience using a formal problemsolving process then, yes, use it for trivial problems too. Get your mind used to solving problems by following PEDAC. Once you get used to it, it will become part of your “muscle memory,” and you’ll be able to deploy it more naturally on more difficult problems, which is where you will really need it. If your first exposure to PEDAC is on the most difficult problems, then it’ll be hard to get good at using this process.
 Can I use PEDAC for developing applications and not just working on solving a coding problem? Yes, but you’ll have some prework to do before using it. To effectively use PEDAC, break down the application into smaller requirements. You’ll likely have to compare against previous coding problems you’ve solved if it’s appropriately small for PEDAC. PEDAC can be applied to any problem that has specific inputs and unambiguous outputs, so you’ll have to break down your application until you have specific and unambiguous requirements.