<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Variables and types in Python
But what is a variable?
A variable is way to store information.
In the print_sum example z is a variable to the result of x + y
Variables are names for values.
In Python the = symbol assigns the value on the right to the name on the left.
The variable is created when a value is assigned to it.
Here, Python assigns an age to a variable age and a name in quotation marks to a variable first_name.
Variables are names for values.
In Python the = symbol assigns the value on the right to the name on the left.
The variable is created when a value is assigned to it.
Here, Python assigns an age to a variable age
    and a name in quotation marks to a variable first_name.
Step1:  If we try to access a variable that we didn't define we get an error
Step2:  This is a Traceback, comes directly from the Python interpreter.
<u>It's the Python way to tell us where we made a mistake.</u>
In this case we have an error called NameError and a message name 'last_name' is not defined
How can we make this code works?
Step3:  Remember
Variables' names
Step4:  Remember variables' names are CASE SENSITIVE
Step5:  FIRST_NAME IS NOT first_name
Printing variables
Do you remember our first lines of code?
Step6:  print is the function we need to use when we want to print something
Step7:  As you can see we can print variables but also values
How can I print
Step8:  let's change this a little bit
Step9:  We have 3 components here
Step10:  <div class="alert alert-success">
    <b>Challenges</b>
Step11:  Challenge 2
What is this code doing?
Step13:  Recap
"Use variables to store values."
"Use print to display values."
"Variables must be created before they are used."
"Variables can be used in calculations."
"Python is case-sensitive."
"Use meaningful variable names."
Introduction to Python built-in data types
In Python there are mainly 4 data types
Step14:  We can sum string together, we concatenate them
Step15:  You can also multiply a string for a number
Step16:  But not I want to multiply my name for 1.5!
Step17:  Let's take about this error!
Numbers
So far we have seen 2 types of numbers
Step18:  You would probably see this error very often, when you are trying to do operation between types that are not compatible
Step19:  This is operation is called casting, we are forcing a conversion to another type, in this case from string to int.
We can also cast to str (string) and we saw the sum (+) operation before.
python
integer_1 = 1
integer_2 = "10"
str(integer_1) + integer_2
Step20:  What will be the result of this operation?
We can sum integers and floats together
Step21:  Internally Python does a casting conversion from int to float, basically
Step22:  List
I love lists!
Lists are a indexed collection of (also mixed) elements.
With mixed I mean you can put different types of variables.
This is how you create a list
Step23:  Lists are very flexible and they allow many operations.
For example you can sum 2 lists
Step24:  As with the strings more than summing we are concatenating our lists.
Same goes with multiplication, a * 3 is equal to a + a + a
Step25:  If you want to add a new element to a list you can use append.
Step26:  HINT
Did you notice # inside the code? It's how you put comments in Python
Back to adding elements you can also use the sum operator (+) but is not really Pythonic...
Step27:  So, generally, just avoid this practise.
What about deleting an element?
Step28:  pop removes and returns the last element when you don't specify and index
Step29:  If you specificy and index betweenn () it will remove that element.
Step30:  I deleted the first element, index 1, why 2 has been removed?
First, lists are an indexed collection of elements, so they have and index and an order.
The index starts from 0 not from 1
So index n. 1 is the second element, while index 0 is the first element.
With this concept we can introduce the brackets notation.
Step31:  We can access an element of a list using the brackets notation with an index inside
Step32:  The element should exist
Step33:  Otherwise we would get an error.
We can also slice lists
Step34:  This is what we called slicing.
Slicing is very powerful Python, is builty by, for now, 2 parts
Step35:  Time for cool tricks
Step36:  If you avoid putting the first index it means from the beginning
If you avoid putting the last index it means till the end of the list
You can also mix the concepts together
Step37:  Small disgression
Step38:  Same slicing concepts can be applied to strings
Before moving to the next type
Step39:  This is how you change a value inside the list.
Nitty great details and best practices
Step40:  How can we add a new element to a dictionary?
We already know the brackets notation, but with dicts we use the key instead of the index
Step41:  If  we want to access the element of a dict we use the same notation
Step42:  If the element does not exist we get an error
Step43:  One way to avoid this is using get
Step44:  If the element with key an_element does not exist we the default value, None if something is not specified
Step45:  How do you delete an element?
Step46:  You can't add dicts but you can update one using values from another one, but pay attention to elements with the same keys.
Step47:  That's all for Python data types for now!
Recap
We have 4 main data types
Step48:  Loops and flow controls
Loops and flow controls serve the need to control how your code is going to be executed by Python.
More or less they translate to computers this kind of actions
Step49:  Let's break this down
Step50:  In the first example the second if is something separated from the first one.
Let's explain this a little bit more.
Key points
with a chain of if elif and else only the code under the first satisfied condition is executed
== is to compare elements
!= to check if elements are not the same
>, >=, <, <= to verify if something is minor/greater/equal
Do you see that we don't have { } inside if/elif/else? Python uses indentation
For and while
For
for iterates over something, we can call this something an object
Step51:  Note
When I normally iterate over a dictionary I get the its keys
To get also the elements I need to use items()
Step52:  Do you see what is happening here?
While
while is repeated till the expression results "True"
Step53:  <div class="alert alert-success">
    <b>Challenges</b>
Step54:  ```python
Create acronym
Step56:  ```python
Count the number of a inside the sentence
sentence = 
Step58:  ```python
Separate odd and even numbers
numbers = [1,2,3,4,5,6,7,8,9,10]
odd_numbers = []
even_numbers = []
for number in numbers
Step59:  Functions and modules
Functions
Functions are a way to write reusable code, you write function using the def word followed my the name of the function.
Step60:  A function generally returns something.
Step62:  Docstrings help you documenting your code.
The docstring of is_even is used by help function to provide more information about you function.
Step63:  You can specifiy the arguments in 2 ways
Step65:  Our function can accept many arguments, you can also specify default arguments
Step67:  If we don't put a default for our argument and we call the function we get an error
Step68:  Another important concept in namespace. You can think of a namespace as a personal shelves where Python put things.
Functions have a reserved namespace that is called local.
Step69:  This is how Python will look for variables
Step70:  In the example 1 python is accessing the enclosed scope, wheras in the example 2 it follow this rule
Step71:  global tells Python to consider a variable like a global and not as a local (as you can see x has a different value now)
HINT
The order of the parameters is important if you don't use the key=value notation.
<div class="alert alert-success">
    <b>Challenges</b>
Step72:  ```python
challenge n.2
import random
input_list = [random.randint(-1,1) for i in range(100)]
def api_call(input_list)
Step73:  ```python
challenge n.3
import random
input_list = [random.randint(-10,10) for i in range(100)]
def api_call(input_list)
<ASSISTANT_TASK:>
Python Code:
age = 29
first_name = 'Christian'
first_name
Explanation: Variables and types in Python
But what is a variable?
A variable is way to store information.
In the print_sum example z is a variable to the result of x + y
Variables are names for values.
In Python the = symbol assigns the value on the right to the name on the left.
The variable is created when a value is assigned to it.
Here, Python assigns an age to a variable age and a name in quotation marks to a variable first_name.
Variables are names for values.
In Python the = symbol assigns the value on the right to the name on the left.
The variable is created when a value is assigned to it.
Here, Python assigns an age to a variable age
    and a name in quotation marks to a variable first_name.
End of explanation
last_name
Explanation: If we try to access a variable that we didn't define we get an error:
End of explanation
# Write your code here
Explanation: This is a Traceback, comes directly from the Python interpreter.
<u>It's the Python way to tell us where we made a mistake.</u>
In this case we have an error called NameError and a message name 'last_name' is not defined
How can we make this code works?
End of explanation
age = 18
first_name = first_name + " " + 'Calogero'
first_name
Explanation: Remember
Variables' names:
can't start with a digit
can't contain spaces, quotation marks, or other punctuation
may contain an underscore (typically used to separate words in long variable names)
Underscores at the start like __alistairs_real_age have a special meaning
    so we won't do that until we understand the convention.
We can reassign variables and mix them
End of explanation
FIRST_NAME = FIRST_NAME + 'Calogero'
Explanation: Remember variables' names are CASE SENSITIVE
End of explanation
def print_sum(x, y):
    z = x + y
    print(z)
Explanation: FIRST_NAME IS NOT first_name
Printing variables
Do you remember our first lines of code?
End of explanation
print(first_name)
print(age)
print("Hello there")
print(1)
Explanation: print is the function we need to use when we want to print something
End of explanation
print(f"My name is {first_name} and I am {age} years old")
Explanation: As you can see we can print variables but also values
How can I print: My name is *first_name* and I am *age* old?
End of explanation
first_name = "Christian"
age = 29
print(f"My name is {first_name} and I am {age} years old")
Explanation: let's change this a little bit
End of explanation
message = f"My name is {first_name} and I am {age} years old"
print(message)
Explanation: We have 3 components here:
    * print function
    * f""
    * variables inside {}
We already know the print function , what is new here is the f"" notation.
It's a new notation called f-strings (available from Python 3.6) to format strings in Python.
Basically we put our text inside f"" and the variables we want to be replaced by their values inside curly brackets, like {first_name}.
This is a real power notation and you can it also when you create variables like this:
End of explanation
initial = "left"
position = initial
initial = "right"
Explanation: <div class="alert alert-success">
    <b>Challenges</b>: take around 5 to resolve each of the following challenges
</div>
Challenge 1
What is the final value of position?
End of explanation
s = 60
m = s * 60
m
Explanation: Challenge 2
What is this code doing?
End of explanation
string_1 = 'This is a string'
string_2 = "This is also a string"
string_3 = '''This is a multi lines
            strings and it works fine'''
string_4 = This is a multi lines
            strings and it works fine
Explanation: Recap
"Use variables to store values."
"Use print to display values."
"Variables must be created before they are used."
"Variables can be used in calculations."
"Python is case-sensitive."
"Use meaningful variable names."
Introduction to Python built-in data types
In Python there are mainly 4 data types:
Strings
Numbers
Lists
Dictionaries
Strings
End of explanation
first_name = 'Christian'
last_name = 'Barra'
name = first_name + last_name
name
# type
Explanation: We can sum string together, we concatenate them
End of explanation
name * 5
Explanation: You can also multiply a string for a number
End of explanation
name * 2
Explanation: But not I want to multiply my name for 1.5!
End of explanation
integer_1 = 1
integer_2 = 10
integer_1 + integer_2
integer_1 = 1
integer_2 = "10"
integer_1 + integer_2 
Explanation: Let's take about this error!
Numbers
So far we have seen 2 types of numbers:
    * 5 -> integer
    * 1.5 -> float
This are the main numberical types in Python
Integer is a number without decimal parts.
A float number is a rappresentation of a fraction, as a consequence is an aprozzimation!
End of explanation
## But we can do this
integer_1 = 1
integer_2 = "10"
integer_1 + int(integer_2)
Explanation: You would probably see this error very often, when you are trying to do operation between types that are not compatible
End of explanation
integer_1 = 1
integer_2 = "10"
str(integer_1) + integer_2
Explanation: This is operation is called casting, we are forcing a conversion to another type, in this case from string to int.
We can also cast to str (string) and we saw the sum (+) operation before.
python
integer_1 = 1
integer_2 = "10"
str(integer_1) + integer_2
End of explanation
int_1 = 5
float_1 = 5.5
int_1 + float_1
Explanation: What will be the result of this operation?
We can sum integers and floats together
End of explanation
float(5) + 5.5
Explanation: Internally Python does a casting conversion from int to float, basically
End of explanation
my_first_list = [1,2,3,4,5]
my_first_list
a_mixed_list = [1,2,"Ciao"]
a_mixed_list
# this is useful when you can to cast something to a list
my_first_list = list("christian")
my_first_list
my_letters = list("Christian")
my_letters
Explanation: List
I love lists!
Lists are a indexed collection of (also mixed) elements.
With mixed I mean you can put different types of variables.
This is how you create a list
End of explanation
a = [1,2,3,4,5]
b = [6,7,8,9,10]
a + b
Explanation: Lists are very flexible and they allow many operations.
For example you can sum 2 lists
End of explanation
a*3
a + a + a
Explanation: As with the strings more than summing we are concatenating our lists.
Same goes with multiplication, a * 3 is equal to a + a + a
End of explanation
l = [] # this is an empty list
l.append(1)
l
Explanation: If you want to add a new element to a list you can use append.
End of explanation
l = []
l = l + [1]
l
Explanation: HINT
Did you notice # inside the code? It's how you put comments in Python
Back to adding elements you can also use the sum operator (+) but is not really Pythonic...
End of explanation
l = [1,2,3,4,5]
l
l.pop()
l
Explanation: So, generally, just avoid this practise.
What about deleting an element?
End of explanation
l = [1,2,3,4,5]
Explanation: pop removes and returns the last element when you don't specify and index
End of explanation
l.pop(1)
l
Explanation: If you specificy and index betweenn () it will remove that element.
End of explanation
l = [1,2,3,4,5]
Explanation: I deleted the first element, index 1, why 2 has been removed?
First, lists are an indexed collection of elements, so they have and index and an order.
The index starts from 0 not from 1
So index n. 1 is the second element, while index 0 is the first element.
With this concept we can introduce the brackets notation.
End of explanation
l[0]
l[1]
Explanation: We can access an element of a list using the brackets notation with an index inside:
End of explanation
l[100000]
Explanation: The element should exist:
End of explanation
l
l[0:2]
Explanation: Otherwise we would get an error.
We can also slice lists:
End of explanation
l[-50:-20]
l[-50:20]
l[0:10000000000]
Explanation: This is what we called slicing.
Slicing is very powerful Python, is builty by, for now, 2 parts:
    * the first index of the element, this element will be included
    * the last index of element we want to consider, but it won't be included
Slicing returns a new list
2 important concepts:
    * slicing is not like accessing an element
    * slicing returns a list
    * slicing don't raise a list index out of range but returns an empty list
End of explanation
l[:]
Explanation: Time for cool tricks:
End of explanation
# From element with index 1 till the end
l[1:]
# from the beginning of the list till element with index 4, not included
l[:4]
# Element with index 4 is:
l[4]
Explanation: If you avoid putting the first index it means from the beginning
If you avoid putting the last index it means till the end of the list
You can also mix the concepts together
End of explanation
a_string = "Hello there, how is going?"
a_string[0]
a_string[4:10000]
a_string[:]
Explanation: Small disgression: back to strings
End of explanation
l = [1,2,3,4,5]
l[0] = "Ciao"
l
Explanation: Same slicing concepts can be applied to strings
Before moving to the next type
End of explanation
info_class = {
    "number_of_students": 10,
    "details": []
}
info_class
my_first_dictionary = dict(my_key="my_value")
my_first_dictionary
Explanation: This is how you change a value inside the list.
Nitty great details and best practices:
    * avoid popping with an index
    * avoid adding elements at the beggining/in the middle of your list.
Dictionary
Dictionaries are a key=value collection, they are not ordered (opposed to lists that are ordered) and you can put mixed types of variables inside (as for the lists.
This is how you create a dictionary:
End of explanation
my_first_dictionary['new_key'] = "My new key"
my_first_dictionary
Explanation: How can we add a new element to a dictionary?
We already know the brackets notation, but with dicts we use the key instead of the index
End of explanation
my_first_dictionary['new_key']
Explanation: If  we want to access the element of a dict we use the same notation
End of explanation
my_first_dictionary['an_element']
Explanation: If the element does not exist we get an error
End of explanation
my_first_dictionary.get("an_element")
Explanation: One way to avoid this is using get
End of explanation
my_first_dictionary.get("an_element", "My default value")
Explanation: If the element with key an_element does not exist we the default value, None if something is not specified
End of explanation
my_first_dictionary
del my_first_dictionary["my_key"]
my_first_dictionary
# Remeber to check if the key exists when deleting an element
del my_first_dictionary["my_key"]
# Otherwise you can use pop with a default value
my_first_dictionary.pop("my_key", "Does not exist")
Explanation: How do you delete an element?
End of explanation
my_first_dictionary = {"my_key":"my_value", "1": []}
my_second_dictionary = {"my_key":"my_2_value", "2":"my_second_value"}
my_first_dictionary.update(my_second_dictionary)
my_first_dictionary
Explanation: You can't add dicts but you can update one using values from another one, but pay attention to elements with the same keys.
End of explanation
# Now I want to add the students that I miss from the list inside the dictionary
# student n. 4 is Bartosz and number 5 is Wioleta
# Use the way that you prefer, at the end you should obtain a dict with they keys that you don't have (4,5)
list_of_student_id = [1,2,3,4,5]
student_names = {1: "Christian", 2:"Monika", 3: "Lucasz"}
# We have the dict of new students and we want to add the add this new elements to the old one
# How can we do this?
old_students = {1: "Christian", 2:"Monika", 3: "Lucasz"}
new_students = {6: "Anna", 7:"Jacek", 8: "Arnold"}
# I'd like 2 new variables, first_name and last_name
# How can you extract first_name and last_name from my_name?
my_name = "christian Calogero Barra"
Explanation: That's all for Python data types for now!
Recap
We have 4 main data types:
Strings
Numbers (Integers and floats)
Lists
Dictionaries
We can slice:
strings
lists
We can append new elements to a list
We can add new keys to a dictionary
Something that exists but we didn't talk about: tuple and set 
<div class="alert alert-success">
    <b>Challenges</b>: take around 5 to resolve each of the following challenges
</div>
End of explanation
counter = 5
if counter > 1:
    print("Greater than 1")
else:
    print("Minor of 1")
Explanation: Loops and flow controls
Loops and flow controls serve the need to control how your code is going to be executed by Python.
More or less they translate to computers this kind of actions:
    * If the fridge is empty go to the supermarket
    * For each ingredient inside the recipe cook them
    * While the house is not clean, keep cleaning
Flow controls
Flow control means to change the behaviour of your code depending from some conditions (True, False, minor, major or equal of something).
In Python we have:
* if
* else
* elif
End of explanation
# Example 2
gender = "m"
if gender == "f":
    print("oman")
elif gender == "v":
    print("man")
elif gender == "a":
    print("man")
elif gender == "f":
    print("man")
Explanation: Let's break this down:
    1. we create a new variable: counter = 5
    2. we check if counter is greater than 1
    3. we print something
    4. else is executed when counter > 1 is False
    5. we print something else
Let's look at 2 exmaples with a subtle difference
 elif stands for else if
End of explanation
for element in [1,2,3,4,5]:
    print(element)
my_string = "Christian"
for letter in my_string:
    print(letter)
my_dict = {"first_name": "Christian", "last_name": "Barra"}
for key in my_dict:
    print(key)
Explanation: In the first example the second if is something separated from the first one.
Let's explain this a little bit more.
Key points
with a chain of if elif and else only the code under the first satisfied condition is executed
== is to compare elements
!= to check if elements are not the same
>, >=, <, <= to verify if something is minor/greater/equal
Do you see that we don't have { } inside if/elif/else? Python uses indentation
For and while
For
for iterates over something, we can call this something an object
End of explanation
my_dict = {"first_name": "Christian", "last_name": "Barra"}
for item in my_dict:
    print(item)
for key in my_dict:
    print(my_dict[key])
Explanation: Note
When I normally iterate over a dictionary I get the its keys
To get also the elements I need to use items()
End of explanation
i = 8
while i < 10:
    i = i + 1 
    print(i)
x = 0
while x:
    print("Hello")
Explanation: Do you see what is happening here?
While
while is repeated till the expression results "True"
End of explanation
# Put your code here
words = ["red", "green", "blue", "yellow"]
result = ""
for word in words:
    result = result + word
print(result)
words[0] + words[1] + words[2]
empty = "-"
empty.join(words)
Explanation: <div class="alert alert-success">
    <b>Challenges</b>: take around 5 to resolve each of the following challenges
</div>
In the next challenges you will have to fill some empty spaces (____).
Feel free to scroll back to each part of our lesson
```python
Concatenate all words: ["red", "green", "blue"] => "redgreenblue"
words = ["red", "green", "blue"]
result = _
for  in _:
    
print(result)
```
End of explanation
# Put your code here
acronym = ""
for word in ["red", "green", "blue"]:
    if word[0] == 'r':
        acronym = acronym + word[0]
    elif word[0] == 'g':
        acronym = acronym + word[0]
    elif word[0] == 'b':
        acronym = acronym + word[0]
    
print(acronym.upper())
Explanation: ```python
Create acronym: ["red", "green", "blue"] => "RGB"
acronym = 
for word in ["red", "green", "blue"]:
    if  == 'r':
        acronym = 
    elif  == 'g':
        acronym = 
    elif  == 'b':
        acronym = ___
print(acronym)
```
End of explanation
# Put your code here
sentence = From a very early age, perhaps the age of five or six, 
I knew that when I grew up I should be a writer. Between the ages of about seventeen 
and twenty-four I tried to abandon this idea, 
but I did so with the consciousness that I was outraging my true nature 
and that sooner or later I should have to settle down and write books.
counter = 0
for letter in sentence:
    
    if letter == "a":
        counter += 1
        
print(counter)
Explanation: ```python
Count the number of a inside the sentence
sentence = From a very early age, perhaps the age of five or six, 
I knew that when I grew up I should be a writer. Between the ages of about seventeen 
and twenty-four I tried to abandon this idea, 
but I did so with the consciousness that I was outraging my true nature 
and that sooner or later I should have to settle down and write books.
counter = ___
for letter in sentence:
      == :
        counter = 
