#!/usr/bin/python3
# the above line is a shebang for Linux systems, making the script executable
# import the required libraries
import random
# using a class essentially allows for grouped, named variables
class output_colours:
normal = "\033[m"
incorrect = "\033[91m"
correct = "\033[92m"
warning = "\033[93m"
emphasis = "\033[94m"
# ask the user for their name, and say hello
# the title() method makes sure the first letter is upper-case
name = input(output_colours.emphasis + "\nWhat's your name? " + output_colours.normal).title()
print("Hello, " + name + "!")
def run_quiz():
# initialise a variable to count correct answers
count_correct = 0
# execute the question section five times
# although i isn't needed, it does improve the user experience ("question i of 5")
for i in range(1, 6):
# generate two random numbers in an array, and find their product
numbers = [
random.randint(1,21),
random.randint(1,21)
]
product = numbers[0] * numbers[1]
# introduce question
print("\nQuestion " + output_colours.emphasis + str(i) + output_colours.normal + " of 5:")
# the question has yet to be answered with a valid answer (correctness irrelevant)
answered = False
while not answered:
# an "x" is used rather than a "*" as not everyone is familiar with the latter
answer = input("What is " + str(numbers[0]) + " x " + str(numbers[1]) + "? ")
# try to convert answer to an integer
try:
answer = int(answer)
# if they didn't give a valid numeric answer
except ValueError:
print(output_colours.warning +
"That answer doesn't seem to be a whole number." +
"Please give your answer as digits, such as \"45\"." +
output_colours.normal)
# if everything goes well
else:
answered = True
# compare the user's answer with the real product
# if the answer was right:
if answer == product:
# congratulate and increase count_correct by one
print(output_colours.correct + "Correct!" + output_colours.normal + " Well done!")
count_correct += 1
# if the answer was wrong:
else:
# tell them the correct answer
print(output_colours.incorrect +
"Sorry; that wasn't correct." +
output_colours.normal +
" The answer is actually " +
output_colours.emphasis +
str(product) +
output_colours.normal)
# initialise comment variable
# this holds a string with a comment about the user's score
comment = ""
if count_correct == 5:
comment = "Perfect!"
elif count_correct == 4:
comment = "Almost 100%. Good job!"
elif count_correct == 3:
comment = "Not bad!"
elif count_correct == 2:
comment = "Could be worse."
elif count_correct == 1:
comment = "At least you got one right!"
elif count_correct == 0:
comment = "Better luck next time."
# tell the user what score they reached
print("\nWell, " +
name +
", you scored " +
output_colours.emphasis +
str(count_correct) +
output_colours.normal +
"/5. " +
comment)
# ask the user if they would like to run the quiz again
try_again = input("Would you like to have another go? [" +
output_colours.correct +
"Y" +
output_colours.normal +
"/" +
output_colours.incorrect +
"N" +
output_colours.normal +
"] ")
if try_again.upper() == "Y":
run_quiz()
# run the quiz
# up until this point it has merely been defined in a function, and must be called
run_quiz()
# bid farewell before quitting
print(output_colours.emphasis + "\nBye!" + output_colours.normal)
In the script that I have written, a number of different variables are created. Created at different points in the program, they assume different levels of scope. The place in which the variables are declared defines this scope, which ensures there are no conflicts when repeating blocks of code or calling functions several times.
Before the main function is defined, I declare six variables; all of which are strings. The first five appear in the output_colours
class, and are used to change the colour of output text. Although this is not essential, it provides the user with a better experience. The last variable is the name
string. This holds user input collected from the console, once converted to the right case using the .title()
method.
Inside of the run_quiz()
function, more variables are declared. The first is count_correct
, which is an integer that holds the number of questions that the user answered correctly. Each time the user submits the correct answer to one of the questions, this variable's value is increased by one using the +=
operator.
The script then enters a for
loop. Immediately three variables are declared: numbers
, an array of integers; product
, an single integer; and answered
, a Boolean. The first consists of two numbers, generated using the randint()
function from the random
module. They each assume different values between one and twenty, inclusive. The second variable is found by multiplying the two number generated for the numbers
array. This is the answer that the script looks for later. Thirdly, the Boolean variable is set to False
, which is inverted once a valid answer has been given (for example, "5", as opposed to "five").
The script then enters a try..except
block, which attempts to convert the value entered by the user to an integer. If this fails due to a ValueError, almost certainly caused by the user not inputting an answer as numerical digits, the script will ask the question a second time. In order to test whether or not the answer can be converted, the answer
variable is passed to the int()
function, which raises and exception if it cannot. If the answer successfully converts, the answered
variable is set tot True so that the while
loop started beforehand stops.
After this, the answer given, now in integer form, is compared to the actual answer, held in the product
variable. If the two variables are equal, if answer == product
, the count_correct
variable is increased by one, as mentioned before. Once all five questions have been answered, the script exits the for loop started near the beginning of the run_quiz()
function.
An empty string variable is created called comment
, which is then modified based on the score achieved in the quiz. It must be declared outside of the if..elif
block so that the variable is still available to code after the block.This is an example of variable scope.
After this point, only one more variable is declared; try_again
. This is filled with text input from the user. If the user enters "y" or "Y", the quiz will run again, otherwise the script will exit.
Although different programming languages have different syntax and ways of declaring variables, the underlying, fundamental variable types exist in almost all languages. These are some of the most common.
Integer – These are used to hold single numbers, generally ranging from 0 to a value defined by the space in memory allocated to the variable. If an integer is assigned only one, 8-bit byte in memory, it can assume only one of 256 possible values. A 32-bit integer, in contrast, can assume any one of up to 4,294,967,296 values. In many languages, integers are used to hold negative numbers. The key fact is that integers cannot be used to hold numbers with decimals points. Integers can be used in mathematical operations intuitively, unlike strings in many languages, and are often among the easiest variables to work with.
String – Used to hold text, strings are made up of a number of characters in a sequence. Strings are one of the more complex data types, and are sometimes harder to define than integers. In more implicit languages like JavaScript and Python, however, they are fairly seamlessly integrated. Strings are virtually unlimited in terms of length, although in C, for example, one must sometimes strictly declare how many bytes in memory the string with consume. Strings are often used to interact with the user, both in terms of input and output, and can sometimes be converted to other data types by was of parsing. An example of this is the int()
function in Python.
Boolean – Able to store only two different values, Booleans, often referred to as bools, either equate to true or false. They are useful for holding information that would typically be the answer to a "yes" or "no" question. For example, a script may need to check if a file exists on the computer it's running on. In PHP, for example, the file_exists()
function returns a Boolean value. This can then be used in a conditional or if
statement to execute code only if the specified file was found.
Date – In programming terms, dates are often stored as the number of milliseconds between a point in time and midnight on the 1st January, 1970, known as the Unix Epoch. This format means that leap years and second needn't be accounted for in many applications, and that a great amount of accuracy can be used. When interacting with the user, a number of different date formats are used, although ISO standard 8601 states that YYYY-MM-DD is the globally-effective, correct way to express dates numerically.
Floating Point – As integers can only be used to hold "whole numbers", floating point variables, or floats, are used. In C, a float consumes 32 bits in memory; 23 bits for significant data, 8 bits for the exponent (where the decimal point lies), and one bit for the sign value (positive or negative). Floats are most commonly used to store decimal numbers that are not required to be of a particularly high accuracy. In C and in many other languages, there is also the double
data type, which is the same as the float
type but which consumes 64 bits of memory. As a result, 52 bits are dedicated to the significand, 11 bits to the exponent, and 1 bit to the sign.
Decimal – Similar to the float
and double
data types, the decimal
type is used to store non-integer numbers. Unlike the other two data types, however, a decimal tends to consume 128 bits in memory. As well as this difference, decimals are stored using decimal digits – one to nine inclusive – that humans are familiar with. In contrast, float
and double
variables are stored in binary form. This gives decimal variables much more accuracy, being able to represent numbers up to 29 digits long. Because of their precision, decimals are often used in finance software, such as that used to operate the modern, digital stock exchange.
An important aspect of being a programmer is to be able to judge what type of variable would be best suited for storing a particular piece of information. Below are some types of data that a program may need to store, and which data types I would use for them.
For a 16-digit bank card number I would use a string. This may seem like an odd choice at first sight, but I decided this because a bank card number is not an actual value, but rather an identifier. In much the same way as one would not perform arithmetic on a phone number, one would not do so with a card number. In addition to this, using an integer – as may seem more appropriate – would strip and leading zeros from the beginning of the number. In practice, I don't believe that any bank card number so in fact begin with zeros, but they should still be stored in a string. This same logic applies to the storing of account sort codes, phone numbers, and American address ZIP codes.
When storing someone's telephone number, I would use the same logic described above. As phone numbers can have leading zeros, and often do, and will never the used in mathematical operations, I believe a string to be the most appropriate data type.
In order to store the price of a banana, I would be tempted to use an integer representing the price in pence. Depending on the situation, I would possibly do this, as a performance improvement could be enjoyed as a result. Before outputting any values, the integer would be divided by 100 giving a float, which would be shown to the user. In reality, however, I would likely use a float or double even. Many currencies, such as Bitcoin, are hugely divisible, and are rarely found in amounts greater than 1. For this reason, multiplying the value by 10 until it could be expressed as an integer would be time consuming and would make the performance improvement negligible.
I would use an integer to express the distance in miles to Alpha Centauri. This is because this value is usually expressed in light-years, and cannot be calculated to any level of accuracy that would warrant the use of a float. The use of an integer would also meant that the program would run more efficiently, and not fill unnecessary overhead.
Although many different programming languages exist, and they almost all have different syntactic patterns, the fundamental building blocks of programming exist in most, if not all, of them.
In order to execute part of a program only if a particular condition is met, conditionals are used. These appear in a number of places, but their most basic use is generally in an if
statement. Consider the following snippet of Python code:
input_number = int(input("Enter an integer: "))
if input_number == 5:
print("Five was entered.")
elif input_number > 10:
print("A number greater than 10 was entered.")
else:
print("A number below 11, which wasn't 5, was entered.")
Here, the user is asked to input an integer. Once data has been received, it is converted to an actual integer, as the input()
function returns a string. Once an integer, the input_number
variable is easier to compare.
The first clause of the if..elif..else
block compares the answer with the number 5. If the two are equal (i.e., the user entered 5) the program outputs a string using the print()
function.
The second clause of the block uses a different operator. Rather than ==
(is equal to) it uses >
(is greater than), meaning that the conditional will equate to true if the user-generated integer is greater than 10. It's also worth noting that the line begins with elif
(else if) rather than if
. This means that the conditional will only be evaluated if the first conditional equated to false. I utilised this fact in the program I wrote close to the end, when picking a comment to print. Although the users score could easily match several of the conditionals I used, the interpreter leaves the if
block once one of the conditions has been met.
The third clause of the block begins with else
, meaning that the code found in that section will only the executed if none of the conditions above equated to true. This is useful for creating a fall-back value for a variable, if none of a series of conditions are met.
In order to avoid the repetition of a particular section of code, which is inefficient, and to make code more maintainable and easier to debug, programmers use functions or sequences of operations. These are essentially blocks of code that have been removed from the main part of the program, and been given a name. This means that at different points in the program, the section can be called, and will be executed, before the program continues.
By splitting parts of a program into functions that accept arguments, a program can become much easier to develop and manage. The following is an example of the definition of a simple function in Python, which takes two arguments and returns the result of their multiplication, plus one.
def foo(number_1, number_2):
return number_1 * numner_2 + 1
print(str(foo(2, 10)))
print(str(foo(5, 6)))
The program begins by defining the foo()
function. The two variables it accepts are given names, which are only effective within the function's code. The one line inside the function returns an integer, found by multiplying the two arguments given to it using the *
operator, and then adding 1.
After the function is defined, it's used in a print function call. The foo()
function is called, and passed the integers 2 and 10 as arguments. The output of the function, 21 as an integer, is then piped through the str()
function, which converts the integer value to a string. This is what the print()
function receives, and shows to the user.
The last line then does the same as the one before it, but passes 5 and 6 to the foo()
function. This would result in the program outputting 31 after 21. By using a function in this scenario, the code is made more maintainable and less repetitive. If the developer was to decide that they would rather the foo()
function would rather add 5 where it currently adds 1, only one line would need to be changed. Had a function not been used, 2 would need to be.
In order to repeat a section of code a number of times with a minor difference and in immediate succession, a loop is typically used. Below the for
loop is explained.
The for
loop is generally given three pieces of code, which are executed or evaluated at different points. In JavaScript, for example, a typical loop looks roughly like this:
for (var i = 0; i < 10; i++) {
...
}
The first of the three pieces of code is executed once at the beginning of the loop. This is generally used to create a variable to count the number of times the loop has been executed. The second piece is a conditional that is evaluated every time the loop runs. If this conditional equates to true, the code inside the loop will be executed, otherwise the program will continue to run after the loop's closing wiggly-brace (}
). The third piece of code is executed every time the conditional is evaluated to true.
In this case, a variable is created, i
, and set to a value of 0. Each time the loop is attempted, the interpreter will check whether or not the variable i
is less than 10. If it is, the loop will run. Lastly, the variable i
is increased by one, so that the loop does not execute indefinitely.