Chapter 7: Identifying Challenges within Solutions

In this chapter, we will be evaluating algorithms and diagrams as we learn to navigate through some common errors and to determine whether possible adjustments can be made to an existing algorithm to simplify it. We will evaluate the solutions based on the problem description to verify whether the solution aligns with the problem. We will be learning about identifying pitfalls in the solution design process. As a note, we will expand on the content of this chapter, later in this book, in Section 2, Applying Python and Computational Thinking, and Section 3, Data Processing, Analysis, and Applications Using Computational Thinking and Python, of this book as we dive deeper into the Python programming language.

To learn about debugging, let's remind ourselves that the computational thinking process is not linear. Even when we are working from the original problem, we will sometimes redefine the problem or need to adjust the generalization due to a change in the population our algorithm is for or if we want to tweak our design of the algorithm. But sometimes, we come at problems after an algorithm has been designed and used. Depending on our roles, we'll be evaluating algorithms for errors, changes needed, and so on. Understanding how to find and analyze errors can help us, regardless of whether we are absolute Python beginners or deep in our careers.

Throughout this chapter, you will learn how to identify and fix bugs in your program and how to avoid pitfalls in the algorithm designs.

In this chapter, we will cover the following topics:

  • Identifying errors in algorithm design
  • Debugging algorithms
  • Comparing solutions
  • Refining and redefining solutions

Technical requirements

You will need the latest version of Python to run the codes in this chapter. You will find the full source code used in this chapter here: https://github.com/PacktPublishing/Applied-Computational-Thinking-with-Python/tree/master/Chapter07

Identifying errors in algorithm design

Errors in algorithms are just a fact of life for any coder. It's important to get comfortable with making mistakes. As mentioned in Chapter 5, Exploring Problem Analysis, and Chapter 6, Solution Processes and Design, it's good practice to test your algorithm and test it often. Waiting until you have finished hundreds or thousands of lines of code to test something is a recipe for disaster. And yes, I was once working on copying a game and did not test at all. Not until I had all 4,585 lines copied. I was young. Truth be told, I never found the error I made. I started over and started testing at every corner. The second time was successful, but I'd wasted weeks copying everything (it was from a book—GitHub wasn't a thing yet) and then trying to figure out the errors. So please don't be me. Please test your algorithms.

Now, before moving on to debugging and working with codes, let's take a look at the errors we can encounter when solving problems.

In this section, we'll focus on the following two broad categories of errors: syntax errors and logic errors.

Syntax errors

Syntax errors are sometimes called parsing errors. They're errors we create when we forget to indent, add a colon, add quotation marks for strings, and so on. Let's have a look at the different types of syntax errors in the following sections.

Using colons

Colons are used in Python to separate conditions, create loops, and more. The colon is a way to tell the algorithm that the next thing is part of this particular block of code. When we introduce colons in Python, it automatically indents the next line in our code. But if we forget to include a colon where it is needed, the program will not run successfully. Let's take a look at a syntax error:

for i in range(1, 10)

    print(i)

If we run this code, we get an error message that says invalid syntax. The following screenshot shows the pop-up window that appears when we try to run this program:

Figure 7.1 – Error pop-up window

Figure 7.1 – Error pop-up window

If we run this from the Python shell instead, here's how that error appears:

SyntaxError: invalid syntax

As you can see, the Python program alerts us when we have code that contains errors.

Notice that there is a colon missing after the range in the code. Now, take a look at the fixed syntax in the following code:

ch7_syntaxerror1.py

for i in range(1, 10):

    print(i)

When we run the fixed code, the program runs and prints the numbers 1 through 9, shown as follows:

1

2

3

4

5

6

7

8

9

You may recall that the range function does not include the upper endpoint. If we wanted to print the number 10, our range would have needed to be range(1, 11).

Now, let's take a look at other punctuation used in Python that can lead to some errors, namely, parentheses, nested parentheses, and brackets.

Using nested parentheses and brackets

In addition to errors in syntax that involve colons, which are my most common error, there are also errors when we have nested parentheses. We must always check that every open parenthesis has a closing parenthesis. The same is true for brackets. Let's look at the following code, which contains an error with the parentheses:

