**Tuple and Set Exercises**

Tuples and sets are useful tools to work with in Python. Tuples are particularly useful, and we're going to learn how to use (and create) some useful Python functions that use them.

But first, again, let's go over a warm-up exercise together.

** Warm-up Exercise:** Write a function

`list_to_tuple`

that takes in a list `l`

and returns a tuple with the same elements in the same order.In [1]:

```
# solution 1
def list_to_tuple(l):
tup = () # empty tuple
for elem in l:
# () + () adds two tuple together
# (elem,) is a single element tuple containing just elem
tup = tup + (elem,)
return tup
# solution 2
def list_to_tuple(l):
return tuple(l)
list_to_tuple([1,2,3,4])
```

Out[1]:

** Exercise 1:** Python has a function

`enumerate`

which takes in a list `l`

and returns something that can generate the list`[(0, l[0]), (1, l[1]), ..., (len(l)-1,l[-1])]`

that is, a list of tuples pairing indices with the corresponding elements. As an example:

In [2]:

```
list(enumerate(["a","b","c"]))
```

Out[2]:

Write a function `enumerate_list`

which takes a list `l`

and returns the list generated by `list(enumerate(l))`

without calling `enumerate`

.

(solution below)

.

.

.

.

.

.

In [3]:

```
# solution
def enumerate_list(l):
new_l = []
for i in range(len(l)):
new_l.append((i,l[i]))
return new_l
enumerate_list(["a","b","c"])
```

Out[3]:

** Exercise 2:** Python also has a function

`zip`

that takes in any number of lists of the same length and returns something that can generate a list of tuples where the corresponding elements in each list are returned in order. For example:In [4]:

```
list(zip(["A","B","C"],["a","b","c"]))
```

Out[4]:

Write a function `zip_list`

that takes in two lists `l1`

and `l2`

and returns the list generated by `list(zip(l1,l2))`

without calling `zip`

.:

(solution below)

.

.

.

.

.

.

In [5]:

```
# solution
def zip_list(l1, l2):
new_l = []
for i in range(len(l1)):
new_l.append((l1[i],l2[i]))
return new_l
zip_list(["A","B","C"],["a","b","c"])
```

Out[5]:

`enumerate`

and `zip`

can actually take in more than lists. They can also take in, for example, tuples and strings. How they work isn't too important right now (we'll learn more about it next week!) but you may be interested and knowing that you can loop through them:

In [6]:

```
l1 = ["A","B","C"]
l2 = ["a","b","c"]
for index, element in enumerate(l1):
print("Element {} is {}".format(index, element))
print("")
for element1, element2 in zip(l1, l2):
print("{} is paired with {}".format(element1, element2))
```

Sets are particularly good when you often want to check if elements are contained in it. These next two exercises can give some examples.

** Exercise 3:** Write a function

`contains_all`

that takes in a list `l`

and a set `s`

and returns `True`

if every element in `l`

is contained in `s`

and returns `False`

otherwise.(solution below)

.

.

.

.

.

.

In [7]:

```
# solution 1
def contains_all(l, s):
for elem in l:
if elem not in s:
return False
return True
# solution 2, if you know about Python subset operators
def contains_all(l, s):
return set(l) <= s # subset
print(contains_all([1, 2, 2], {1, 2, 3}))
print(contains_all([1, 4], {1, 2, 3}))
```

** Exercise 4:** Write a function

`contains_half`

that takes in a list `l`

and a set `s`

and return `True`

if `l`

are contained in `s`

and returns `False`

otherwise.(solution below)

.

.

.

.

.

.

In [8]:

```
# solution
def contains_half(l, s):
count = 0
for elem in l:
if elem in s:
count += 1
return count >= len(l)/2
print(contains_half([1, 2, 3], {1, 2}))
print(contains_half([4], {1, 2}))
```

** Exercise 5:** Write a function

`prod`

that takes in two sets `s1`

and `s2`

and returns the (Cartesian) product of these two sets. That is, all tuples `(e1, e2)`

where `e1`

is in `s1`

and `e2`

is in `s2`

.(solution below)

.

.

.

.

.

.

In [9]:

```
# solution 1 using loops
def prod(s1, s2):
new_s = set()
for e1 in s1:
for e2 in s2:
new_s.add((e1,e2))
return new_s
# solution 2 using (set) comprehensions
def prod(s1, s2):
return {(e1, e2) for e1 in s1 for e2 in s2}
prod((1,2,3),('a','b','c'))
```

Out[9]: