Designing Solutions and Solution Processes
I. Designing Solutions
When we are designing solutions, we often use a design thinking model , even if we don’t always realize it. Design thinking is described by different models, but we’ll be looking at the five-step model that is most commonly seen when using design thinking.
In conjunction with computational thinking, the design thinking process can help us evolve our ideas before we start diagramming solutions. It should be noted that we don’t go through the design thinking process linearly, much like in computational thinking. Think about the steps in computational thinking:
- Problem decomposition
- Pattern recognition
- Abstraction
- Algorithm design
The design thinking model works the same way. It was designed by the Hasso-Plattner Institute of Design at Stanford University. The main steps of the model include the following:
- Empathize : Understand the problem from the audience or stakeholder perspective.
- Define : Identify the objectives, the decisions that need to be made, any biases introduced, and any details pertaining to the problem.
- Ideate : Brainstorm ideas, which go with the diagramming we’ll be doing in the next section of this part.
- Prototype : Design the algorithm solution and check it often.
- Test : Check your algorithm often throughout the process and go back to previous steps as needed.
As you can see, I’ve adapted the design thinking model to align more with a computational thinking process. The main goal when we’re using these models and combining them is to break down the harder problems into simpler chunks so we can solve and design the best algorithms. This does not take the place of computational thinking. It simply provides a better idea of how we can address the process. The following diagram can help demonstrate how the process may work:
As you can see, rather than using the linear model most frequently shown, the preceding model shows the process as cyclical . That said, going back to empathize can happen from any point, so going back and forth between these steps is the best way to use the design thinking model.
Let’s take a look at a scenario where we are using design thinking in conjunction with computational thinking.
Problem 1 - A marketing survey
Let’s say you’re working with a marketing firm and they ask you to put together a survey to gather feedback about a website. Here are some of the steps you may go through:
- Identifying stakeholders : This includes the people you’ll survey as well as the people who will use the information after the survey, for example.
- Identifying questions : This is where you define what information you hope to find from the survey.
- Designing the survey : This includes not only the questions you identified but the aesthetics of what the survey will look like.
- Information gathering : This is where you decide how you will communicate with the people who will fill out the survey, such as email, a link on a website, or similar.
- Data analysis : You can write a Python algorithm to help you with data analysis, including creating tables and graphs based on the data collected.
- Data sharing : This is where you will plan the visuals, reports, and data presentation to the original stakeholders.
Let’s be clear: this is an oversimplification of the process. But let’s say you realize you need to include another group for the survey. Say you were only initially getting feedback from students at a school but realized you wanted to add teachers and parents. Well, then you would go back to step 1 and identify in which ways the rest of your information would be affected. You may want to change the look of the survey or add a different one for adults versus children. You may need to add questions that are for only one group, which affects your decision-making in the algorithm for the survey.
Now let’s take a look at these steps within the design thinking process.
For our problem, identifying the stakeholders and questions are part of steps 1, 2, and 3 of the design thinking model: empathize , define , and ideate . Building the algorithm is both part of prototype and test , which are steps 4 and 5 . Adding people to the survey takes us back to steps 1–3 . And the cycle repeats until we have a working algorithm for our scenarios. Throughout the computational thinking model and using its elements, you’ll use the design thinking process embedded within. It’s a natural part of the decision-making process.
Now that we’ve looked at the design thinking model, let’s take a look at how to visually represent the decision-making using diagramming solutions.
II. Diagramming Solutions
When we are designing algorithms, we often use diagrams and flowcharts to help us analyze the process and visually see where our decisions are made. These diagrams allow us to create better algorithms.
The process of creating these diagrams varies by developer or coder. For example, I usually create a brainstorm for the problem, then a flowchart from that information. To look at that process, let’s go back to our survey problem from earlier in this chapter. Look at the following brainstorm. It is not complete, as you can add a lot of sub-topics. This brainstorm assumes we are surveying stakeholders to evaluate and share feedback on a school website.
As you can see from the diagram, there are many considerations to be made. The actual survey design may be provided to us as programmers or we may take part in designing the survey. If we have the survey, our brainstorm may look different, as we navigate through the questions and decide how to best place them within the algorithm. This is part of the empathizing process. We are looking at our information from multiple angles, from multiple stakeholders’ perspectives, and deciding how we’ll write an algorithm to help us get to where we need. The purpose of an informal diagram such as the brainstorm is that it allows us to begin organizing ideas before trying to create a more detailed and organized flowchart. When we work on the diagram, we are defining and ideating our algorithm. That’s why it’s important to sketch out our plans before beginning to code directly.
With regard to flowcharts, we saw a few in the last chapter when discussing the creation of a store in Python. Now let’s take a look at a flowchart for decision-making based on some decisions.
It is important to note that surveys can be difficult to create from scratch. Part of the reason is that there may be questions that depend on each other. For example, let’s say you ask the user to state whether they approve of the color choices or not. If they do, you can move on. But if they don’t, you may want to provide other color schemes for review. That question would only appear for those who choose the No option. Our flowchart could be rather complicated if we were to tackle all the information for our brainstorm, so we’ll focus on a few questions within the Look category of the brainstorm. Take a look at the following flowchart:
As you can see from the flowchart, some things are not clearly visible, such as what happens when you complete one question, where you go after each decision, and so on. When I create flowcharts, I sometimes add arrows to help me see what happens after each step. The following flowchart shows some of the arrows added:
As can be seen from the preceding flowchart, not all arrows are added, but look closely at Color Scheme . If a user approves of the color scheme, then they go directly to the Fonts section. If they don’t, they are shown options. Assuming one option is shown at a time, then the user would go to Fonts after they choose one they like. It is also possible to add a prompt that asks the user if they’d like to see the options again, which would bring them back to the Alt option 1 . Arrows can be added to show those details.
It all depends on what is easiest for you as a developer and programmer to understand yourself. Think of these as your journal notes if you were a writer. The way you organize your ideas can be personal, just make sure your end result and algorithm can be easily used by the people it is intended for.
Now let’s take a look at how to put everything together and create solutions to some problems.
III. Creating Solutions
When we are presented with problems, we want to create solutions that address the information we have been provided, with an algorithm that provides everything needed and that is easily understood by the user. In this section, we’ll take the content we’ve been learning in this chapter in order to design solutions to problems.
As we create these solutions using our brainstorms and flowcharts, we should be considering the following:
- Does the solution we have planned address the problem?
- Does the solution design show a clear path for the algorithm to be successful?
And if the answers to those questions are yes, then we can start coding the solution. Remember, we need to test the algorithm as often as we can. Here are some things to keep in mind when writing the algorithm:
- Add comments to identify sections you may need to go back to and that clearly help to identify and define your variables, dictionaries, functions, and any key components.
- Check that you don’t have any errors.
- Run your program as often as possible to test for errors.
For the solution process, we’re going to use a slightly different problem than the survey we were working on earlier in the chapter. We will tackle components you can use for that problem as we go through this book, such as adding images, showing graphics, and more. But for now, let’s stick with some more basic Python in order to practice the process of creating a solution.
Problem 2 - Pizza order
I know – food. But it’s one of the best ways to demonstrate logic and algorithm creation, so bear with me. Let’s say we have a pizzeria. We sell only one type of crust because we’re a specialty kind of place. We sell two different sizes of pizza: personal and family. There are two sauce options: marinara and garlic cream. There are three cheese options: no cheese, regular cheese, and extra cheese.
There are five toppings to choose from (I’m limiting those because we’re just learning the process): mushrooms, pepperoni, Italian sausage, onions, and peppers. And no, we’re not putting olives anywhere near my pizzeria.
Let’s break down that problem. We want an algorithm to capture the options chosen by the user to order their pizza. Things we’re not going to take into consideration right now are cost and additional items in the order, such as an additional pizza, beverages, desserts, and so on.
Here’s what we know:
- Size : personal or family
- Sauce : marinara or garlic cream
- Cheese : no cheese, regular cheese, extra cheese
- Toppings : mushrooms, pepperoni, Italian sausage, onions, peppers
Now that we have that, let’s look at a flowchart with the information:
As you can see, the figure shows a fairly linear decision-making process for this particular problem. One thing we haven’t considered is asking the user if they wish to make any changes. That may need to happen at each step. Say you changed your mind while choosing cheese to go for a marinara instead of a garlic cream sauce. You’ll need to have a way to go back, so we’ll need to keep that in mind as we create the algorithm.
Keep in mind that we’re sticking to text codes currently, so we’ll use input from the user in numbers and letters for now. However, there are ways to incorporate Python into more robust algorithms that incorporate images, buttons, and more.
Take a look at the following snippet from the algorithm:
1
2
3
4
5
6
7
8
9
10
11
12
# Get input for your variables for size and sauce first.
size_choice = str(input("Is this a personal or family pizza? Type personal or family. "))
sauce_choice = str(input("Which sauce would you like? Marinara or garlic cream? Type m for marinara and g for garlic cream. "))
if sauce_choice == "g":
sauce = "garlic cream"
else:
sauce = "marinara"
# The cheese choice will dictate a few more options. Define the variable first.
cheese_choice = str(input("Would you like cheese on your pizza? Type y for yes and n for no. "))
Notice in the snippet that we defined the size and the sauce first. I will reiterate here that there are other ways to tackle this particular logic process. For example, we can save some of the variables to dictionaries and work with arrays. For now, we’re using what we’ve learned so far to create our algorithms, but we’ll get a chance to learn about other approaches later in this book.
Take a look at the following snippet with those options, which is a continuation of the preceding code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Toppings need to happen whether or not you want cheese.
if cheese_choice == "y":
cheese2_choice = str(input("Would you like regular cheese or extra cheese? Type r for regular and e for extra cheese. "))
if cheese2_choice == "r":
cheese = "regular cheese"
else:
cheese = "extra cheese"
toppings1_input = str(input("Would you like mushrooms on your pizza? Type y for yes and n for no. "))
if toppings1_input == "y":
toppings1 = "mushrooms"
else:
toppings1 = "no mushrooms"
else:
cheese = "no cheese"
if cheese_choice == "n":
toppings1_input = str(input("Would you like mushrooms on your pizza? Type y for yes and n for no. "))
if toppings1_input == "y":
toppings1 = "mushrooms"
else:
toppings1 = "no mushrooms"
print("You want a " + size_choice + " pizza with " + sauce + " sauce, " + cheese + ", and " + toppings1 + ".")
As you can see from the snippet, we only worked with mushrooms. The output for this particular code after choosing family size, garlic sauce, regular cheese, and mushrooms looks as follows:
1
2
3
4
5
6
Is this a personal or family pizza? Type personal or family.family
Which sauce would you like? Marinara or garlic cream? Type m for marinara and g for garlic cream. g
Would you like cheese on your pizza? Type y for yes and n for no. y
Would you like regular cheese or extra cheese? Type r for regular and e for extra cheese. r
Would you like mushrooms on your pizza? Type y for yes and n for no. y
You want a family pizza with garlic cream sauce, regular cheese, and mushrooms.
Using the code provided and taking a look at the output, try to put together the rest of the code for the remaining four ingredients. And I guess that if you are creating your own pizza, you’re welcome to change the options provided here. Just keep the olives to yourself.
Now, as mentioned before, we may need to go back and make changes. Let’s take a look at a snippet that does that for you:
1
2
3
4
5
6
7
8
9
10
11
ready_end = str(input("Do you need to make any changes? Type y for yes and n for no. "))
if ready_end == "y":
size_choice = str(input("Is this a personal or family pizza? Type 1 for personal and 2 for family. "))
sauce_choice = str(input("Which sauce would you like? Marinara or garlic cream? Type m for marinara and g for garlic cream. "))
if sauce_choice == "g":
sauce = "garlic cream"
else:
sauce = "marinara"
cheese_choice = str(input("Would you like cheese on your pizza? Type y for yes and n for no. "))
As you can see from the snippet of code, there is a decision that needs to be made about the changes needed. If yes, then we present the questions again. If no, then we print the choices for the user. Take a look at the following output with the fully run program:
1
2
3
4
5
6
7
8
9
10
Is this a personal or family pizza? Type personal or family.family
Which sauce would you like? Marinara or garlic cream? Type m for marinara and g for garlic cream. g
Would you like cheese on your pizza? Type y for yes and n for no. n
Would you like mushrooms on your pizza? Type y for yes and n for no. y
Do you need to make any changes? Type y for yes and n for no. y
Is this a personal or family pizza? Type 1 for personal and 2 for family. family
Which sauce would you like? Marinara or garlic cream? Type m for marinara and g for garlic cream. m
Would you like cheese on your pizza? Type y for yes and n for no. n
Would you like mushrooms on your pizza? Type y for yes and n for no. y
You want a family pizza with marinara sauce, no cheese, and mushrooms.
As shown in the code, the questions were asked twice because we made a change in our options. Depending on how often you want to ask that question, you’ll need to continue to repeat some of this code.
Full code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# Get input for your variables for size and sauce first.
size_choice = str(input("Is this a personal or family pizza? Type personal or family. "))
sauce_choice = str(input("Which sauce would you like? Marinara or garlic cream? Type m for marinara and g for garlic cream. "))
if sauce_choice == "g":
sauce = "garlic cream"
else:
sauce = "marinara"
# The cheese choice will dictate a few more options. Define the variable first.
cheese_choice = str(input("Would you like cheese on your pizza? Type y for yes and n for no. "))
# Toppings need to happen whether or not you want cheese.
if cheese_choice == "y":
cheese2_choice = str(input("Would you like regular cheese or extra cheese? Type r for regular and e for extra cheese. "))
if cheese2_choice == "r":
cheese = "regular cheese"
else:
cheese = "extra cheese"
toppings1_input = str(input("Would you like mushrooms on your pizza? Type y for yes and n for no. "))
if toppings1_input == "y":
toppings1 = "mushrooms"
else:
toppings1 = "no mushrooms"
else:
cheese = "no cheese"
if cheese_choice == "n":
toppings1_input = str(input("Would you like mushrooms on your pizza? Type y for yes and n for no. "))
if toppings1_input == "y":
toppings1 = "mushrooms"
else:
toppings1 = "no mushrooms"
ready_end = str(input("Do you need to make any changes? Type y for yes and n for no. "))
if ready_end == "y":
size_choice = str(input("Is this a personal or family pizza? Type 1 for personal and 2 for family. "))
sauce_choice = str(input("Which sauce would you like? Marinara or garlic cream? Type m for marinara and g for garlic cream. "))
if sauce_choice == "g":
sauce = "garlic cream"
else:
sauce = "marinara"
cheese_choice = str(input("Would you like cheese on your pizza? Type y for yes and n for no. "))
if cheese_choice == "y":
cheese2_choice = str(input("Would you like regular cheese or extra cheese? Type r for regular and e for extra cheese. "))
if cheese2_choice == "r":
cheese = "regular cheese"
else:
cheese = "extra cheese"
toppings1_input = str(input("Would you like mushrooms on your pizza? Type y for yes and n for no. "))
if toppings1_input == "y":
toppings1 = "mushrooms"
else:
toppings1 = "no mushrooms"
else:
cheese = "no cheese"
if cheese_choice == "n":
toppings1_input = str(input("Would you like mushrooms on your pizza? Type y for yes and n for no. "))
if toppings1_input == "y":
toppings1 = "mushrooms"
else:
toppings1 = "no mushrooms"
print("You want a " + size_choice + " pizza with " + sauce + " sauce, " + cheese + ", and " + toppings1 + ".")
else:
print("You want a " + size_choice + " pizza with " + sauce + " sauce, " + cheese + ", and " + toppings1 + ".")
Problem 3 - Delays and Python
One of my first problems in Python was to create an algorithm that would react differently depending on the color chosen. This is similar to what you’d have if you were creating a traffic light. Each light has a different delay. So let’s create an algorithm that addresses that. We’ll make it a user-chosen color between green, yellow, and red, just to keep the traffic light theme. So let’s put some assumptions together:
- Green will mean a 5-second delay
- Yellow will mean a 2-second delay
- Red will mean a 4-second delay
There’s no reason for these specific delays; I just wanted to keep them all under 5 seconds. Now, let’s say that we’re playing a game and the user has to choose a color. If they choose yellow or red, they’ll get a delay and then will be asked again. The goal is to get a You win! You can go now message from the program. So let’s create a flowchart for this:
As you can see from the flowchart, the game restarts if you choose yellow or red. Now that we have the basics of what the game will look like, we have to code it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import time
print("Let's play a game. Choose a color to learn your destiny. Choose wisely or you'll have to start over. ")
i = 0
while i < 4:
color = str(input("Choose a color: red, green, or yellow. "))
if color == "green":
print("You must wait 5 seconds to learn your fate.")
time.sleep(5)
print("You win! Excellent choice!")
break
elif color == "yellow":
print("You must wait 2 seconds to learn your fate.")
time.sleep(2)
print("You lose! You must start over.")
i = i + 1
else:
print("You must wait 4 seconds to learn your fate.")
time.sleep(4)
print("You lose! You must start over.")
i = i + 1
As you can see, the algorithm contains some of the code we’ve looked at in previous chapters when talking about loops, Boolean statements, and more. This particular code returns to the beginning for three rounds if the user has not won the game. We used an if-elif-else statement to go through the color scenarios. The output of the game playing three rounds looks as follows:
1
2
3
4
5
6
7
8
9
10
Let's play a game. Choose a color to learn your destiny. Choose wisely or you'll have to start over.
Choose a color: red, green, or yellow. yellow
You must wait 2 seconds to learn your fate.
You lose! You must start over.
Choose a color: red, green, or yellow. red
You must wait 4 seconds to learn your fate.
You lose! You must start over.
Choose a color: red, green, or yellow. green
You must wait 5 seconds to learn your fate.
You win! Excellent choice!
As you can see from the game output, all three rounds were played. Each delay happened according to the statement, which you’ll have to test for yourself since I can’t show time delays with text.
Having the flowchart made creating this algorithm simpler than if I’d started coding as soon as I’d read the problem. It’s important to get used to fleshing out the processes you’ll need prior to writing your algorithms. Designing solutions can be a long and tedious process, but the more organized we are at the start, the better our algorithms will be.