name = str(input('What is your name? ')

print(name)

As you can see, there are two open parentheses in the name definition, but only one closing parenthesis. When we run that program, we get an invalid syntax error from Python. Here's what happens when we run that program in the Python shell or interpreter:

SyntaxError: invalid syntax

Now here's the same code without the error, notice that we even took the str() out because it was not needed, which resulted in simplifying our code and eliminating the error at the same time

ch7_syntaxerror2.py

name = input('What is your name? ')

print(name)

Now when we run the code, the program asks for the name then prints it. The output looks as follows:

What is your name? Monique

Monique

As you can see, the program now runs without problems.

In Chapter 3, Understanding Algorithms and Algorithmic Thinking, we used a dictionary to create a menu with pricing for each menu item. Dictionaries contain brackets to denote when the dictionary begins and when it ends. Let's look at a few lines of code:

cars = {

    "Hyundai": "Kona",

    "Honda": "CR-V",

    "Toyota": "Camry"

    

print(cars)

If we look at the program, the dictionary is missing the closing bracket, }, so we get a syntax error, the same as in our previous examples. The following snippet shows the corrected program:

ch7_syntaxerror3.py

cars = {

    "Hyundai": "Kona",

    "Honda": "CR-V",

    "Toyota": "Camry"

    }

print(cars)

As you can see, once the bracket has been added, the program will run and print the following output:

{'Hyundai': 'Kona', 'Honda': 'CR-V', 'Toyota': 'Camry'}

Each entry from the dictionary is printed in one line, divided by a comma. It is helpful to add print statements as we are writing algorithms to ensure we do not have any errors. I typically then remove unnecessary print functions once I've tested them, but they do come in handy when we're writing long algorithms and need to test them to avoid issues.

There are many other errors we can incorporate while writing algorithms in Python. Let's take a look at a few more syntax errors.

Other syntax errors

There are many other errors in syntax that can be introduced, especially in longer programs. If you look at the dictionary we just used, forgetting a comma will also create a syntax error, for example. Generally, these syntax errors are quickly identified when we try to run a program. Python will highlight where an indentation is expected or when a bracket is missing. Syntax errors are typically easy to identify, but there are many other types of errors.

Errors in logic

In Chapter 4, Understanding Logical Reasoning, we discussed logic errors that we can encounter:

  • Using the wrong variable in an equation or statement
  • Using the wrong operator to test conditions
  • Using wrong indentation when checking for conditions

Now we'll look at other errors in logic that have a specific callout from Python and what each error represents.

Errors in logic are also called runtime errors. The following table shows some of the built-in errors in Python and what they represent:

Table 7.1 - Table of exceptions and causes/descriptions
Table 7.1 - Table of exceptions and causes/descriptions

Table 7.1 - Table of exceptions and causes/descriptions

As you can see, there are many different types of errors that are flagged as exceptions in Python. You can get the list of Python exceptions by running the following code:

ch7_errors.py

print(dir(locals()['__builtins__']))

When we run that code, the output provides the error values as follows:

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

As mentioned, these are built-in exceptions in Python. There is a way to define our own exceptions, but we will not be going into them in this particular book.

Please note that these are not the only errors we will encounter when we are programming. We can have errors due to our own mistakes in calculations, as we discussed in Chapter 4, Understanding Logical Reasoning. We can introduce errors in our Boolean logic. The goal is to avoid as many as we can so that our program runs without problems. And remember, test your algorithms and test them often.

Now let's look at a few algorithms with errors and try to identify the errors so we can correct them.

Debugging algorithms

There is a debugger we can run in Python using the breakpoint() function (which is built-in). We can introduce this code into our program and insert it where we are unsure of our code. Adding breakpoint() will then check for bugs and errors. When we run a breakpoint() function, we'll get a pdb output, which stands for Python Debugger. As a note, this built-in function appears in Python 3.7 and newer versions. The previous debugger for Python 3.6 and older was pdb.set_trace().

When we run the debugger, we can use four commands:

  • c: Continues the execution
  • q: Quits the debugger/execution
  • n: Steps to the next line within the function
  • s: Steps to the next line in this function or a called function

Let's take a look at a code and run each of the commands outlined:

ch7_debugger.py

number = 5

number2 = 'five'

print(number)

breakpoint()

print(number2)

Looking at this code, you can see the breakpoint() command after print(number). The code will run normally until it reaches the breakpoint() command. At this stage, the execution stops. If we hit the c key, then it will just continue to run the program. Take a look at what that output looks like.

Notice in the code there are three dots between two slashes, /…/. This is done because the paths may differ from your computer to mine. Yours will include the full path where the program is located:

5

> /Users/.../Python/ch7_debugger.py(8)<module>()

-> print(number2)

(Pdb) c

five

As you can see, it went on to print the string, five, as it just continues the program. Now let's look at the output when we run the q command, which quits the program:

5

> /Users/.../Python/ch7_debugger.py(8)<module>()

-> print(number2)

(Pdb) q

Traceback (most recent call last):

  File "/Users/.../Python/ch7_debugger.py", line 8, in <module>

    print(number2)

  File "/Users/.../Python/ch7_debugger.py", line 8, in <module>

    print(number2)

bdb.BdbQuit

As you can see, once we use the q command, we get a traceback error because the program quits. It printed the line above the breakpoint() code, but not the second print(number2) command. Now, let's see what happens when we type n, which should take us to the next line:

5

> /Users/.../Python/ch7_debugger.py(8)<module>()

-> print(number2)

(Pdb) n

five

--Return--

> /Users/.../Python/ch7_debugger.py(8)<module>()->None

-> print(number2)

(Pdb)

As you can see, when we typed n, the program continued to run and printed the second command line. When it does so, you can see the -> None output and the code that ran: print(number2). Finally, let's look at slightly altered code to see what happens when we use s while running the debugger:

ch7_debugger2.py

number = 5

number2 = 'five'

print(number)

breakpoint()

print(str(number) + number2)

When we run this program and the debugger, we get the following output if we use s:

5

> /Users/.../Python/ch7_debugger2.py(8)<module>()

-> print(number + " " + number2)

(Pdb) s

TypeError: unsupported operand type(s) for +: 'int' and 'str'

> /Users/.../Python/ch7_debugger2.py(8)<module>()

-> print(number + " " + number2)

(Pdb)

As you can see, the program encountered TypeError and provides more information. I tried to combine an integer and a string. So, we would need to fix that code to run it correctly. Before I do so, let's look at what happens when I try to continue the code with c:

5

> /Users/.../Python/ch7_debugger2.py(8)<module>()

-> print(number + " " + number2)

(Pdb) c

Traceback (most recent call last):

  File "/Users/.../Python/ch7_debugger2.py", line 8, in <module>

    print(number + " " + number2)

TypeError: unsupported operand type(s) for +: 'int' and 'str'

As you can see, I can get the same information from both commands, with slightly different responses from the program. To fix the problem, I'd have to convert the number into a string, which I can do in the print line using the following code:

ch7_debugger3.py

number = 5

number2 = 'five'

print(number)

breakpoint()

print(str(number) + " " + number2)

Now that I've fixed the code so that the items in the print line are all strings, the output looks as follows when I use c to continue:

5

> /Users/.../Python/ch7_debugger3.py(8)<module>()

-> print(str(number) + " " + number2)

(Pdb) c

5 five

As you can see, the program now printed the correct information, combining the number as a string, with the five string. The double quotes add a space between them, which we have seen before, but will discuss again when we look at Python basics in Chapter 8, Introduction to Python.

Now, let's take a look at some solutions to the same problem so we can analyze them.

Comparing solutions

As we look at problems, I've mentioned that we have multiple ways of doing the same things in Python. Depending on what we are trying to accomplish, some commands may be better than others in our algorithms. Let's start by taking a look at a couple of solutions for one problem.

Problem 1 - Printing even numbers

You've been asked to write an algorithm that prints even numbers based on a range that the user provides. That is, if the user enters the range 2 through 20, then the program would print 2, 4, 6, 8, 10, 12, 14, 16, 18, and 20. Let's assume we want to include the endpoints if they are even.

Let's take a look at the first of two possible solutions. Remember, one solution may not be better than the other. A lot will depend on what the goal for your full algorithm is. Is a list more appropriate? A dictionary? A function? Those questions are important when we design solutions.

Algorithm solution 1 - Printing even numbers

Recall that we will be taking user input to create a list of even numbers given a range. Take a look at the following code, which asks the user for the input then prints out the numbers:

ch7_evenalgorithm1.py

print("This program will print the even numbers for any range of numbers provided.")

endpoint1 = int(input("What is the lower endpoint of your range? "))

endpoint2 = int(input("What is the upper endpoint of your range? "))

endpoint2 = endpoint2 + 1

for i in range(endpoint1, endpoint2):

    if i % 2 == 0:

        print(i)

        

Notice that endpoint2 was converted into endpoint2 + 1. That is because if we do not add 1, then the upper endpoint will not be included if it is an even number. The program also begins with a printed message for the user that states what the program does.

When I run this program with the endpoints 2 and 6, I get the following output:

This program will print the even numbers for any range of numbers provided.

What is the lower endpoint of your range? 2

What is the upper endpoint of your range? 6

2

4

6

As you can see, both endpoints are even and included. If we run the program with the endpoints 3 and 9, we get the following output:

This program will print the even numbers for any range of numbers provided.

What is the lower endpoint of your range? 3

What is the upper endpoint of your range? 9

4

6

8

Even though the endpoint is technically 10 now, the upper limit of the range is not included, so the largest even number below 10 is 8. Now, I can run this program for a much larger range, but the larger the range, the harder it is to scroll to get all the numbers. So, let's take a look at a different way to get our even numbers.

Algorithm solution 2 - Printing even numbers

As we saw from the previous example, each even number is being printed to a different line. Let's see whether we can change that and instead create a list. Lists in Python can be empty. We use any name for them, then equal them to items inside braces or just the empty braces.

For example, I can create an empty list called evenNumbers = []. Let's see what that looks like in the following algorithm:

ch7_evenalgorithm2.py

print("This program will print the even numbers for any range of numbers provided.")

endpoint1 = int(input("What is the lower endpoint of your range? "))

endpoint2 = int(input("What is the upper endpoint of your range? "))

endpoint2 = endpoint2 + 1

evenNumbers = []

for i in range(endpoint1, endpoint2):

    if i % 2 == 0:

        evenNumbers.append(i)

        

        

print(evenNumbers)

You can see that the first few lines of code are the same. The only difference in this particular code is how the numbers are printed. The list is created before the for loop. Then, each of the numbers is appended to the list using the evenNumbers.append(i) code. Finally, we print our list to get the following output:

This program will print the even numbers for any range of numbers provided.

What is the lower endpoint of your range? 2

What is the upper endpoint of your range? 10

[2, 4, 6, 8, 10]

As you can see, the even numbers are all included in one list, which is easier to read than if printed one at a time, one line at a time. Imagine if you had to print even numbers in the range 300–1,000. A list would make that easier to read when we run the program. The output would look as follows for the second algorithm:

This program will print the even numbers for any range of numbers provided.

What is the lower endpoint of your range? 300

What is the upper endpoint of your range? 1000

[300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 536, 538, 540, 542, 544, 546, 548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568, 570, 572, 574, 576, 578, 580, 582, 584, 586, 588, 590, 592, 594, 596, 598, 600, 602, 604, 606, 608, 610, 612, 614, 616, 618, 620, 622, 624, 626, 628, 630, 632, 634, 636, 638, 640, 642, 644, 646, 648, 650, 652, 654, 656, 658, 660, 662, 664, 666, 668, 670, 672, 674, 676, 678, 680, 682, 684, 686, 688, 690, 692, 694, 696, 698, 700, 702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722, 724, 726, 728, 730, 732, 734, 736, 738, 740, 742, 744, 746, 748, 750, 752, 754, 756, 758, 760, 762, 764, 766, 768, 770, 772, 774, 776, 778, 780, 782, 784, 786, 788, 790, 792, 794, 796, 798, 800, 802, 804, 806, 808, 810, 812, 814, 816, 818, 820, 822, 824, 826, 828, 830, 832, 834, 836, 838, 840, 842, 844, 846, 848, 850, 852, 854, 856, 858, 860, 862, 864, 866, 868, 870, 872, 874, 876, 878, 880, 882, 884, 886, 888, 890, 892, 894, 896, 898, 900, 902, 904, 906, 908, 910, 912, 914, 916, 918, 920, 922, 924, 926, 928, 930, 932, 934, 936, 938, 940, 942, 944, 946, 948, 950, 952, 954, 956, 958, 960, 962, 964, 966, 968, 970, 972, 974, 976, 978, 980, 982, 984, 986, 988, 990, 992, 994, 996, 998, 1000]

The reason I only printed this one versus the first algorithm is that the first algorithm would take pages, and we don't want to waste printed pages in this book. You can see that one is just easier to use and more appropriate than the other due to the ease of reading the larger group of numbers.

This is why we need to look at all of our algorithms and determine whether they are the best possible way to express what we need. While some algorithms work, they may not be the best solution, and sometimes that's okay. But other times, making some changes, sometimes as subtle as adding a couple of lines of code, as we did with algorithm 2, can change our output fairly dramatically and be much more helpful for us.

As we compared these two algorithms, we were also refining and redefining our solution, which we will do more of in the next section.

Refining and redefining solutions

If we look at algorithms long enough, we can always find ways to refine them and redefine them. Think about how many updates we get for apps on our phones. Someone is always playing with the apps, making them more secure, adding levels to games, updating the art files, and so on. As programmers/coders, we are always trying to make our work better.

We are going to start this section with an algorithm. The following program prints out the names of three pets:

ch7_pets1.py

cat = "Whiskers"

dog = "King Kong"

bird = "Pirate"

print("The cat's name is " + cat + ", the dog's name is " + dog +

      ", and the bird's name is " + bird + ".")

This simple code has everything within it, so there's no user input this time. You can see the character used after dog + in the print() command. This backslash allows us to add the remaining code in the next line so we can more easily read it.

The output for the code looks as follows:

The cat's name is Whiskers, the dog's name is King Kong, and the bird's name is Pirate.

As you can see, it's a simple sentence with the pet names.

Now, let's say we have a cat, dog, and bird, but their names are not the same. We can instead use a function that takes three arguments. Keep in mind we will go into all of the definitions and information on functions in Chapter 8, Introduction to Python. For now, let's look at what that algorithm could look like with a function. We'll name the function myPets(). Take a look at the following algorithm:

ch7_pets2.py

def myPets(cat, dog, bird):

    print("The cat's name is " + cat + ", the dog's name is " + dog +

          ", and the bird's name is " + bird + ".")

myPets(cat = "Whiskers", dog = "King Kong", bird = "Pirate")

The algorithm looks very similar to the previous one, except the definitions of the names are in the last line of the code. The function is called, using the information from that line to fill in the blanks from the definition in the algorithm lines above it. The output looks the same as the previous code:

The cat's name is Whiskers, the dog's name is King Kong, and the bird's name is Pirate.

Now, as you can see, this only printed one function because we only provided information for one, but we can call the function as many times as we want to with as many values as we want. Take a look at this algorithm:

ch7_pets3.py

def myPets(cat, dog, bird):

    print("The cat's name is " + cat + ", the dog's name is " + dog +

          ", and the bird's name is " + bird + ".")

myPets(cat = "Whiskers", dog = "King Kong", bird = "Pirate")

myPets(cat = "Mimi", dog = "Jack", bird = "Peyo")

myPets(cat = "Softy", dog = "Leila", bird = "Oliver")

As you can see, the function will now be called three times. We only have one print() command, but the function definition means that print() command will be used any time the function is called. Take a look at what the output looks like:

The cat's name is Whiskers, the dog's name is King Kong, and the bird's name is Pirate.

The cat's name is Mimi, the dog's name is Jack, and the bird's name is Peyo.

The cat's name is Softy, the dog's name is Leila, and the bird's name is Oliver.

Notice that three different sentences were printed with the three sets of pet names provided when we called the function.

When we're writing algorithms, it's important to take into consideration what we need now and what we might need later. Using the first algorithm was fine for one instance, but if we wanted to run the algorithm for every person in a community or every student in a classroom, for example, the second algorithm is more helpful. Redefining what we need and refining our algorithms helps us to improve what we get out of our programs.

Note that, as mentioned, we will talk about functions more in Chapter 8, Introduction to Python. One of the things we'll address is creating a function for an unknown number of arguments. For example, what if I only had a dog and a bird? We can address that with a few changes to the algorithm. We will look into that soon. For now, we know just a little more about why we need to sometimes compare algorithms and redefine and redesign them to better fit our needs.

Summary

In this chapter, we discussed errors in algorithm design and how to debug solutions. We also learned how to compare solutions and refine and redesign solutions when needed. After reading this chapter, you should know more about syntax errors in algorithms and how to use the debugger using the breakpoint() command in Python 3.7 and above. The built-in debugger provides you with four courses of action: c = continue, q = quit, n = next line, and s = step.

Using the debugger allows us to identify pieces of code where we may have made mistakes. We can add this line to any place in our code to determine the issue.

We also looked at algorithms that provide the same output but using different code. By comparing algorithm solutions, we can identify which of them are more useful, what better suits our problem or situation, and why we should use one over the other. Remember that algorithms are lists of instructions. Knowing which instructions to use given the broader use of the algorithm is critical. Some solutions may be more appropriate for your problem than others. Take into consideration the algorithm's purpose, the snippets in the algorithm, and how they will be used within the bigger algorithm and make your determinations accordingly. Each problem and each solution is unique.

As we finish out Section 1, Introduction to Computational Thinking, of this book, we have learned about the computational thinking process, always looking at possible scenarios to help us to understand the usefulness of the process, how to brainstorm and create flowcharts for decisions, and how to design our algorithms. In Section 2, Applying Python and Computational Thinking, we will begin looking at the Python language more in depth so we can tackle more complex problems, such as those dealing with data and functions. We'll also take a more in-depth look at the Python programming language, and we'll apply the knowledge to multiple types of problems in the further chapters.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.175.180