print(counter)
```
End of explanation
numbers = [1,2,3,4,5,6,7,8,9,10,12]
odd_numbers = []
even_numbers = []
for number in numbers:
    if number % 2 == 0:
        even_numbers = even_numbers + [number]
    else:
        odd_numbers = odd_numbers + [number]
print(even_numbers)
print(odd_numbers)
Explanation: ```python
Separate odd and even numbers
numbers = [1,2,3,4,5,6,7,8,9,10]
odd_numbers = []
even_numbers = []
for number in numbers:
    if number % 2 == 0:
        
    else:
        
print(odd_numbers)
print(even_numbers)
```
End of explanation
def my_Function():
    print("This is my function")
# This is how you calla function
my_Function()
Explanation: Functions and modules
Functions
Functions are a way to write reusable code, you write function using the def word followed my the name of the function.
End of explanation
def is_even(number):
    '''
    Return True if the number is even.
    
    False is all the other cases.
    
    This text is called docstring.
    '''
    if number % 2 == 0:
        return True
    
    return False
is_even(1)
is_even(10)
Explanation: A function generally returns something.
End of explanation
help(is_even)
def who_is_bigger(x, y):
    
    Return the greater number between x and y
    
    if x >= y:
        return x
    
    return y
who_is_bigger(1,10)
who_is_bigger(1, 10)
Explanation: Docstrings help you documenting your code.
The docstring of is_even is used by help function to provide more information about you function.
End of explanation
# this is like arguments
who_is_bigger(1,10)
# with key=value notation
who_is_bigger(x=1,y=10)
# with key=value the order is no longer important
who_is_bigger(y=10,x=1)
Explanation: You can specifiy the arguments in 2 ways:
    * like arguments
    * key=value notation
End of explanation
def say_something(message="Ciao"):
    
    Print a message, "Ciao" by default
    
    print(message)
say_something()
Explanation: Our function can accept many arguments, you can also specify default arguments:
End of explanation
def say_something(message="Ciao"):
    
    Print a message, "Ciao" by default
    
    print(message)
say_something()
Explanation: If we don't put a default for our argument and we call the function we get an error:
End of explanation
x = 10
def tell_me_the_value():
    x = 1
    print(x)
tell_me_the_value()
x = 10
def tell_me_the_value():
    print(x)
tell_me_the_value()
Explanation: Another important concept in namespace. You can think of a namespace as a personal shelves where Python put things.
Functions have a reserved namespace that is called local.
End of explanation
# Example 1
x = 10
def tell_me_the_value():
    x = "Ciao"
    def something_else(x):
        print(x)
    something_else(x)
tell_me_the_value()
x
# Example 2
x = 10
def tell_me_the_value():
    def something_else(x):
        x = 11
    something_else(x)
tell_me_the_value()
x
Explanation: This is how Python will look for variables:
Local is what we have seen with our tell_me_the_value function.
Python will first look inside the function and then outside.
End of explanation
# Example 1
x = 10
def tell_me_the_value():
    global x
    x = "Ciao"
    def something_else(x):
        print(x)
    something_else(x)
tell_me_the_value()
x
Explanation: In the example 1 python is accessing the enclosed scope, wheras in the example 2 it follow this rule:
    1. look inside the local scope -> empty
    2. look inside the enclosed scope (body of tell_me_the_value) -> empty
    3. look inside the global scope -> found (x=10)
End of explanation
# Put your code here
Explanation: global tells Python to consider a variable like a global and not as a local (as you can see x has a different value now)
HINT
The order of the parameters is important if you don't use the key=value notation.
<div class="alert alert-success">
    <b>Challenges</b>: take around 5 to resolve each of the following challenges
</div>
```python
challenge n.1
input_list = [1,2,3, None, 5]
def api_call(input_list):
    '''
    Take a list of values and then return an integer 
    with the number of numbers in that list
    '''
    counter = 0
for element in input_list:
    if type(element) is int:
        counter = counter + 1
return counter
```
End of explanation
# Copy your function here
Explanation: ```python
challenge n.2
import random
input_list = [random.randint(-1,1) for i in range(100)]
def api_call(input_list):
    '''
    Take a list of values and then it return a list with the
    same number of elements [True, False,...] where
    True if element >= 0
    False if element < 0
    '''
list_true_false = []
for element in input_list:
    if element ____ ____:
        ____
    else:
        ____
return ____
```
End of explanation
# Copy your function here
Explanation: ```python
challenge n.3
import random
input_list = [random.randint(-10,10) for i in range(100)]
def api_call(input_list):
    '''
    This function take a list of values and then return a dictionary.
The dictionary has 2 keys:
bigger_0: number of numbers inside the given list &gt; 0
lower_0: number of numbers inside the given list &lt; 0
'''
```
End of explanation
<END_TASK>