All CollectionsCodeMonkey Courses | Dive DeeperBanana Tales course
Banana Tales Part 2 - Python - Coding Concepts
Banana Tales Part 2 - Python - Coding Concepts

This article will provide you with in-depth explanations of the coding concepts taught on Banana Tales Part 2, how and when to use them.

Written by Livnat Hershkovitz
Updated over a week ago

## These are the coding concepts that are taught on Banana Tales Part 2 and will be reviewed in this article:

1. Classes - challenges 88 - 93

2. Input - challenges - 94 - 97

3. Simple Data Types (integers, strings) - challenges 98 - 110

4. Advanced Data Types (dictionary, set, tuple) - challenges 111 - 128

5. 2d-lists - challenges 129 - 141

6. Bubble Sort - challenges 142 - 150

# Classes

A Class is a way to bundle functionality together. After defining a class, objects of the class can be created.

A class definition consists of a description on how an object in the class "looks like" (properties) and "behaves like" (methods).

Methods are functions of the class. Properties can be thought of as the variables of the class.

For example, `Student` can be a class. The properties can be: name (e.g 'John Smith'), grade level (e.g 4), grades (e.g ‘Biology’: ‘B+’, ‘Math’: ‘A’ } ). The methods can be updating the student's grades, calculating the student's average grade, updating the grade level, etc.

A class is defined using the reserved word `class`. By convention, the class name is capitalized.

The syntax is:

`class ClassName:`

Once a class is defined, you can create objects of the class. This is called initializing objects.

The syntax is:

`object_name = ClassName()`

There is one special method called `__init__()`. This method is called each time an object is initialized. `__init__() `is a special method for defining and initializing the objects' properties of a class.

The first parameter of any class method is always the object it is operating on, which is written in the method's parenthesis as `self`.

Usually, the value of the properties will be set when the object is defined. That way, we can create different objects with different values.

If we go back to the student class example, we can define one object with the name "Sara" and one object with the name "John".

The code will be:

`class Student:`

` def __init__(self, name):`

` self.name = name`

`student1 = Student("Sara")`

`student2 = Student("John")`

You can define different methods inside the class definition. Each definition starts with the reserved word `def` and its first parameter is `self`.

Let's add two methods to the Student class - one to update the grade level; the other to print the student's information.

The code will be:

`class Student:`

` def __init__(self, name):`

` self.name = name`

` self.grade_level = 1`

` def update_grade(self, level):`

` self.grade_level = level`

` def print_info(self):`

` print("Student name: " + self.name)`

` print("Grade level: " + str(self.grade_level)`

`student1 = Student("Sara")`

Notice the difference between the two new methods - one has just one parameter (self), the other has two. When calling a method, we don't pass a value for self. The number of arguments is always one less than the number of the parameters.

The code to call these two methods will be:

`student1.update_grade(4)`

`student1.print_info()`

In Banana Tales, the challenges that practice classes include a drill that needs to drill through some bricks. The class name is `Drill`. Its properties are x and y. These two properties define where the drill will appear when the code runs and it is initialized. The Drill class has a method `drill_right()` which moves (drills through bricks if in the way) twice to the right.

You need to initialize objects of Drill that will drill the bricks, thus will lower the buildings and clear the way to the banana.

When initializing an object of Drill, we need to specify the values of x and y that the drill will appear at (upon clicking on run). If you move your mouse across the game area, the x,y coordinates are displayed.

See below how the x,y coordinates are displayed when the mouse hover over the game area (before clicking on run) and how the drill appears (and moves) once we click on run.

# Input

The input() function reads a message entered by the user. It allows entering text.

When the execution of the code reaches an input() instruction, the execution is halted (waits) until the Enter key is pressed. The input() function returns the text entered.

This function allows interacting with the user.

The syntax to use this function:

`string_variable = input()`

When calling the input() function, you can add text to be printed before the user needs to enter their response. It can also be empty.

The syntax to promote text to the user first -

`string_variable = input("Enter your text")`

The function returns the user's response. You should assign the return value to a variable to be used later in your program. The example above assigns the response to the variable `string_variable`.

In the example below, the user is prompted with a question ("What is your name?"). Notice how the program waits until the user types a response and clicks on Enter. The response is assigned to the variable answer, which is then used to print another message to the user.

