<jupyter_start><jupyter_text>Tuples [Download exercise zip](../_static/generated/tuples.zip)[Browse files online](https://github.com/DavidLeoni/softpython-en/tree/master/tuples)A tuple in Python is an _immutable_ sequence of heterogenous elements which allows duplicates, so we can put inside the objects we want, of different types, and with repetitions.  What to do1. Unzip [exercises zip](../_static/generated/tuples.zip) in a folder, you should obtain something like this:```tuples    tuples1.ipynb    tuples1-sol.ipynb    tuples2-chal.ipynb        jupman.py         ```**WARNING: to correctly visualize the notebook, it MUST be in an unzipped folder !** 2. open Jupyter Notebook from that folder. Two things should open, first a console and then a browser. The browser should show a file list: navigate the list and open the notebook `tuples.ipynb`3. Go on reading the exercises file, sometimes you will find paragraphs marked **Exercises** which will ask to write Python commands in the following cells.  Shortcut keys:- to execute Python code inside a Jupyter cell, press `Control + Enter`- to execute Python code inside a Jupyter cell AND select next cell, press `Shift + Enter`- to execute Python code inside a Jupyter cell AND a create a new cell aftwerwards, press `Alt + Enter`- If the notebooks look stuck, try to select `Kernel -> Restart`  Creating tuplesTuples are created with round parenthesis `()` and by separating the elements with commas `,`Some example:<jupyter_code>numbers = (6,7,5,7,7,9)
print(numbers)<jupyter_output>(6, 7, 5, 7, 7, 9)<jupyter_text>**Tuples of one element:** You can create a tuple of a single element **by adding a comma after the element**:<jupyter_code>little_tup = (4,)  # notice the comma !!!<jupyter_output><empty_output><jupyter_text>Let's verify the type is the expected one:<jupyter_code>type(little_tup)<jupyter_output><empty_output><jupyter_text>To see the difference, we write down here `(4)` without comma and we verify the type of the obtained object:<jupyter_code>fake = (4)
type(fake)<jupyter_output><empty_output><jupyter_text>We see that `fake` is an `int`, because `4` has been evaluated as an expression inside round brackets so the result is the content inside the parenthesis.  Empty tupleWe can also create an empty tuple:<jupyter_code>empty = ()
print(empty)
type(empty)<jupyter_output><empty_output><jupyter_text>Tuples without bracketsWhen we assign values to some variable, (and _only_ when we assign values to variables) it is possible to use a notation like the following, in which on the left of `=` we put names of variables and on the right we place a sequence of values:<jupyter_code>a,b,c = 1, 2, 3
a
b
c<jupyter_output><empty_output><jupyter_text>If we ask ourselves what that `1,2,3` is, we can try putting on the left a single variable:<jupyter_code># WARNING: BETTER AVOID THIS!
x = 1,2,3
type(x)<jupyter_output><empty_output><jupyter_text>We see that Python considered that `1,2,3` as a tuple. Typically, you would never write assignments with less variables than values to put, but if it happens, probably you will find yourself with some undesired tuple ! **QUESTION**: Have a look at the following code snippets, and for each try guessing which result it produces (or if it gives an error)1.  ```python    z,w = 5,6    print(type(z))    print(type(w))    ```1.  ```python    a,b = 5,6    a,b = b,a    print('a=',a)    print('b=',b)    ```1.  ```python    z = 5,    print(type(z))    ```1.  ```python    z = ,    print(type(z))    ```  Heterogenous elementsIn a tuple we can put elements of different types, like numbers and strings:<jupyter_code>stuff = (4, "paper", 5, 2,"scissors", 7)
stuff
type(stuff)<jupyter_output><empty_output><jupyter_text>We can also insert other tuples:<jupyter_code>salad = ( ("lettuce", 3), ("tomatoes",9), ("carrots",4) )
salad
type(salad)<jupyter_output><empty_output><jupyter_text>And also lists:<jupyter_code>mix = ( ["when", "it", "rains"], ["I", "program"], [7,3,9] )<jupyter_output><empty_output><jupyter_text>**WARNING: avoid mutable objects inside tuples!**Inserting _mutable_ objects like lists inside tuples may cause problems in some situations like when you later want to use the tuple as element of a set or a key in a dictionary (we will see the details in the respective tutorials)     Let's see how the previous examples are represented in Python Tutor:<jupyter_code># WARNING: before using the function jupman.pytut() which follows, 
#          it is necessary to first execute this cell with Shift+Enter (once is enough)

import sys
sys.path.append('../')
import jupman
stuff = (4, "paper", 5, 2,"scissors", 7)
salad = ( ("lettuce", 3), ("tomatoes",9), ("carrots",4) )
mix = ( ["when", "it", "rains"], ["I", "program"], [7,3,9] )

jupman.pytut()<jupyter_output><empty_output><jupyter_text>Creating tuples from sequencesYou can create a tuple from any sequence, like for example a list:<jupyter_code>tuple( [8,2,5] )<jupyter_output><empty_output><jupyter_text>Or a string (which is a character sequence):<jupyter_code>tuple("abc")<jupyter_output><empty_output><jupyter_text>Creating sequences from tuples Since the tuple is a sequence, it is also possible to generate lists from tuples:<jupyter_code>list( (3,4,2,3)  )<jupyter_output><empty_output><jupyter_text>**QUESTION**: Does is it make sense creating a tuple from another tuple like this? Can we rewrite the code in a more concise way?<jupyter_code>x = (4,2,5)
y = tuple(x)<jupyter_output><empty_output><jupyter_text>**ANSWER**: since a tuple is IMMUTABLE, once we create in memory the object `(4,2,5)` we are sure nobody will modify it, so it's not necessary to create a new tuple and we can directly write:```pythonx = (4,2,5)y = x``` **QUESTION**:  Have a look at the following expressions, and for each try to guess which result produces (or if it gives an error):1.  ```python    (1.2,3.4)    ```1.  ```python        (1;2;3;4)    ```1.  ```python        (1,2;3,4)    ```1.  ```python        (1,2,3,4)    ```1.  ```python        (())    ```1.  ```python        type(())    ```1.  ```python        ((),)    ```1.  ```python        tuple([('a'),('b'),('c')])    ```1.  ```python        tuple(tuple(('z','u','m')))    ```1.  ```python        str(('a','b','c'))    ```1.  ```python        "".join(('a','b','c'))    ```  OperatorsThe following operators work on tuples and behave exactly as in lists:|Operator|Result|Meaning||---|---|----||`len`(tuple)|`int`|Return the length of a tuple||tuple`[`int`]`|`object`|Reads an element at specified index||tuple`[`int`:`int`]`|`tuple`| Extracts a sub-tuple - return a NEW tuple||tuple `+` tuple|`tuple`|Concatenates two tuples - return a NEW tuple||obj `in` tuple|`bool`|Checks whether an element is present in a tuple||tuple `*` int|`tuple`| Replicates the tuple - return a NEW tuple||`==`,`!=`|`bool`| Checks if two tuples are equal or different|  len`len` function returns the tuple length:<jupyter_code>len( (4,2,3) )
len( (7,) )
len( () )<jupyter_output><empty_output><jupyter_text>**QUESTION**: Have a look at following expressions, and for each try to guess the result (or if it gives an error)    1.  ```python    len(3,2,4)    ```1.  ```python        len((3,2,4))    ```1.  ```python        len(('a',))    ```1.  ```python        len(('a,'))    ```1.  ```python        len(((),(),()))    ```1.  ```python        len(len((1,2,3,4)))    ```1.  ```python        len([('d','a','c','d'),(('ab')),[('a','b','c')]])    ```  Reading an elementLike in strings and lists by using brackets we can read an element at a certain position:<jupyter_code>#      0  1  2  3
tup = (10,11,12,13)
tup[0]
tup[1]
tup[2]
tup[3]<jupyter_output><empty_output><jupyter_text>We can also use negative indexes:<jupyter_code>tup[-1]<jupyter_output><empty_output><jupyter_text>**QUESTION**: Have a look at the following expressions and for each of them try to guess the result or if it produces an error:     1.  ```python    (1,2,3)[0]    ```1.  ```python        (1,2,3)[3]    ```1.  ```python        (1,2,3)0    ```1.  ```python        ('a,')[0]    ```1.  ```python        ('a',)[0]    ```1.  ```python        (1,2,3)[-0]    ```1.  ```python        (1,2,3)[-1]    ```1.  ```python        (1,2,3)[-3]    ```1.  ```python        ()[0]    ```1.  ```python        (())[0]    ```1.  ```python        type((())[0])    ```      Exercise - animalsGiven the string `animals = "Siamese cat,dog,canary,piglet,rabbit,hamster"`1. convert it to a list2. create a tuple of tuples where each tuple has two elements: the animal name and the name length, i.e.  (("dog",3), ( "hamster",7))3. print the tupleYou should obtain:```Siamese cat,dog,canary,piglet,rabbit,hamster(('Siamese cat', 11), ('dog', 3), ('canary', 6), ('piglet', 6), ('rabbit', 6), ('hamster', 7))```* you can assume `animals` always contains exactly 6 animals<jupyter_code>#jupman-purge-output
animals = "Siamese cat,dog,canary,piglet,rabbit,hamster"

# write here
my_list = animals.split(',')

#print(animals)
print()

animals_tuple = ( (my_list[0], len(my_list[0])), 
                  (my_list[1], len(my_list[1])), 
                  (my_list[2], len(my_list[2])), 
                  (my_list[3], len(my_list[3])),
                  (my_list[4], len(my_list[4])),
                  (my_list[5], len(my_list[5])))

print(animals_tuple)<jupyter_output>(('Siamese cat', 11), ('dog', 3), ('canary', 6), ('piglet', 6), ('rabbit', 6), ('hamster', 7))<jupyter_text>SlicesAs with strings and lists, by using _slices_ we can also extract subsequences from a tuple, that is, on the right of the tuple we can write square brackets with inside a start index INCLUDED, a colon `:` and an end index EXCLUDED:<jupyter_code>tup = (10,11,12,13,14,15,16,17,18,19)
tup[2:6]  # from index 2 INCLUDED to 6 EXCLUDED<jupyter_output><empty_output><jupyter_text>It is possible to alternate the gathering of elements by adding the number of elements to skip as a third numerical parameter in the square brackets, for example:<jupyter_code>tup = (10,11,12,13,14,15,16,17)
tup[0:8:5]
tup[0:8:2]
tup[1:8:1]<jupyter_output><empty_output><jupyter_text>**WARNING: remeber that slices produce a NEW tuple !** **QUESTION**: Have a look at the following code snippets, and for each try to guess which result it produces (or if it gives an error)    1.  ```python    (7,6,8,9,5)(1:3)    ```1.  ```python        (7,6,8,9,5)[1:3]    ```1.  ```python        (10,11,12,13,14,15,16)[3:100]    ```1.  ```python        (10,11,12,13,14,15,16)[-3:5]    ```1.  ```python        (1,0,1,0,1,0)[::2]    ```1.  ```python        (1,2,3)[::1]    ```1.  ```python        (1,0,1,0,1,0)[1::2]    ```1.  ```python        tuple("postcards")[0::2]    ```1.  ```python        (4,5,6,3,4,7)[0:::2]    ```  ConcatenationIt is possible to concatenate two tuples by using the operator `+`, which creates a NEW tuple:<jupyter_code>t = (1,2,3) + (4,5,6,7,8)
t
type(t)<jupyter_output><empty_output><jupyter_text>Let's verify that original tuples are not modified:<jupyter_code>x = (1,2,3)
y = (4,5,6,7,8)
t = x + y
t
x
y<jupyter_output><empty_output><jupyter_text>Let's see how they are represented in Python Tutor:<jupyter_code># FOR PYTHON TUTOR TO WORK, REMEMBER TO EXECUTE HERE THIS CELL with Shift+Enter
#   (it's sufficient to execute it only once, it's also at the beginning of this notebook)
import sys
sys.path.append('../')
import jupman
x = (1,2,3)
y = (4,5,6,7,8)
t = x + y
print(t)
print(x)
print(y)

jupman.pytut()<jupyter_output>(1, 2, 3, 4, 5, 6, 7, 8)
(1, 2, 3)
(4, 5, 6, 7, 8)<jupyter_text>**QUESTION**: Have a look at the following code snippets, and for each try guessing which result  it produces (or if it gives an error)1.  ```python        (2,3,4) + tuple([5,6,7])    ```    1.  ```python        "crazy"+('r','o','c','k','e','t')    ```1.  ```python    ()+()    ```1.  ```python        type(()+())    ```1.  ```python        len(()+())    ```1.  ```python        ()+[]    ```1.  ```python        []+()    ```      Membership As in all sequences, if we want to verify whether an element is contained in a tuple we can use the operator `in` which returns a boolean value:<jupyter_code>'e' in ('h','e','l','m','e','t')
'z' in ('h','e','l','m','e','t')<jupyter_output><empty_output><jupyter_text>not inTo check whether something is **not** belonging to a tuple, we can use two forms:**not in - form 1**:<jupyter_code>"carrot" not in ("watermelon","banana","apple")
"watermelon" not in ("watermelon","banana","apple")<jupyter_output><empty_output><jupyter_text>**not in - form 2**<jupyter_code>not "carrot" in ("watermelon","banana","apple")
not "watermelon" in ("watermelon","banana","apple")<jupyter_output><empty_output><jupyter_text>**QUESTION**: Have a look at the following code snippets, and for each try to guess which result it produces (or if it gives an error)    1.  ```python        3 in (1.0, 2.0,3.0)    ```1.  ```python        3.0 in (1,2,3)    ```1.  ```python        3 not in (3)    ```1.  ```python        3 not in (3,)    ```1.  ```python        6 not in ()    ```1.  ```python    0 in (0)[0]    ```1.  ```python        [] in ()    ```1.  ```python        () in []    ```1.  ```python        not [] in ()    ```1.  ```python        () in ()    ```1.  ```python        () in (())    ```1.  ```python        () in ((),)    ```1.  ```python        'ciao' in ('c','i','a','o')    ```  MultiplicationTo replicate the elements in a tuple, it is possible to use the operator `*` which produces a NEW tuple:<jupyter_code>(7,8,5) * 3
(7,8,5) * 1
(7,8,5) * 0<jupyter_output><empty_output><jupyter_text>**QUESTION**: What is the following code going to print?```pythonx = (5,6,7)y = x * 3print('x=',x)print('y=',y)``` **ANWSER**: It will print:```x = (5, 6, 7)y = (5, 6, 7, 5, 6, 7, 5, 6, 7)```because the multiplication generates a NEW tuple which is associated to `y`. The tuple associated to `x` remains unchanged. **QUESTION**: Have a look at the following expressions, and for each try to guess which result it produces (or if it gives an error)    1.  ```python    (5,6,7)*(3.0)    ```1.  ```python        (5,6,7)*(3,0)    ```1.  ```python        (5,6,7)*(3)    ```1.  ```python        (5,6,7)*3    ```1.  ```python        (4,2,3)*int(3.0)    ```1.  ```python        (1,2)*[3][0]    ```1.  ```python        (1,2)*(3,4)[-1]    ```1.  ```python        [(9,8)]*4    ```1.  ```python    (1+2,3+4)*5    ```    1.  ```python    (1+2,)*4    ```1.  ```python    (1+2)*4    ```        1.  ```python    (1,2,3)*0    ```1.  ```python    (7)*0    ```1.  ```python    (7,)*0    ```  Exercise - welcomeGiven a tuple `x` containing exactly 3 integers, and a tuple `y` containing exactly 3 tuples of characters, write some code to create a tuple `z` containing each tuple of `y` replicated by the corresponding integer in `x`.Example - given:```pythonx = (2,4,3)y = (('w','e','l','c'),('o',),('m','e'))```after your code it should print:```python>>> print(z)('w', 'e', 'l', 'c', 'w', 'e', 'l', 'c', 'o', 'o', 'o', 'o', 'm', 'e', 'm', 'e', 'm', 'e')```<jupyter_code>#jupman-purge-output
x = (2,4,3)
y = (('w','e','l','c'),('o',),('m','e'))

# write here
z = y[0]*x[0] + y[1]*x[1] + y[2]*x[2] 

print(z)<jupyter_output>('w', 'e', 'l', 'c', 'w', 'e', 'l', 'c', 'o', 'o', 'o', 'o', 'm', 'e', 'm', 'e', 'm', 'e')<jupyter_text>Write an element Tuples are _immutable,_ so trying to i.e. write an assignment for placing the number `12` into the cell at index `3` provokes an error: ```python      0 1 2 3 4tup = (5,8,7,9,11)tup[3] = 666---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last) in       1 tup = (5,8,7,9,11)----> 2 tup[3] = 666TypeError: 'tuple' object does not support item assignment``` What we can do is to create a NEW tuple by composing it from sequences takes from the original one:<jupyter_code>#      0  1  2  3  4  5  6
tup = (17,54,34,87,26,95,34)
tup =  tup[0:3] + (12,) + tup[4:]
tup<jupyter_output><empty_output><jupyter_text>**WARNING:** `append`, `extend`, `insert`, `sort` **DO NOT WORK WITH TUPLES !**All the methods you used to modify lists will _not_ work with tuples.   Exercise - badmodTry writing down here  `(1,2,3).append(4)` and see which error appears:<jupyter_code># write here<jupyter_output><empty_output><jupyter_text>Exercise -  abdeGiven a tuple `x`, save in a variable `y` another tuple containing:* at the beginning, the same elements of `x` _except_ the last one* at the end, the elements `'d'` and `'e'` . * Your code should work with _any_ tuple `x`Example - given:```pythonx = ('a','b','c')```after your code, you should see printed:```bashx = ('a', 'b', 'c')y = ('a', 'b', 'd', 'e')```<jupyter_code>#jupman-purge-output
x = ('a','b','c')

# write here
y = x[:-1] + ('d','e')

print('x=',x)
print('y=',y)<jupyter_output>x= ('a', 'b', 'c')
y= ('a', 'b', 'd', 'e')<jupyter_text>Exercise - charismaticGiven a tuple `t` having alternating uppercase / lowercase characters, write some code which modifies the assignment of `t` so that `t` becomes equal to a tuple having all characters lowercase as first ones and all uppercase characters as last ones.Example - given:```pythont = ('C', 'h','A', 'r', 'I', 's', 'M', 'a', 'T', 'i', 'C')```after your code it must result:```python>>> print(t)('C', 'A', 'I', 'M', 'T', 'C', 'h', 'r', 's', 'a', 'i')```<jupyter_code>#jupman-purge-output
t = ('C', 'h','A', 'r', 'I', 's', 'M', 'a', 'T', 'i', 'C')

# write here
t = t[::2] + t[1::2]
print(t)<jupyter_output>('C', 'A', 'I', 'M', 'T', 'C', 'h', 'r', 's', 'a', 'i')<jupyter_text>Exercise - sortingGiven a tuple `x` of unordered numbers, write some code which changes the assignment of `x` so that `x` results assigned to a sorted tuple* your code must work for _any_ tuple `x`* **HINT**: as we've already written, tuples DO NOT have `sort` method (because it would mutate them), but lists have it ...Example - given:```pythonx = (3,4,2,5,5,5,2,3)```after your code it must result: ```python>>> print(x)(2, 2, 3, 3, 4, 5, 5, 5)```<jupyter_code>#jupman-purge-output
x = (3,4,2,5,5,5,2,3)

# write here
y = list(x)
y.sort()
x = tuple(y)
print(x)<jupyter_output>(2, 2, 3, 3, 4, 5, 5, 5)<jupyter_text>MethodsTuples are objects of type `typle` and have methods which allows to operate on them:|Method|Return|Description||-------|------|-----------||`tuple.index(obj)`|`int`|Searches for the first occurence of an element and returns its position||`tuple.count(obj)`|`int`|Count the occurrences of an element|  `index` method `index` method allows to find the index of the FIRST occurrence of an element.<jupyter_code>tup = ('b','a','r','a','t','t','o')
tup.index('b')
tup.index('a')
tup.index('t')<jupyter_output><empty_output><jupyter_text>If the element we're looking for is not present, we will get an error: ```python>>> tup.index('z')---------------------------------------------------------------------------ValueError                                Traceback (most recent call last) in ----> 1 tup.index('z')ValueError: tuple.index(x): x not in tuple``` Optionally, you can specify an index to start searching from (**included**):<jupyter_code># 0   1   2   3   4   5   6   7   8
('b','a','r','a','t','t','a','r','e').index('r',3)<jupyter_output><empty_output><jupyter_text>and also where to end (**excluded**): ```python 0   1   2   3   4   5   6   7   8('b','a','r','a','t','t','a','r','e').index('r',3,7)---------------------------------------------------------------------------ValueError                                Traceback (most recent call last) in       1  0   1   2   3   4   5   6   7   8----> 2 ('b','a','r','a','t','t','a','r','e').index('r',3,7)ValueError: tuple.index(x): x not in tuple```  Do not abuse index    **WARNING**: `index` **is often used in a wrong / inefficient ways**Always ask yourself:    1. Could the tuple contain duplicates? Remember only the _first_ will be found!2. Could the tuple _not_ contain  the searched element?  Remember to also handle this case!3. `index` performs a search on all the tuple, which could be inefficient: is it really needed, or do we already know the interval where to search?4. If we want to know if an `element` is in a position we already know (i.e. `3`), `index` is useless, it's enough to write `my_tuple[3] == element`. If you used `index`, it could discover duplicate characters which are _before_ or _after_ the one we are interested in! **QUESTION**: Have a look at the following expressions, and for each try to guess which result (or if it gives an error)    1.  ```python    (3,4,2).index(4)    ```1.  ```python        (3,4,---1).index(-1)    ```1.  ```python        (2.2,.2,2,).index(2)    ```1.  ```python        (3,4,2).index(len([3,8,2,9]))    ```1.  ```python        (6,6,6).index(666)    ```1.  ```python        (4,2,3).index(3).index(3)    ```1.  ```python        tuple("GUG").index("g")    ```1.  ```python        (tuple("ci") + ("a","o")).index('a')    ```    1.  ```python        (()).index(())    ```1.  ```python        ((),).index(())    ```  Exercise - The chinese boxesWrite some code which searches the word `"Chinese"` in each of 3 tuples nested into each other, printing the actual position relative to the tuple which contains the occurrance.- the tuples always start with 4 stringsExample - given:```pythontup = ('Open','The','Chinese','Boxes', ('Boxes','Open','The','Chinese', ('Chinese', 'Open','The','Boxes')))```after your code, it must print:```('Open', 'The', 'Chinese', 'Boxes') contains Chinese at position 2('Boxes', 'Open', 'The', 'Chinese') contains Chinese at position 3('Chinese', 'Open', 'The', 'Boxes') contains Chinese at position 0```<jupyter_code>#jupman-purge-output
word = 'Chinese'
tup = ('Open','The','Chinese','Boxes', ('Boxes','Open','The','Chinese', ('Chinese', 'Open','The','Boxes')))
#                    2                                        3           0        

#word = 'c'
#tup = ('a','b','c','d',('e','c','g','h',('a','b','d','c')))
#                2            1                        3

# write here

t1 = tup[:4]
t2 = tup[4][:4]
t3 = tup[4][4] 
i1 = t1.index(word)
i2 = t2.index(word)
i3 = t3.index(word)

print(t1,"contains", word, "at position", i1)
print(t2,"contains", word, "at position", i2)
print(t3,"contains", word, "at position", i3)<jupyter_output>('Open', 'The', 'Chinese', 'Boxes') contains Chinese at position 2
('Boxes', 'Open', 'The', 'Chinese') contains Chinese at position 3
('Chinese', 'Open', 'The', 'Boxes') contains Chinese at position 0<jupyter_text>`count` methodWe can obtain the number of occurrences of a certain element in a list by using the method `count`:<jupyter_code>t = ('a', 'c', 'a', 'd', 'e', 'm', 'i', 'a')
t.count('a')
t.count('d')<jupyter_output><empty_output><jupyter_text>If an element is not present `0` is returned:<jupyter_code>t.count('z')<jupyter_output><empty_output><jupyter_text>Do not abuse count    **WARNING**: `count` **is often used in a wrong / inefficient ways**Always ask yourself:    1. Could the tuple contain duplicates? Remember only the _first_ will be found!2. Could the tuple _not_ contain the element to count?  Remember to also handle this case!3. `count` performs a search on all the tuple, which could be inefficient: is it really needed, or do we already know the interval where to search? **QUESTION**: Have a look at the following expressions, and for each try to guess which result (or if it gives an error)1.  ```python    ('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count('o')    ```1.  ```python    ('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count( ('o') )    ```1.  ```python    ('p', 'o', 'r', 't', 'e', 'n', 't', 'o', 's', 'o').count( ('o',) )    ```    1.  ```python    (1,0,0,0).count( 0 )    ```            1.  ```python    (1,0,0,0).count( (0) )    ```        1.  ```python    (1,0,0,0).count( (0,) )    ```    1.  ```python    (1,0,(0,),(0,)).count( (0,) )    ```        1.  ```python    (1,0,(0.0),((0,0),(0,0))).count( (0,0) )    ```          Exercise - fruitsGiven the string `s = "apple|pear|apple|cherry|pear|apple|pear|pear|cherry|pear|strawberry"`Insert the elements separated by `"|"` (pipe character) in a list.    1. How many elements must the list have?2. Knowing the list created at previous point has only four distinct elements (es `"apple"`, `"pear"`, `"cherry"`, and `"strawberry"`), create another list where each element is a tuple containing the name of the fruit and its multiplicity (that is, the number of times it appears in the original list).Example - given:```pythoncounts = [("apple", 3), ("pear",5), ...]```Here you can write code which works given a specific constant, so you don't need cycles.3. Print the content of each tuple in a separate line (i.e.: first libe; `"apple"` is present 3 times)You should obtain:```bash[('apple', 3), ('pear', 5), ('cherry', 2), ('strawberry', 1)]apple is present 3 timespear is present 5 timescherry is present 2 timesstrawberry is present 1 times```<jupyter_code>s = "apple|pear|apple|cherry|pear|apple|pear|pear|cherry|pear|strawberry"

# write here

words = s.split("|")
#print(words)

tapples = ("apple", words.count("apple"))
tpears = ("pear", words.count("pear"))
tcherries = ("cherry", words.count("cherry"))
tstrawberries = ("strawberry", words.count("strawberry"))
counts =[tapples, tpears, tcherries, tstrawberries]

print(counts) 
print()
print(tapples[0], "is present", tapples[1], "times")
print(tpears[0], "is present", tpears[1], "times")
print(tcherries[0], "is present", tcherries[1], "times")
print(tstrawberries[0], "is present", tstrawberries[1], "times")<jupyter_output>[('apple', 3), ('pear', 5), ('cherry', 2), ('strawberry', 1)]

apple is present 3 times
pear is present 5 times
cherry is present 2 times
strawberry is present 1 times
{'fraction_non_alphanumeric': 0.19491129785247432, 'fraction_numerical': 0.032407407407407406, 'mean_word_length': 3.9036627241510873, 'pattern_counts': {'":': 0, '<': 152, '<?xml version=': 0, '>': 168, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '40', 'dir': 'jupyter-structured-clean-dedup', 'id': '265360', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 9307, 'n_tokens_neox': 8889, 'n_words': 2928, 'path': 'tuples/tuples1-sol.ipynb', 'repo_name': 'simoneb1x/softpython-en', 'size': '25704'}