In Banana Tales, the challenges that practice the input() function starts with the banana being locked up by a snake. Upon freeing the banana (by shortening the snake's length), the pigeon takes the banana and drops it in a random place.

Based on the position the banana landed, the user needs to type 'up' or 'down' to determine the height of the giraffes.

# Simple Data Types

A data type is the type of the data (number, string, boolean, etc). It defines what a variable can hold. The type also defines the operations that can be performed on the data.

A variable can store different types of data. In Python, you don't need to specify the data type of the variable when defining the variable. It is set when assigning a value to a variable based on the value's type.

The following data types will be reviewed:

## Integers

Integers are zero, positive or negative numbers without a decimal point.

For example in Banana Tales, the giraffe's height or the snake's length are integers.

Sometimes, you have a value that represents a number but its type is actually a string. For example, if a user entered the number as an input. Performing arithmetic operations on the numbers will result in an error.

The following code will raise an error:

`a = input("Enter a number ")`

`b = input("Enter another number ")`

`product = a * b`

`print(product)`

The int() function returns a number for the argument that represents a number.

If we take the example above, when the user types a number, it is actually a string. If we will use the int() function, we can use it as a number (integer).

The code will be:

`a = input("Enter a number ")`

`num1 = int(a)`

`b = input("Enter another number ")`

`num2 = int(b)`

`product = num1 * num2`

`print(product)`

In this example, the data type of the variables a and b is string; The data type of the variables num1 and num2 is integer.

In Banana Tales, the challenges that practice integers includes input from the user. In these challenges, the user needs to enter numbers. Since the type of the value returned from the input() function is a string, we need to use the int() function to convert the input to an integer.

## Strings

A string is a sequence of characters. It represents text. For example, we use strings when we print messages or prompt messages to the user.

When assigning a string to a variable, use quotation marks. In the example below, my_var is a string:

`my_var = "Coding is fun!"`

Accessing strings

Strings are also lists of characters. You can access a single character by using its index in the string. For example:

`my_var = "Coding is fun!"`

`print(my_var[0]) # will print 'C'`

`print(my_var[1]) # will print 'o'`

`print(my_var[5]) # will print 'g'`

`print(my_var[13]) # will print '!'`

You can access a range of characters by using the slice notation.

For example:

`my_var = "Coding is fun!"`

`second_word = my_var[7:9]`

`print(second_word) # will print 'is'`

In Python, you can also use negative indexing. The index -1 refers to the last item. You can use it to refer to a single character or by using the slice notation.

`my_var = "Coding is fun!"`

`print(my_var[-1]) # will print '!'`

`print(my_var[-2]) # will print 'n'`

`last_word = my_var[10:-1]`

`print(last_word) # will print 'fun'`

Reversing strings

The third argument in the slice notation is step. If you use a negative number (-1), you can reverse the string. Use the slice notation `[::-1]`. It means: start at the end of the string, stop at position 0 and move one step backwards.

`my_var = "coding is fun!"`

`reverse_var = my_var[::-1]`

`print(reverse_var) #will print '!nuf si gnidoc'`

Looping over strings

You can loop over the characters of a string using a for-loop. See below example:

Concatenate strings

The concatenation operation combines two (or more) strings together using the + operator.

For example, the following code combines the string "abc" with the string "def".

`str1 = "abc"`

`str2 = "def"`

`new_str = str1 + str2`

`print(new_str) # will print 'abcdef'`

Built-in str() function

The str() function returns a string for an argument that is a number.

Using the str() function is useful. Python knows how to add two numbers together, or two strings together (also known as concatenating strings), but doesn’t know how to add a number to a string or a string to a number.

For example, when we want to print a message with an argument which is a number, the following code will result in an error:

`my_var = "Coding is fun! Python is cool!"`

`count = 0`

`for c in my_var:`

` if c == 'o':`

` count = count + 1`

`print("The letter 'o' appears " + count + " times")`

To fix this code, we will use the str() function with count in the print message.

The code will be:

`print("The letter 'o' appears " + str(count) + " times")`

in and not in Operators

The in operator returns True if a sub-string is found in a string and False otherwise. The not in operator returns True if a sub-string is not found in a string and False otherwise.

For example:

`print("on" in "Python") # will print True`

`print("by" in "Python") # will print False`

`print("on" not in "Python") # will print False`

`print("by" not in "Python") # will print True`

Strings in Banana Tales

In Banana Tales, the challenges that practice strings include gates with code and passwords. The gates need to be opened before the banana can get to the monkey.

When a challenge is loaded, some of the gates are closed and some are open. All the passwords are built based on the gates' codes, using the same pattern. The passwords of the open gates are displayed. You need to find the pattern and build the passwords for the closed gates.

The property code holds the gate's code. For example:

`code = gate.code`

The function open(), opens the gate. Its argument is the password.

For example, if the password is the same as the gate's code:

`password = gate.code`

`gate.open(password)`

The patterns in these challenges can be to concatenate strings, reverse strings, duplicate letters or use some part of the code.

Note: the code for the gates that are opened is generated each time you click on the RUN button. Hence, it is different each time you run the game. In order to solve the challenges, you will need to build the passwords in the code.

See in the example below, that once clicking on rewind and run again, the open gate's code is different from the first run. It is 'fish' on the first run and then 'time'.

The following data types will be reviewed:

## Dictionary

A dictionary is a collection of keys and values. Dictionaries can not have duplicated items, meaning the keys are unique. A dictionary is defined using curly brackets {}. The key & value pair is defined using a colon (:) - key:value.

The syntax to define a dictionary:

`dictionary_name = {key1:value1, key2:value2,...}`

For example:

`shopping_list = {"eggs":12 , "milk":2, "apples":5, "tomatoes": 6}`

You can refer to a value by using its key.

The syntax to refer to a value is:

`dictionary_name[key]`

For example:

`shopping_list = {"eggs":12, "milk":2, "apples":5, "tomatoes": 6}`

`print("How many apples are you buying?")`

`print(shopping_list["apples"]) # will print '5'`

Trying to access a key that is not found in the dictionary will result in an error.

The following code will print 2 (the value of the key "milk") but then an error will be given and running of the code will stop. As you can see, 12 is not printed (the value of the key "eggs").

`shopping_list = {"eggs":12, "milk":2, "apples":5}`

`print(shopping_list["milk"])`

`print(shopping_list["soda"])`

`print(shopping_list["eggs"])`

A dictionary can be updated. New pairs can be added and values can be updated.

The syntax for adding or updating a key is:

`dictionary_name[key] = value`

If the key already exists, its value is updated. Otherwise, a new key and value is added to the dictionary.

In the example below:

1. the number of "eggs" will be updated to 18 since the key "eggs" already exists

2. a new key: "soda" and its value 2 will be added, since that key does not exists in the dictionary

`shopping_list = {"eggs":12, "milk":2, "apples":5}`

`shopping_list["eggs"] = 18`

`shopping_list["soda"] = 2`

`print(shopping_list)`

The in and not in operators return True or False based on if the key is found in the dictionary or not. These operators only check if a key is found in the dictionary - they do not look for values.

The syntax to use these operators is:

`key in dictionary_name`

`key not in dictionary_name`

For example:

`shopping_list = {"eggs":12, "milk":2, "apples":5}`

`if "eggs" in shopping_list:`

` print("my list is complete")`

`if "candy" not in shopping_list:`

` print("healthy shoppings")`

In Banana Tales, the challenges that practice dictionaries include gates, but here we do not know the passwords. The rat has all the passwords for the gates. A dictionary holds pairs of gate code and password. The function get_passwords() returns a dictionary with the codes and passwords.

In order to find the password, you need to use the gate's code that you are trying to open.

First get the dictionary:

`codes_and_passwords = rat.get_passwords()`

`password = codes_and_passwords[gate.code]`

Open the gate:

`gate.open(password)`

As the game advances, there will be challenges where some gates are already open, or that some gates are missing from the rat's dictionary. You will need to use the in and not in operators to check if the gate's code exists in the dictionary or not.

Each time you run the game, new codes are generated for the gates. Hence, each run the rat returns a different dictionary with codes and passwords.

## Set

A set is an unordered collection of unique items. The set can be changed by adding or removing items. A set is defined using curly brackets {} and commas to separate between the items.

The syntax to define a set is:

`set_name = {item1, item2, ...}`

For example:

`birds = {"eagle", "owl", "vulture", "falcon"}`

The syntax is:

`set_name.add(new_item)`

For example:

`birds = {"eagle", "owl", "vulture", "falcon"}`

`birds.add("hawk")`

Since the set is unique, adding an item that already exists in the set will not affect the set.

Removing an item:

The pop() function removes any item from the set. It also returns the removed item. You can not know in advance which item will be removed.

The syntax is:

`set_name.pop()`

For example:

`birds = {"eagle", "owl", "vulture", "falcon", "hawk"}`

`removed_item = birds.pop()`

`print(removed_item)`

`print(birds)`

Removing a specific item:

The remove() function removes a specific item from the set.

The syntax is:

`set_name.remove(item)`

For example:

`birds = {"eagle", "owl", "vulture", "falcon", "hawk"}`

`birds.remove("vulture")`

Trying to remove an item that doesn't exist in the set, will cause an error.

Looping over sets

You can loop over the items of a set using a for-loop.

The syntax is:

`for loop_variable in set_name:`

See below example:

In Banana Tales, the challenges that practice sets introduce baskets with balloons. Adding a balloon makes the basket go up, removing a balloon makes the basket go down. balloon_colors is a property of basket. It holds the colors of the balloons in the basket. balloon_colors is a set, hence, you can only have one balloon from each color.

Trying to add an item to balloon_colors which is not a valid color will raise an error.

You need to make the baskets go up or down to fill the gaps and clear the way for the banana.

Notice in the example below, that adding "red" and "blue" again, does not add another balloon to the basket. Also, since we added one balloon too many (we need 3 balloons in the basket), we removed it.

## Tuple

A tuple is a sorted collection that cannot be changed. Meaning that after a tuple is defined, items can not be added, removed or changed. Unlike a set, a tuple can contain duplicates. The items in a tuple are indexed, starting from 0. A tuple is defined using round brackets: ().

The syntax to define a tuple is:

`tuple_name = (item1, item2, ...)`

For example:

`names = ("Donna", "John", "Alex", "Sarah", "Micheal")`

Accessing the items is done using square brackets [] and the index.

For example:

`names = ("Donna", "John", "Alex", "Sarah", "Micheal")`

`print(names[0]) # will print 'Donna'`

`print(names[2]) # will print 'Alex'`

`print(names[4]) # will print 'Micheal'`

Looping over tuples

You can loop over the items of a tuple using a for-loop.

The syntax is:

`for loop_variable in tuple_name:`

See example:

In Banana Tales, the challenges that practice tuples continue to use baskets with balloons. A tuple named new_colors is defined, it holds colors. We use this tuple to add balloons based on the colors defined in the tuple; and to remove balloons that their color is not defined in the tuple.

# 2d-lists

A 2 dimensional list (2d-list) is a list of lists. It can be thought of as a table of rows and columns.

The items of a 2d-lists are lists.

You can define a 2d-list like this:

`list_name = [ [item1, item2, ...]. [item11, item12,...], ...]`

For example:

`numbers = [ [1,2,3,4,5,6,7,8,9], [1,3,5,7,9], [2,4,6,8], [2,3,5,7] ]`

Each item is represented by two indexes. To refer to an item in a 2d-list use the list's name and square brackets twice. Inside the first brackets write the row of the item; inside the second brackets write the column of the item. Both row and column start from zero.

The syntax to refer to an item:

`list_name[row_i][column_i]`

For example:

`numbers = [ [1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16] ]`

`print(numbers[0][1]) # will print '2'`

`print(numbers[2][0]) # will print '3'`

`print(numbers[3][3]) # will print '16'`

In order to refer to one row, use just one square bracket with the row's index.

For example, the following code prints the second row (remember, the index starts from 0).

`numbers = [ [1, 2, 3, 4], [2, 4, 6, 8], [3, 6, 9, 12], [4, 8, 12, 16] ]`

`print(numbers[1]) # will print '[2, 4, 6, 8]'`

Numbers of rows and columns:

The len() function returns the number of items in a list.

To get the number of rows in a 2d-list, use:

`len(list_name)`

To get the length of one row, use:

`len(list_name[row_i])`

For example:

`numbers = [ [1, 2, 3], [2, 4, 6], [3, 6, 9], [4, 8, 12] ]`

`print(len(numbers[3])) # will print '3'`

`print(len(numbers)) # will print '4'`

Looping over 2d-lists:

In order to loop over the items of a 2d-list, we need to use two nested for-loops. The outer for-loop will iterate over the rows of the 2d-list. The inner for-loop will iterate over the columns of the 2d-list (for a specific row).

The syntax will be:

`for i in range(len(list_name)):`

` for j in range(len(list_name[i])):`

` # Do something...`

For example, the following code prints all the numbers in a 2d-list:

`numbers = [ [1, 2, 3, 4], [11, 12], [21, 22, 23] ]`

`for i in range(len(numbers)):`

` for j in range(len(numbers[i])):`

` print(numbers[i][j])`

The index i holds the row number; the index j holds the column number;

For each row (index i), we loop over the numbers in that row and print them.

numbers[i][j] is the item position at row i and column j.

In Banana Tales, the challenges that cover 2d-lists include clouds. The clouds form a 2d-list. Each cloud is represented by two indexes: its row and its column.

The name of the 2d-list is clouds.

To create a cloud - initialize a `Cloud()` to the specific item in the clouds list.

For example, to create a cloud at the first row, first column:

`clouds[0][0] = Cloud()`

For example, to create a cloud at the third row, fourth column:

`clouds[4][5] = Cloud()`

To remove a cloud - assign `None` to a the specific item in the clouds list.

None is a null value or no value at all. Assigning None to an item in the 2d-list - clouds, will remove the cloud from the list, thus creating an empty spot.

For example, to remove a cloud from the second row, first column:

`clouds[1][0] = None`

In some challenges, you will need to create clouds to allow the banana to pass. You might need to add just one or two clouds or an entire row.

In other challenges, you will need to remove clouds that block the banana's path.

In challenges where you need to create or remove an entire row or column, you will need to use a for-loop or nested for-loops.

Note: `None` (no cloud) is also an item in the list.

# Bubble Sort

In computer science, sorting is an algorithm that puts items in a certain order. For example, if the items in a list are numbers, you can sort them from largest to smallest or from smallest to largest.

There are several algorithms that sort items in a list. In Banana Tales, we will use Bubble sort.

Swap

Before understanding the algorithm, let's understand the concept of swap, which is used in this sorting algorithm.

We swap between the values of two variables.

For example, we have two variables: the value of one is 4; the value of the other is 7. We want to change the value of the first to 7 and the other to 4.

Our code before the swap is:

`var1 = 4`

`var2 = 7`

If we will assign the value of var2 to var1, we will override the value of var1 and will not be able to assign it to var2.

We need to use another variable to hold one of the variable's value before overriding it.

The code for swapping two variables using a temporary variable will be:

`temp = var1`

`var1 = var2`

`var2 = temp`

See example below:

The process of the swap will be:

Bubble Sort Algorithm

Let's say we want to sort a list from smallest to largest.

The Bubble sort algorithm sorts a list by comparing between two adjacent items and swaps their places if they are in the wrong order. The algorithm iterates repeatedly. In each iteration, the next item is "bubbled" up to the correct place.

The Bubble sort algorithm, starts with looping over the list and comparing every two adjacent items. After the first iteration on the list, the largest item will be at the end of the list.

Then, we need to loop over the list again. This time we don't need to go until the end of the list, because we already know the largest item is positioned there. Again, the algorithm will compare each two adjacent items and will swap their places if needed. At the end of this iteration, the second largest item will be positioned in the one before the last item of the list.

After two iterations, we have 2 items positioned correctly.

This will continue until the list is sorted.

The algorithm is implemented using nested for-loops.

The outer loop iterates per the number of items in the list minus one. The inner loop iterates per the number of items in the list minus one minus the number of items already positioned (the index of the outer loop).

The code inside the inner for-loop compares between the two adjacent items (index j and j+1) and swap their places if needed.

The following code sorts the list numbers. After each iteration over the list, the list is printed, and you can see below how the numbers are bubbled to the correct place.

`numbers = [5, 6, 9, 7, 3, 4, 8, 2]`

`length = len(numbers) - 1`

`for i in range(length):`

` for j in range(length-i):`

` if numbers[j] > numbers[j+1]:`

` temp = numbers[j+1]`

` numbers[j+1] = numbers[j]`

In Banana Tales, the challenges that cover Bubble sort include flamingos.

The flamingos have heights but we can't change their heights (like the giraffes). We need to change the flamingos' position so that they are placed in order (based on their heights) and create stairs for the banana.

Assignment of flamingos

In order for the flamingos to "change" places, we need to assign a flamingo to a cell in the flamingos list.

For example:

`flamingos[0] = flamingos[1]`

This code copies the flamingo on the right of the = sign (flamingos[1]) and places it instead of the flamingo on the left of the = sign (flamingos[0]).

In the first few challenges, you practice swapping using a temporary variable.

To swap places between two flamingos:

1. assign one flamingo to a temp variable: `temp = flamingos[0]`

2. assign a flamingo to the first flamingo's cell in the list: `flamingos[0] = flamingos[1]`

3. assign temp to the second flamingo's cell in the list: `flamingos[1] = temp`

As you continue playing, the challenges introduce the Bubble sort algorithm. First, with several for-loops, and then with two nested for-loops.

Relevant Articles: