├── OOP_abstraction.py ├── OOP_encapsulation.py ├── OOP_inheritance.py ├── OOP_polymorphism.py ├── README.md ├── args_kwargs_exercises.js ├── forestfires.csv ├── led_board.py ├── list_dict_comprehension_exercises.md ├── nursery_v1.py └── rural_fires.csv /OOP_abstraction.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Use an abstract base class (ABC) from Python’s abc module. 3 | This will enforce that all subclasses of Tray must implement the report_status method. 4 | ''' 5 | 6 | import sys 7 | from abc import ABC, abstractmethod 8 | 9 | class Tray(ABC): 10 | def __init__(self, species, number_of_plants): 11 | if int(number_of_plants) < 1: 12 | sys.exit('Number of plants has to be at least one') 13 | if type(species) != str: 14 | sys.exit('Species should be a string') 15 | self.species = species 16 | self.number_of_plants = number_of_plants 17 | self.is_usable = True 18 | 19 | def is_empty(self): 20 | return self.number_of_plants == 0 21 | 22 | # Abstract method that must be implemented by subclasses 23 | @abstractmethod 24 | def report_status(self): 25 | pass 26 | 27 | class SingleUseTray(Tray): 28 | def __init__(self, species, number_of_plants): 29 | super().__init__(species, number_of_plants) 30 | 31 | def remove_plants(self): 32 | if not self.is_usable: 33 | sys.exit('This tray cannot be used anymore') 34 | self.is_usable = False 35 | return [Plant(self.species) for _ in range(self.number_of_plants)] 36 | 37 | # Implementation of the abstract method 38 | def report_status(self): 39 | if not self.is_usable: 40 | return "This single-use tray has been used and is now empty." 41 | else: 42 | return f"This single-use tray contains {self.number_of_plants} {self.species} plants and is ready to use." 43 | 44 | class MultipleUseTray(Tray): 45 | def __init__(self, species, number_of_plants): 46 | super().__init__(species, number_of_plants) 47 | self.number_of_uses = 0 48 | 49 | def remove_plants(self, number): 50 | if number > self.number_of_plants: 51 | sys.exit(f'The tray only contains {self.number_of_plants} {self.species}') 52 | self.number_of_plants -= number 53 | return [Plant(self.species) for _ in range(number)] 54 | 55 | def add_seeds(self, number): 56 | if number > 0: 57 | self.number_of_plants += number 58 | 59 | # Implementation of the abstract method 60 | def report_status(self): 61 | if self.is_empty(): 62 | return "This multiple-use tray is empty but can be refilled with seeds." 63 | else: 64 | return f"This multiple-use tray has {self.number_of_plants} {self.species} plants and is reusable." 65 | 66 | class Plant: 67 | def __init__(self, species): 68 | if type(species) != str: 69 | sys.exit('Species should be a string') 70 | self.species = species 71 | 72 | def __repr__(self): 73 | return f'{self.species}' 74 | 75 | # Create tray objects 76 | stray = SingleUseTray('Rose', 3) 77 | mtray = MultipleUseTray('Lily', 4) 78 | 79 | # Remove and add to the trays 80 | plants_from_stray = stray.remove_plants() 81 | mtray.add_seeds(2) 82 | plants_from_mtray = mtray.remove_plants(5) 83 | 84 | # Print tray status reports 85 | print(stray.report_status()) 86 | print(mtray.report_status()) 87 | -------------------------------------------------------------------------------- /OOP_encapsulation.py: -------------------------------------------------------------------------------- 1 | class Tray: 2 | def __init__(self, seed_type, num_of_seeds): 3 | # Public attributes 4 | self.seed_type = seed_type 5 | self.num_of_seeds = num_of_seeds 6 | 7 | # Private attribute (encapsulation) 8 | self.__growth_stage = "Seed" 9 | 10 | # Public getter method to access the current growth stage 11 | def get_growth_stage(self): 12 | return self.__growth_stage 13 | 14 | # Public setter method to change the growth stage 15 | def set_growth_stage(self, stage): 16 | valid_stages = ["Seed", "Sprout", "Seedling", "Mature Plant"] 17 | if stage in valid_stages: 18 | self.__growth_stage = stage 19 | else: 20 | print(f"Invalid growth stage: {stage}") 21 | 22 | # Public method to simulate plant growth 23 | def grow_plants(self): 24 | if self.__growth_stage == "Seed": 25 | self.__growth_stage = "Sprout" 26 | elif self.__growth_stage == "Sprout": 27 | self.__growth_stage = "Seedling" 28 | elif self.__growth_stage == "Seedling": 29 | self.__growth_stage = "Mature Plant" 30 | else: 31 | print("Plants are already fully grown!") 32 | 33 | # Example usage 34 | tray = Tray("Tomato", 30) 35 | print("Seed Type:", tray.seed_type) 36 | print("Number of Seeds:", tray.num_of_seeds) 37 | print("Current Growth Stage:", tray.get_growth_stage()) 38 | 39 | # Using the setter to update growth stage 40 | tray.set_growth_stage("Seedling") 41 | print("Growth Stage after setter:", tray.get_growth_stage()) 42 | 43 | # Simulate plant growth 44 | tray.grow_plants() 45 | print("Growth Stage after growing:", tray.get_growth_stage()) 46 | -------------------------------------------------------------------------------- /OOP_inheritance.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class Tray: 4 | def __init__(self,species,number_of_plants): 5 | if int(number_of_plants) < 1: 6 | sys.exit('Number of plants has to be at least one') 7 | if type(species)!=str: 8 | sys.exit('Species should be a string') 9 | self.species=species 10 | self.number_of_plants=number_of_plants 11 | self.is_usable=True 12 | 13 | def is_empty(self): 14 | return self.number_of_plants == 0 15 | 16 | def __repr__(self): 17 | return f'This tray has {self.number_of_plants} {self.species}' 18 | 19 | class SingleUseTray(Tray): 20 | def __init__(self,species,number_of_plants): 21 | super().__init__(species,number_of_plants) 22 | 23 | def remove_plants(self): # self refers to the object of the class 24 | if not self.is_usable: 25 | sys.exit('This tray cannot be used anymore') 26 | plants = [Plant(self.species) for _ in range(self.number_of_plants)] 27 | self.is_usable=False 28 | self.number_of_plants= 0 29 | return plants 30 | 31 | class MultipleUseTray(Tray): 32 | def __init__(self,species,number_of_plants): 33 | super().__init__(species,number_of_plants) 34 | self.number_of_uses=0 35 | 36 | def remove_plants(self, number): # self refers to the object of the class 37 | if number > self.number_of_plants: 38 | sys.exit(f'The tray only contains {self.number_of_plants} {self.species}') 39 | self.number_of_plants = self.number_of_plants-number 40 | return [Plant(self.species) for _ in range(number)] 41 | 42 | def add_seeds(self,number): 43 | if (number>0): 44 | self.number_of_plants += number 45 | 46 | class Plant: 47 | def __init__(self,species): 48 | if type(species)!=str: 49 | sys.exit('Species should be a string') 50 | self.species=species 51 | 52 | def __repr__(self): 53 | return f'{self.species}' 54 | 55 | 56 | # create tray objects 57 | stray=SingleUseTray('Rose',3) 58 | mtray=MultipleUseTray('Lily',4) 59 | # remove and add to the trays 60 | plants_from_stray=stray.remove_plants() 61 | mtray.add_seeds(2) 62 | plants_from_mtray=mtray.remove_plants(5) 63 | # print tray contents 64 | print(stray) 65 | print(mtray) 66 | -------------------------------------------------------------------------------- /OOP_polymorphism.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class Tray: 4 | def __init__(self,species,number_of_plants): 5 | if int(number_of_plants) < 1: 6 | sys.exit('Number of plants has to be at least one') 7 | if type(species)!=str: 8 | sys.exit('Species should be a string') 9 | self.species=species 10 | self.number_of_plants=number_of_plants 11 | self.is_usable=True 12 | 13 | def is_empty(self): 14 | return self.number_of_plants == 0 15 | 16 | def __repr__(self): 17 | return f'This tray has {self.number_of_plants} {self.species}' 18 | 19 | class SingleUseTray(Tray): 20 | def __init__(self,species,number_of_plants): 21 | super().__init__(species,number_of_plants) 22 | 23 | def remove_plants(self): # self refers to the object of the class 24 | if not self.is_usable: 25 | sys.exit('This tray cannot be used anymore') 26 | self.is_usable=False 27 | return [Plant(self.species) for _ in range(self.number_of_plants)] 28 | 29 | # example of polymorphism 30 | def __repr__(self): 31 | return f'This single use tray has {self.number_of_plants} {self.species}' 32 | 33 | 34 | class MultipleUseTray(Tray): 35 | def __init__(self,species,number_of_plants): 36 | super().__init__(species,number_of_plants) 37 | self.number_of_uses=0 38 | 39 | def remove_plants(self, number): # self refers to the object of the class 40 | if number > self.number_of_plants: 41 | sys.exit(f'The tray only contains {self.number_of_plants} {self.species}') 42 | self.number_of_plants = self.number_of_plants-number 43 | return [Plant(self.species) for _ in range(number)] 44 | 45 | def add_seeds(self,number): 46 | if (number>0): 47 | self.number_of_plants += number 48 | 49 | class Plant: 50 | def __init__(self,species): 51 | if type(species)!=str: 52 | sys.exit('Species should be a string') 53 | self.species=species 54 | 55 | def __repr__(self): 56 | return f'{self.species}' 57 | 58 | 59 | # create tray objects 60 | stray=SingleUseTray('Rose',3) 61 | mtray=MultipleUseTray('Lily',4) 62 | # remove and add to the trays 63 | plants_from_stray=stray.remove_plants() 64 | mtray.add_seeds(2) 65 | plants_from_mtray=mtray.remove_plants(5) 66 | # print tray contents 67 | print(stray) 68 | print(mtray) 69 | 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction to Python 2024/2025 2 | 3 | Masters in Data Science applied to agricultural and food sciences, environment, and forestry engineering. 4 | 5 | Instructor: Manuel Campagnolo (mlc@isa.ulisboa.pt) 6 | 7 | Teaching assistant: Dominic Welsh (djwelsh@edu.ulisboa.pt) 8 | 9 |
10 | 11 | 12 | # Online resources for the course 13 | 14 | 15 | 16 | * **Required:** [CS50’s Introduction to Programming with Python](https://cs50.harvard.edu/python/2022): lectures (videos and notes), problems sets, shorts; The platform allows you to test your code at the [CS50 codespace](https://cs50.dev/) for the proposed problems (you need to have your own GitHub account to access the codespace). 17 | * Python Programming course at [PP.fi](https://programming-23.mooc.fi/): same features as CS50 but to test your solutions to problems you are required to pass previous tests 18 | * [Learn Python](https://v2.scrimba.com/learn-python-c03): lectures (videos) and interactive examples and exercises 19 | * [Introduction to Python (VScode)](https://vscodeedu.com/courses/intro-to-python): interactive lectures and exercises 20 | * Basic concepts and features of the Python language and system: [The Python Tutorial at python.org](https://docs.python.org/3/tutorial/index.html). 21 | * Fenix webpage for the course (https://fenix.isa.ulisboa.pt/courses/intpy-283463546571610) 22 | * Moodle (https://elearning.ulisboa.pt/course/view.php?id=9100) 23 | 24 |
25 | 26 | 27 | 28 | #### Comparison of CS50P and PP.fi 29 | 30 | 31 | 32 | | CS50P | Contents | PP.fi | Contents | 33 | | ----------- | ----------- |----------- | ----------- | 34 | | Lecture 0 | Creating Code with Python; Functions; Bugs; Strings and Parameters; Formatting Strings; More on Strings; Integers or int; Readability Wins; Float Basics; More on Floats; Def; Returning Values | Part 1 | Intro; I/O; More about variables; Arithmetic operations; Conditional statements | 35 | | Lecture 1 | Conditionals, if Statements, Control FlowModulo; Creating Our Own Parity Function; Pythonic; match | Part 2 | Programming terminology; More conditionals; Combining conditions; Simple loops | 36 | | Lecture 2 | Loops; While Loops; For Loops; Improving with User Input; More About Lists; Length; Dictionaries, More on code modularity | Part 3 | Loops with conditions; Working with strings; More loops; Defining functions | 37 | | | | Part 4 | The Visual Studio Code editor, Python interpreter and built-in debugging tool; More functions; Lists; Definite iteration; Print statement formatting; More strings and lists | 38 | | | | Part 5 | More lists; References; Dictionary; Tuple | 39 | | Lecture 3 | Exceptions, Runtime Errors, try, else, Creating a Function to Get an Integer, pass | Part 6 | Reading files; Writing files; Handling errors; Local and global variables | 40 | | Lecture 4 | Libraries, Random, Statistics, Command-Line Arguments, slice, Packages, APIs, Making Your Own Libraries| Part 7 | Modules; Randomness; Times and dates; Data processing; Creating your own modules; More Python features | 41 | | Lecture 5 | Unit Tests; assert; pytest; Testing Strings; Organizing Tests into Folders | | | 42 | | Lecture 6| File I/O; open; with; CSV; Binary Files and PIL | | | 43 | | Lecture 7 | Regular Expressions; Case Sensitivity; Cleaning Up User Input; Extracting User Input ||| 44 | | Lecture 8 | Object-Oriented Programming; Classes; raise; Decorators; Class Methods; Static Methods; Inheritance; Inheritance and Exceptions; Operator Overloading| Part 8 | Objects and methods; Classes and objects; Defining classes; Defining methods; More examples of classes | 45 | | | | Part 9 | Objects and references; Objects as attributes; Encapsulation; Scope of methods; Class attributes; More examples with classes | 46 | | | | Part 10 | Class hierarchies; Access modifiers; Object oriented programming techniques; Developing a larger application | 47 | | Lecture 9 | set; Global Variables; Constants; Type Hints; Docstrings; argparse; Unpacking; args and kwargs; map; List Comprehensions; filter; Dictionary Comprehensions; enumerate; Generators and Iterators | Part 11 | List comprehensions; More comprehensions; Recursion; More recursion examples | 48 | | | | Part 12 | Functions as arguments; Generators; Functional programming; Regular expressions| 49 | 50 |
51 |
52 | 53 |
54 | 55 | 56 | # Class 1 (September 13, 2024): data types, variables, functions 57 | 58 | 59 | 60 | 1. Install Python and VS code: https://code.visualstudio.com/docs/python/python-tutorial. Alternatively, you can code in the CS50 cloud environment (VScode). Two steps: 1. log in into your github account; 2. access your code space at https://cs50.dev/. This environment allows you to test automatically your scripts for the CS50 problem sets. 61 | 2. Some useful keyworks for the command line interface (CLI) in terminal: 62 | * `code filename.py` to create a new file 63 | * `ls` to list files in folder 64 | * `cp filename newfilename` to copy a file, e.g. `cp ..\hello.py farewell.py` (`..` represents parent folder) 65 | * `mv filename newfilename` to rename or move file, e.g. `my farewell.py goodbye.py` or `mv farewell.py ..` (move one folder up) 66 | * `rm filename` to delete (remove) file 67 | * `mkdir foldername` to create new folder 68 | * `cd foldername` change directory, e.g. `cd ..` 69 | * `rmdir foldername` to delete folder 70 | * `clear` to clear terminal window 71 | 3. The REPL (interactive Read -Eval-Print-Loop) environment: see https://realpython.com/interacting-with-python/ 72 | 4. All values in Python have a **type**. The five basic types are: integer, float, string, Boolean, and None. 73 | * strings (`str`), variables, print (a function), parameters (e.g. `end=`), input, comments, formatted strings (`f"..."`), `.strip()`, `.title` (methods) 74 | * integers (`int`), operations for integers, casting (e.g. `str`to `int`) 75 | * floating point values (`float`), round, format floats (e.g. `f"{z:.2f}`) 76 | * `True`, `False`, `and`, `or`, `not` 77 | 5. Functions, `def`, `return` 78 | 6. Suggested problems: [CS50 Problem set 0](https://cs50.harvard.edu/python/2022/psets/0/) 79 |
80 | 81 |
82 | 83 | 84 | 85 | # Class 2 (September 20, 2024): conditionals, lists, dictionaries 86 | 87 | 88 | 89 | 1. Conditionals: 90 | - `if`, `elif`, `else`: 91 | ``` 92 | if score >= 70: 93 | print("Grade: C to A") 94 | elif score >= 60: 95 | print("Grade: D") 96 | else: 97 | print("Grade: F") 98 | ``` 99 | - `match`: 100 | ``` 101 | match species: 102 | case 'versicolor': 103 | label=0 104 | case 'virginica' 105 | label=1 106 | case _: 107 | label=2 108 | ``` 109 | 4. Pythonic coding: `def main()`, define other functions, call `main()`. The code must be modular. 110 | 5. While loops, for loops, `break`, `break` and `return` 111 | 6. Data type *list* `[]`: methods `append`, `extend` 112 | 7. Data type *dictionary* `{}`, `items()`, keys `.key()` and values `.values()` 113 | ``` 114 | knights = {'gallahad': 'the pure', 'robin': 'the brave'} 115 | for k, v in knights.items(): 116 | print(k, v) 117 | if 'gallahad' in knights: 118 | print('Go Gallahad') 119 | ``` 120 | 9. Suggested problems: [CS50 Problem set 1 and 2](https://cs50.harvard.edu/python/2022/psets/). See the assignment on Moodle: problems [File extensions](https://cs50.harvard.edu/python/2022/psets/1/extensions/), [Coke machine](https://cs50.harvard.edu/python/2022/psets/2/coke/), [Plates](https://cs50.harvard.edu/python/2022/psets/2/plates/) 121 | 122 |
123 | 124 |
125 | 126 | 127 | 128 | # Class 3 (September 27, 2024): exercises, best practices 129 | 130 | 131 | 132 | Exercises from [CS50 Problem set 0, 1 and 2](https://cs50.harvard.edu/python/2022/psets/). 133 | 134 |
135 | 136 |
137 | 138 | 139 | # Class 4 (October 4, 2024): handling exceptions 140 | 141 | 142 | 143 | Handling exceptions in Python: raising and catching exceptions. 144 | 145 | 1. Example from (https://cs50.harvard.edu/python/2022/shorts/handling_exceptions/). Exercise: adapt the proposed code to be more modular, where the main function is something like the one below: 146 | 147 | ``` 148 | def main(): 149 | spacecraft = input("Enter a spacecraft: ") 150 | au=get_au(spacecraft) 151 | m = convert(au) 152 | print(f"{m} m") 153 | ``` 154 | 155 | 2. Exercises from [CS50 Problem set 3](https://cs50.harvard.edu/python/2022/psets/3/). 156 | 157 | For the *fuel gauge* problem (https://cs50.harvard.edu/python/2022/psets/3/fuel/), try to organize your code as follows. As suggested in *hints*, you should catch `ValueError` and `ZeroDivisionError` exceptions in your code. In the code below, the user is being asked for correct values for `x,y` until they satisfy the requirements: `x,y` must be inputted as a string `x/y`, `x` has to be less or equal to `y`, and `y` cannot be zero. The function `get_string_of_integers_X_less_than_Y` in the code below should take care of that. 158 | 159 | ``` 160 | def main(): 161 | # asks user for input until the input is as expected 162 | x,y=get_string_of_integers_X_less_than_Y() 163 | # compute percentage from two integers 164 | p=compute_percentage(x,y) 165 | # print output 166 | print_gauge(p) 167 | ``` 168 | 169 | 3. A few examples of code that can be helpful to solve problems in problem set 3: 170 | 171 | Example of basic use of `try-except` to catch a `ValueError`: 172 | ``` 173 | try: 174 | x = int(input("What's x?")) 175 | except ValueError: 176 | print("x is not an integer") 177 | else: 178 | print(f"x is {x}") 179 | ``` 180 | 181 | Function for requesting an integer from the user until no exceptions are caught: 182 | ``` 183 | def get_int(): 184 | while True: 185 | try: 186 | x = int(input("What's x?")) 187 | except ValueError: 188 | print("x is not an integer") 189 | else: 190 | break 191 | return x 192 | ``` 193 | 194 | We may want to exit the execution of our script if some exception is caught. This can be done with `sys.exit()`, which can also be used to print a message. 195 | ``` 196 | import sys # import module 197 | try: 198 | x = int(input("What's x?")) 199 | except ValueError: 200 | sys.exit("x is not an integer") 201 | ``` 202 | 203 | Example of code that catches `CRTL-C` or `CRTL-D`: 204 | 205 | ``` 206 | while True: 207 | try: 208 | x=int(input()) 209 | except ValueError: 210 | print('x is not integer') 211 | except KeyboardInterrupt: #CTRL-C 212 | print('\n KeyboardInterrupt') 213 | break 214 | except EOFError: # CTRL-D 215 | print('\n EOFError') 216 | break 217 | else: 218 | print(x) 219 | ``` 220 | 221 | For a list of Python Built-in Exceptions, you can explore (https://www.w3schools.com/python/python_ref_exceptions.asp) 222 |
223 | 224 |
225 | 226 | 227 | # Class 5 (October 11, 2024): libraries, modules, APIs 228 | 229 | 230 | 231 | ### Modules 232 | You can store your own functions in modules (which are just python scripts) and `import` then into your main code. Let's imagine you created a file named `mymodule.py` in a given folder. In your main script, you can import the file if the folder belongs to list of folders the Python interpreter will look for. You can check that by running the following lines of codes in the Python interpreter: 233 | ``` 234 | >>>import sys 235 | >>>sys.path 236 | ``` 237 | If the folder where `mymodule.py` was created does not belong to that list, you can add it with `sys.path.append` which allows you to import your module. To that end, you can include the followings lines to your main script: 238 | ``` 239 | import sys 240 | sys.path.append(r'path-to-folder') # folder where mymodule is 241 | import mymodule 242 | ``` 243 | where `path-to-folder` is the path that you can easily copy in your IDE. 244 | 245 | If your module includes a function named, say, `get_integer`, you can then use the function in your main script either by calling `mymodule.get_integer()` or you can instead load the function with `from mymodule import get_integer` and then just call it with `get_integer()` in the main script as in the following script. 246 | ``` 247 | import sys 248 | sys.path.append(r'/workspaces/8834091/modules') # where file mymodule.py is 249 | from mymodule import get_integer 250 | def main(): 251 | x=get_integer() 252 | print(x) 253 | main() 254 | ``` 255 | Contents of `mymodule.py`: 256 | ``` 257 | import sys 258 | def get_integer() -> int: 259 | while True: 260 | try: 261 | return(int(input('type a number: '))) 262 | except ValueError: 263 | print('not an integer number: try again') 264 | except KeyboardInterrupt: #CTRL-C 265 | print('\n If you want to exit type CTRL-D') 266 | except EOFError: # CTRL-D 267 | sys.exit('\n exit as requested') 268 | ``` 269 | 270 | Often, you import a module that is available at (https://pypi.org/project/pip/). Say you want to load the module `random` which provides a series of functions for sampling, shuffling, and extracting random numbers from a variety of probability distributions. If the module is not already available, you can typically load it in your terminal with 271 | ``` 272 | $pip install random 273 | ``` 274 | and then import it on your main script with `import random`. If you want to know which is the folder where the module is located, you can get that information with `random.__file__`. 275 | 276 | ### `sys.argv` 277 | Previously, we used module `sys`, in particular functions `sys.exit()` and `sys.path`. Another useful function is `sys.argv`, that allows you to have access to what the user typed in at the command line `$` as in 278 | ``` 279 | import sys 280 | print(len(sys.argv)) # returns the number of words in the command line after $python 281 | print(sys.argv[1]) # returns the 2nd word, i.e., the first word after $python myscript.py 282 | ``` 283 | 284 | For instance, the following script named `sum.py` prints the sum of two numbers that were specified in the command line with `$python sum.py 1.2 4.3`: 285 | ``` 286 | import sys 287 | try: 288 | x,y = float(sys.argv[1]), float(sys.argv[2]) 289 | print('the sum is',x+y) 290 | except IndexError: 291 | print('missing argument') 292 | except ValueError: 293 | print('The arguments are not numbers') 294 | ``` 295 | ### APIs 296 | *Application program interfaces* allow you to communicate with a remote server. For instance, `requests` is a package that allows your program to behave as a web browser would. Consider the following script `myrequest.py` that allows you to explore the *itunes* database (https://performance-partners.apple.com/search-api): 297 | ``` 298 | import requests 299 | import sys 300 | try: 301 | response = requests.get("https://itunes.apple.com/search?entity=song&limit=1&term=" + sys.argv[1]) 302 | print(response.json()) 303 | except IndexError: 304 | sys.exit('Missing argument') 305 | except requests.RequestException: 306 | sys.exit('Request failed') 307 | ``` 308 | You can easily adapt that code to access a different database. For instance if you want to explore the GBIF database (https://data-blog.gbif.org/post/gbif-api-beginners-guide/), you can just replace the main line of code in `myrequest.py` with 309 | ``` 310 | response=requests.get('https://api.gbif.org/v1/species/match?name='+ sys.argv[1]) 311 | ``` 312 | and execute it with, say, `$python myrequest.py Tracheophyta` in the terminal. 313 | 314 | There are many ways of running an API in Python. The following example shows how you can access satellite imagery through the *Google Earth Engine* API and compute the mean land surface temperature at some location from the MODIS11 product. To be able to use the API, you need to have a Google account, and an earth engine project associated to it. 315 | ``` 316 | # pip install earthengine-api 317 | import ee 318 | # Trigger the authentication flow. 319 | ee.Authenticate() 320 | # Initialize the library. 321 | ee.Initialize(project='project-name') # e.g. 'ee-my-mlc-math-isa-utl' 322 | # Import the MODIS land surface temperature collection. 323 | lst = ee.ImageCollection('MODIS/006/MOD11A1') 324 | # Selection of appropriate bands and dates for LST. 325 | lst = lst.select('LST_Day_1km', 'QC_Day').filterDate('2020-01-01', '2024-01-01') 326 | # Define the urban location of interest as a point near Lyon, France. 327 | u_lon = 4.8148 328 | u_lat = 45.7758 329 | u_poi = ee.Geometry.Point(u_lon, u_lat) 330 | scale = 1000 # scale in meters 331 | # Calculate and print the mean value of the LST collection at the point. 332 | lst_urban_point = lst.mean().sample(u_poi, scale).first().get('LST_Day_1km').getInfo() 333 | print('Average daytime LST at urban point:', round(lst_urban_point*0.02 -273.15, 2), '°C') 334 | ``` 335 | 336 | ### Problems 337 | Solve problems from CS50P [Problem_set_4](https://cs50.harvard.edu/python/2022/psets/4/). In particular, for problem *Bitcoin price index* organize your code so the main function is the following: 338 | 339 | ``` 340 | def main(): 341 | x=read_command_line_input() 342 | price=get_bitcoin_price() 343 | print(f"${x*price:,.4f}") 344 | ``` 345 |
346 | 347 |
348 | 349 | 350 | # Class 6 (October 18, 2024): virtual environments; file I/O 351 | 352 | 353 | 354 | ### Virtual environments in Python 355 | 356 | A virtual environment (https://docs.python.org/3/library/venv.html) is: 357 | - Used to contain a specific Python interpreter and software libraries and binaries which are needed to support a project (library or application). These are by default isolated from software in other virtual environments and Python interpreters and libraries installed in the operating system. 358 | - Contained in a directory, conventionally named `.venv` or `venv` in the project directory, or under a container directory for lots of virtual environments. 359 | - Not checked into source control systems such as Git. 360 | - Considered as disposable – it should be simple to delete and recreate it from scratch. You don’t place any project code in the environment. 361 | - Not considered as movable or copyable – you just recreate the same environment in the target location. 362 | 363 | In your system you have the *base* environment by default, and you can create one or more *virtual environments*. Below, we describe how to create a virtual environment and how to activate it, so you commands in terminal are interpreted within that environment. That allows you to encapsulate in each virtual environment you create a given Python version, and a set of Python packages with their given versions. Your data and script files remain on the usual working folders: they should not be moved to the folders where the virtual environment files are stored. 364 | 365 | The following commands work in the [CS50 codespace](https://cs50.dev/) that runs Linux (check with `$cat /etc/os-release` in the terminal). Some need to be slightly adapted for Windows. 366 | 367 | Firstly, let's check what are the available packages and their versions in the base environment, and also let's get extra information about the package `requests` (e.g. dependencies): 368 | 369 | ``` 370 | $ pip list 371 | $ pip show requests 372 | ``` 373 | 374 | Next, let's create a virtual environment. One can first create (with `mkdir`) a folder called, say, `my_venvs` so all the virtual environments are created in that folder. This makes sense since virtual enrironment folders are created independently from the working folders that contain data and scripts. The virtual environment `myvenv` can then be created with: 375 | ``` 376 | my_venvs/ $ python3 -m venv myvenv # creates environment called myvenv with Python 3 377 | ``` 378 | In case one needs to delete the virtual environment, one just needs to delete the folder. This can be done with `$ sudo rm -rf myvenv` in the terminal (Linux). After the virtual environment has been created, one needs to activate it. In Linux, this is done by executing `activate` which lies in the `bin` folder of the virtual environment: 379 | 380 | ``` 381 | my_venvs/ $ source myvenv/bin/activate # note that activate needs to be sourced 382 | ``` 383 | As a result, the prompt shows `(myvenv) my_venvs/ $` which indicates that `myvenv` is now activated. One can check the Python version with `$python -V`. To de-activate a virtual environment, the command is `$ deactivate`. With the environment activated, let's try to install a few packages, specifying the versions. For instance, install the following packages. 384 | 385 | ``` 386 | (myvenv) my_venvs/ $ pip install random11==0.0.1 387 | (myvenv) my_venvs/ $ pip install geopy==1.23.0 388 | (myvenv) my_venvs/ $ pip install requests==2.25.0 389 | ``` 390 | Some of this packages depend on additional packages that are installed automatically. To list all instaled packages within the environment `myvenv` one can execute `(myvenv) $ pip list` as before. Compare the version of `requests` in `myvenv` with the version returned initially in the base environment: this one is 2.25.0 while the one in the base environment is more recent. One can also check where `requests` is installed in `myvenv` with the command `(myvenv) $ pip show requests`. 391 | 392 | Check the system path (where Python will look for installed packages) by executing `print(sys.path)`: one can do this from the terminal with the command 393 | ``` 394 | (myvenv) my_venvs/ $ python -c 'import sys; print(sys.path)' 395 | ``` 396 | Notice that the folder in `myvenv` where the virtual environment packages are installed is listed, but the path to where base packages are stored is not. 397 | 398 | If one wishes to share a virtual environment, the way to do that is to share a file (typically, `requirements.txt`) that allows a collaborator to re-create the environment. `requirements.txt` stores the information about the installed packages in a file in case one intends to share the environment (e.g. in GitHub). Towards that end, one needs to create `requirements.txt` with the packages names and versions, that can be used to create a clone of the environment on another machine. This is done, still within `myvenv` (i.e. with `myvenv` activated) with the following command: 399 | ``` 400 | (myvenv) my_venvs/ $ pip freeze > requirements.txt 401 | ``` 402 | Note that the file `requirements.txt` is created in the folder that contains `myvenv` and not within `myvenv` itself: this makes sense, since one does not want to store scripts or data within `myvenv` but just packages and the Python version. Since `requirements.txt` is now available, one can create a copy of `myvenv` called, say, `myvenv2`. Firstly, one needs to de-activate `myvenv`. Then, the commands to be executed in the terminal are: 403 | ``` 404 | my_venvs/ $ python3 - m venv myvenv2 # create new virtual environment with the Python 3 interpreter called myvenv2 405 | my_venvs/ $ source myvenv2/bin/activate # activate myvenv2 406 | (myvenv2) my_venvs/ $ pip install -r requirements.txt # install packages and versions listed in requirements.txt 407 | ``` 408 | 409 | Exercise: go back to `myvenv`, add package (say, `emoji==0.1.0`), re-build `requirements.txt`, and create new environment `myvenv3` and install the set of packages listed in the new `requirements.txt`. 410 | 411 | ### File I/O 412 | 413 | As discussed in (https://cs50.harvard.edu/python/2022/notes/6/) `open` is a functionality built into Python that allows you to open a file and utilize it in your program. The open function allows you to open a file such that you can read from it or write to it. The most basic way to use `open` allow us to enable file I/O with respect to a given file. In the example below, `w` is the argument value that indicates that the file is open in writing mode. The instruction `file.write(...)` will entirely rewrite the file, deleting the previous contents. 414 | ``` 415 | name='Bob' 416 | file = open("names.txt", "w") 417 | file.write(name) 418 | file.close() 419 | ``` 420 | As an alternative, if the goal is to add new contents to the file, which is appended to the existent content, then `w` should be replaced by `a` (append). Each call to `file.write(name)` will then add the value of `name` to the end of `file`. 421 | 422 | Instead of explicitly opening and closing a file, it's simpler to use the so-called *context manager* in Python, using the keyword `with`, which automatically closes the file: 423 | ``` 424 | with open("names.txt", "w") as f: 425 | f.write(name) 426 | ``` 427 | If one wishes to read from a file, then the file has to be opened in reading mode as in the following example. The method `readlines` reads all lines of the file, and stores them in a list, where each element of the list is the contents of the corresponding line. 428 | ``` 429 | with open("names.txt", "r") as f: 430 | L=f.readlines(name) 431 | ``` 432 | However, it is possible to read one line at the time: 433 | ``` 434 | with open('myfile.txt','r') as f: 435 | N=0 436 | for line in f: 437 | N+=1 438 | print('number of lines', N) 439 | ``` 440 | Aa an alternative, this can be done with method `readline`. This can be included in a loop to read the whole file. Notice that when the end of the file is reached, `readline` returns the empty string, and this can be easily tested with a condition. 441 | 442 | Reading a file in Python gives the flexibility of visiting any position in the file. The initial position is 0 by default but can be instantiated with `f.seek(n)`. Then, `f.read(10)` for instance reads *n* characters from that initial position. Method `f.tell()` returns the current position in the file. 443 | 444 | A file can be of type *text* (human-readable) or *binary*. Binary files like images for instance are read with `with open('myfile.txt','rb') as f`. 445 | 446 | Exercise: Consider the file downloaded from INE (the Portuguese Institute of Statistics) about causes of fires by geographical location [rural_fires.csv](rural_fires.csv). The source is INE: "Rural fires (No.) by Geographic localization (NUTS - 2013) and Cause of fire; Annual" for 2023. Write a script to read the file and exclude the lines which are not formated as a table (header lines). The formatted lines should be written into a new file, say (`table_rural_fires.csv`). 447 | ``` 448 | with open('rural_fires.csv','rb') as f: 449 | with open('table_rural_fires.csv',"w") as fw: 450 | for line in f: 451 | if line[0] in ['1','2','3']: # or smth like line.startswith('1'): 452 | fw.write(line) 453 | ``` 454 | Since the file contains non ASCII characters, one might want to try to decode those characters correctly. Note that Python provides methods `encode` and `decode` as in the example below. 455 | ``` 456 | str_original = 'ção' 457 | bytes_encoded = str_original.encode(encoding='utf-8') 458 | print(type(bytes_encoded)) 459 | str_decoded = bytes_encoded.decode() 460 | print(type(str_decoded)) 461 | print('Encoded bytes =', bytes_encoded) 462 | print('Decoded String =', str_decoded) 463 | print('str_original equals str_decoded =', str_original == str_decoded) 464 | ``` 465 | 466 | 467 |
468 | 469 |
470 | 471 | 472 | # Class 7 (October 25, 2024): tabular data; pandas 473 | 474 | 475 | 476 | ### Create a Pandas DataFrame from scratch 477 | 478 | Pandas dataframes have an intrinsic tabular structure represented by rows and columns where each row and column has a unique *label* (name) and *position* number inside the dataframe. The row labels, called dataframe index, can be integer numbers or string values, the column labels, called column names, are usually strings. Use the following script to create a dataframe with random values. Notice the terminology for rows (`index`) and columns (`columns`). 479 | ``` 480 | import pandas as pd 481 | import numpy as np 482 | df = pd.DataFrame(np.random.randn(6, 4), index=list('abcdef'), columns=list('ABCD')) 483 | print(df) 484 | ``` 485 | Exercices: 486 | 487 | 1. print the column names of `df` with `.columns`. 488 | 2. Create a `Series` that corresponds to column `A` with `['A']` 489 | 3. Create a new dataframe that corresponds to columns `A` and `C` with `[['A','C']]`. 490 | 491 | Notice that `.columns` returns a `pd.Index` object. This is to provide extra functionality and performance compared to lists. To extract a list of names, one can use `.columns.tolist()` or `.columns.values`. 492 | 493 | ### Reading a csv file, selecting columns by name, selecting rows by condition 494 | 495 | Consider the dataset that described 517 fires from the Montesinho natural park in Portugal. For each incident weekday, month, coordinates, and the burnt area are recorded, as well as several meteorological data such as rain, temperature, humidity, and wind (https://www.kaggle.com/datasets/vikasukani/forest-firearea-datasets). For reference, a copy of the file is available [forestfires.csv](forestfires.csv). The variables are: 496 | 497 | - X - x-axis spatial coordinate within the Montesinho park map: 1 to 9 498 | - Y - y-axis spatial coordinate within the Montesinho park map: 2 to 9 499 | - month - month of the year: "Jan" to "dec" 500 | - day - day of the week: "mon" to "sun" 501 | - FFMC - FFMC index from the FWI system: 18.7 to 96.20 502 | - DMC - DMC index from the FWI system: 1.1 to 291.3 503 | - DC - DC index from the FWI system: 7.9 to 860.6 504 | - ISI - ISI index from the FWI system: 0.0 to 56.10 505 | - temp - the temperature in Celsius degrees: 2.2 to 33.30 506 | - RH - relative humidity in %: 15.0 to 100 507 | - wind - wind speed in km/h: 0.40 to 9.40 508 | - rain - outside rain in mm/m2 : 0.0 to 6.4 509 | - area - the burned area of the forest (in ha): 0.00 to 1090.84 510 | 511 | The goal is to download the file and use package `Pandas` to explore it and solve the following tasks. 512 | 513 | 1. Read the file with `pd.read_csv` into a new object `fires`, and show the first 10 rows with `fires.head(10)`. 514 | 2. Create list of column names and determine column data types with attribute `.dtypes`. 515 | 3. Print a summary of the dataframe with `.info()`. 516 | 4. Create a `Series` with the temperature values for all 517 fires. 517 | 5. Create a `DataFrame` just with columns `month` and `day`. 518 | 6. Select fires for which the temperature is higher than 25 Celsius, and between 20 and 25 Celsius; note that each condition needs to be surrounded by `(...)` and can be connected with `&` or `|` or negated with `~`. 519 | 7. Select fires that occured on weekends; use the conditional function `.isin()` 520 | 8. Check if there are no `Null` values in the dataframe with `.notna()`. You can sum along columns with `.sum()`. 521 | 522 | ### Select rows and columns with loc (label-based indexing) and iloc (positional indexing) 523 | 524 | These are operators to select rows and columns from a dataframe. `loc` selects rows and columns using the row and column *names*. `iloc` uses the *positions* in the table. Notice that new values can be assigned to selections defined with `loc`and `iloc`. 525 | 526 | 1. Interpret the result of `fires.iloc[0:3,2:4]` 527 | 2. Use `loc` and `is.in()` to select fires from August and September and just FWI based variables values for those fires. 528 | 3. Use `iloc` to select the first 20 fires and just the FWI based variables values 529 | 530 | ### Combining positional and label-based indexing 531 | 532 | There are several possibilities to combine positional and label-based indexing: 533 | 534 | 1. (with `iloc`) Using `df.columns.get_loc()` which converts the name of one column into its position. Then `iloc` can be used to perform the selection. For multiple columns determined by a list of column names, one can use instead `df.columns.get_indexer()`. Example: Use `iloc` to select the first 20 fires and just the FWI based variables values, using the names rather than the positions of those variables. Solution: `FWI_positions=fires.columns.get_indexer(['FFMC','DMC','DC','ISI'])` and ` 535 | fires.iloc[0:20,FWI_positions]` 536 | 2. (with `loc`) Using `df.index[]` to extract the index names. Then, `loc` can be used to perform the selection. Solution: `fires.loc[fires.index[0:20], ['FFMC', 'DMC', 'DC', 'ISI']]`. 537 | 538 | ### Exporting to file 539 | 540 | Exporting is done with operations named `.to_...` as listed in (https://pandas.pydata.org/docs/user_guide/io.html) 541 | 542 | 1. Export your file as an Excel spreadsheet with `.to_excel("filename.xlsx", sheetname="fires", index=False)` 543 | 2. Read an Excel spreadsheet with: `pd.read_excel("filename.xlsx", sheetname="fires", index=False)` 544 | 545 | ### Use generative AI to help with the following tasks 546 | 547 | 1. Create a dataframe `months_df` from a dictionary: for instance create a dictionary where keys are `jan`, `feb`, `mar`, for all 12 months, and the values are `January`, `February`, `March` and so on. 548 | 549 | ``` 550 | month_data = { 551 | 'Month': [ 552 | 'January', 'February', 'March', 'April', 'May', 'June', 553 | 'July', 'August', 'September', 'October', 'November', 'December' 554 | ], 555 | 'mth': [ 556 | 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 557 | 'jul', 'aug', 'sep', 'oct', 'nov', 'dec' 558 | ] 559 | } 560 | months_df = pd.DataFrame(month_data) 561 | ``` 562 | 563 | 2. Merge with new dataframe to get a new variable that contains the full name of the month. See (https://pandas.pydata.org/docs/user_guide/merging.html) 564 | 565 | ``` 566 | merged_df = pd.merge(fires, months_df, left_on='month', right_on='mth', how='left') 567 | merged_df.drop(columns='mth', inplace=True) 568 | ``` 569 | 570 |
571 | 572 |
573 | 574 | 575 | # Class 8 (November 8, 2024): pandas (cont'd), jupyter notebooks 576 | 577 | 578 | 579 | Create a jupyter notebook for this class. If you're using your CS50 codespace, create a new file in the terminal with `$code mynotebook.ipynb` and follow the suggestions for jupyter notebooks in your codespace session. 580 | 581 | There are many available *cheatsheets* for Pandas that can help visualizing Pandas' functionalities. Since there are many possibilities, a single page cheatsheet is either too limited or too cryptic. This [12-page cheatsheet](https://www.webpages.uidaho.edu/~stevel/cheatsheets/Pandas%20DataFrame%20Notes_12pages.pdf) is pretty self-contained and includes several examples. 582 | 583 | ### Use generative AI to help with the following tasks 584 | 585 | 1. Reduce the `fires` dataframe with method `.groupby` to get just one row per month, and average temperature, average RH, and number of fires per month. The goal is to create a dataframe named `firesbymonth` with columns `avg_temp`, `avg_RH` and `fire_count`. See (https://pandas.pydata.org/docs/user_guide/groupby.html) 586 | 2. What is the effect of adding the method `.reset_index()` to the previous command? 587 | 3. Sort the dataframe `firesbymonth`, such that the 12 rows are ordered by month correctly: `jan`, `feb`, `mar`, and so on. 588 | 4. Create a new column called `conditions` in `firesbymonth` of type string that indicates if a month is `dry&hot`, `dry&cold`, `wet&hot` or `wet&cold`. Use the mean values of `avg_temp` and `avg_RH` to establish the appropriate thresholds. Use method `.apply` and define the function to apply with `lambda`. 589 | 5. Re-organize the information in `fires` into a two-way table that shows the total area of fires per day of the week and per month, where `NaN` are replaced by 0. Towards that end, explore the `.pivot_table` method. 590 | 591 |
592 | 593 |
594 | 595 | 596 | # Class 9 (November 15, 2024): OOP, classes, methods 597 | 598 | 599 | 600 | Suppose that one wants write a script in python using classes to monitor plants at a nursery. Initially plants grow from seeds in trays and one wants to keep track of the trays and number of plants per tray. All plants in a given tray are from the same species. Then, at some point, some plants are transferred from trays to individual pots (one plant per pot). At the end, pots are sold. One wants to track the number of plants of each species that are in the nursery. 601 | 602 | For this type of problem, one wants to mimic entities of the real world (plants, trays, pots, and the nursery) as objects in Python code. Object-oriented programming is an intuitive form of doing so. A class in Python is an object constructor, or a *blueprint* for creating objects. 603 | 604 | The simplest example of class, with very little functionality, is a class to store constant values, which are not supposed to change. When one calls the class `Constants` defined below, an instance of the class with the two properties `MAX_PLANTS_PER_TRAY` and `SALE_PRICE` is created. 605 | ``` 606 | class Constants: 607 | MAX_PLANTS_PER_TRAY=50 608 | SALE_PRICE=10 609 | 610 | print(Constants.SALE_PRICE) 611 | ``` 612 | However, in general we intent to call the class to create one instance (one object) of the class and set the properties of that object. To indicate the values of the instance properties we use the `__init__` method: 613 | ``` 614 | class Plant: 615 | def __init__(self, species): 616 | self.species = species 617 | 618 | my_plant=Plant("Rose") # create instance where property `species` has value `Rose` 619 | print(my_plant.species) 620 | ``` 621 | Alternatively, a class can be created with the `@dataclass` decorator, see (https://docs.python.org/3/library/dataclasses.html). In this case, the `__init__` method is set automatically. 622 | ``` 623 | from dataclasses import dataclass 624 | @dataclass 625 | class Plant: 626 | species: str 627 | ``` 628 | A class can have methods, which are functions defined for objects of the class. In the example below, `Tray` is a class with properties `species` and `number_of_plants`, and methods `remove_plants` and `is_empty`. The first has one argument which is the number of plants to remove from the tray; it returns a list of objects of the class `Plant` which correspond to the plants that were removed from the tray. The method `is_empty` doesn't have an argument and returns `True` or `False`. 629 | ``` 630 | from dataclasses import dataclass 631 | 632 | @dataclass 633 | class Plant: 634 | species: str 635 | 636 | @dataclass 637 | class Tray: 638 | species: str 639 | number_of_plants: int 640 | def remove_plants(self, number): # self refers to the object of the class 641 | number=min(number,self.number_of_plants) #cannot remove more than available 642 | self.number_of_plants -= number 643 | return [Plant(self.species) for _ in range(number)] # returns list of instances of Plant 644 | def is_empty(self): # returns True of False 645 | return self.number_of_plants == 0 646 | 647 | tray=Tray('Lily', 28) 648 | plants=tray.remove_plants(10) 649 | if tray.is_empty(): 650 | print('The tray is empty') 651 | else: 652 | print('There are still', tray.number_of_plants, tray.species, 'plants in the tray') 653 | first_plant=plants[0] 654 | print('The plant removed is', first_plant.species) 655 | ``` 656 | The code for the full problem that envolves plants of several species, trays, pots and sales can be organized in the following manner: 657 | - Plant class: Simple class to represent a plant with a species. 658 | - Pot class: Holds one plant each. 659 | - Tray class: Holds plants of a single species and can remove plants. 660 | - Nursery class: Manages trays, pots, and keeps track of plant counts by species. It has methods like add_tray, transfer_to_pots, and sell_pot to handle operations for tracking and updating counts. 661 | 662 | ### Use generative AI to help with the following tasks 663 | 1. Create a script for the problem using the standard way of initializing classes with method `__init__`. Start with a simplified version of the problem where there are only trays and plants of distinct species in the nursery, which can be represented with 3 classes: `Plant`, `Tray` and `Nursery`. Trays can be created with a given number of plants of the same species, and plants can be removed from trays. The goal in this simplified version is to create the inventory that keeps track of the number of plants of each species that are in trays. 664 | 665 | One possible solution for this simplified problem that was generated by Chat GPT when asked not to use `@dataclass` is [nursery_v1.py](nursery_v1.py). Note that this code lacks the `__str__` or `__repr__` methods and therefore `print(nursery.trays)` returns a list of objects with their memory address. 666 | 667 | 2. Add a `__repr__` method similar to the one below to class `Tray` to redefine the output of `print(nursery.trays)` and make it more informative. 668 | 669 | ``` 670 | def __repr__(self): 671 | return f"Tray(species={self.species}, count={self.count})" 672 | ``` 673 | 674 | 4. Add to the previous script a class that represents pots and adapt your script accordingly. When plants are removed from trays, they are always placed in a pot (one plant per pot). The goal is that the inventory tracks the plants and the species in both trays and pots (instead of just in trays as in [nursery_v1.py](nursery_v1.py)). 675 | 676 | 5. Finally, consider that pots can be sold and therefore removed from the inventory. 677 | 678 | 6. Verify if your script removes trays that are empty from the inventory, and update it if it is not the case. 679 | 680 |
681 | 682 |
683 | 684 | 685 | # Class 10 (November 22, 2024): Basic concepts of OOP 686 | 687 | 688 | 689 | alt text 690 | 691 | The four main concepts of Object-Oriented Programming (OOP) are *Encapsulation*, *Abstraction*, *Inheritance*, and *Polymorphism*. These concepts work together to create modular, scalable, and maintainable code in object-oriented programming. 692 | 693 | This is a central topic in computer science, and therefore you can find all kind of resources about it. Among them, you can find simple descriptions of those concepts, with examples, at the following links: 694 | 1. (https://www.programiz.com/python-programming/object-oriented-programming) 695 | 2. (https://www.freecodecamp.org/news/object-oriented-programming-in-python/) 696 | 3. (https://www.w3schools.com/python/python_inheritance.asp), (https://www.w3schools.com/python/python_polymorphism.asp) 697 | 698 | Building on the plant nursery example of last class, the following scripts illustrate the implementation of those concepts: 699 | - Encapsulation: [OOP_encapsulation.py](https://github.com/isa-ulisboa/greends-ipython/blob/main/OOP_encapsulation.py) 700 | - Inheritance: [OOP_inheritance.py](https://github.com/isa-ulisboa/greends-ipython/blob/main/OOP_inheritance.py) 701 | - Polymorphism: [OOP_polymorphism.py](https://github.com/isa-ulisboa/greends-ipython/blob/main/OOP_polymorphism.py) 702 | - Abstraction: [OOP_abstraction.py](https://github.com/isa-ulisboa/greends-ipython/blob/main/OOP_abstraction.py) 703 | 704 | The next assignment will be the *Cookie jar* problem described at (https://cs50.harvard.edu/python/2022/psets/8/jar/). You will need to create a script for the problem and test it with `check50 cs50/problems/2022/python/jar`. 705 | 706 |
707 | 708 |
709 | 710 | 711 | # Class 11 (November 29, 2024): Unit tests 712 | 713 | 714 | 715 | This topic corresponds to [Section 5](https://cs50.harvard.edu/python/2022/weeks/5/) of the CS50 course: you can find the necessary resources on that link. In particular, see the short [https://cs50.harvard.edu/python/2022/shorts/pytest/](https://cs50.harvard.edu/python/2022/shorts/pytest/). 716 | 717 | The idea is to create functions in Python (the names of those functions start with `test_`) that are used to test existing functions or classes in the script. To execute the test functions we call `pytest` in the terminal [https://docs.pytest.org/](https://docs.pytest.org/) instead of `python`: 718 | 719 | ``` 720 | $ pytest - v # -v is optional for a more verbose output 721 | ``` 722 | If no arguments are given, `pytest` will execute all functions which name starts with `test_` or end with `_test` in scripts in the current directory and all its subdirectories. However, `$pytest my_file.py` will only execute the tests within that file. Moreover, `$pytest my_directory` will only execute the tests defined in files located in that directory. There are further options to select the tests to be executed with `pytest`. 723 | 724 | ### Simple example of a class and tests for that class 725 | 726 | Consider you have two python modules: one with the definition of a class and the other that implement tests over that class. 727 | ```python 728 | # farm_carbon_footprint.py 729 | 730 | import math 731 | 732 | class Farm: 733 | def __init__(self, name, area_hectares): 734 | """Initialize the farm with a name and area in hectares.""" 735 | self.name = name 736 | self.area_hectares = area_hectares 737 | self.activities = [] 738 | 739 | def add_activity(self, activity, emissions_per_unit, units): 740 | """Add an activity with emissions in kg CO2e per unit and units.""" 741 | self.activities.append((activity, emissions_per_unit, units)) 742 | 743 | def total_emissions(self): 744 | """Calculate total carbon emissions from all activities.""" 745 | return sum(emissions_per_unit * units for _, emissions_per_unit, units in self.activities) 746 | 747 | def emissions_per_hectare(self): 748 | """Calculate carbon emissions per hectare.""" 749 | if self.area_hectares == 0: 750 | raise ValueError("Farm area cannot be zero.") 751 | return self.total_emissions() / self.area_hectares 752 | 753 | def radius_circle_with_farm_area(self): 754 | """ Calculate the radius (in meters) of a circle that has the same area as the farm""" 755 | return(math.sqrt(self.area_hectares/3.1459)*100) 756 | ``` 757 | and 758 | ```python 759 | # test_farm_carbon_footprint.py 760 | 761 | import pytest 762 | from farm_carbon_footprint import Farm 763 | 764 | def test_add_activity(): 765 | farm = Farm("Green Pastures", 10) 766 | farm.add_activity("Tractor Usage", 50, 5) # 50 kg CO2e per hour, 5 hours 767 | farm.add_activity("Fertilizer Use", 10, 20) # 10 kg CO2e per kg, 20 kg 768 | assert len(farm.activities) == 2 769 | 770 | def test_total_emissions(): 771 | farm = Farm("Green Pastures", 10) 772 | farm.add_activity("Tractor Usage", 50, 5) # 50 kg CO2e per hour, 5 hours 773 | farm.add_activity("Fertilizer Use", 10, 20) # 10 kg CO2e per kg, 20 kg 774 | assert farm.total_emissions() == 450 # 250 + 200 775 | 776 | def test_emissions_per_hectare(): 777 | farm = Farm("Green Pastures", 10) 778 | farm.add_activity("Tractor Usage", 50, 5) # 50 kg CO2e per hour, 5 hours 779 | farm.add_activity("Fertilizer Use", 10, 20) # 10 kg CO2e per kg, 20 kg 780 | assert farm.emissions_per_hectare() == 45 # 450 total / 10 hectares 781 | 782 | def test_emissions_per_hectare_zero_area(): 783 | farm = Farm("Tiny Farm", 0) 784 | farm.add_activity("Tractor Usage", 50, 2) # 50 kg CO2e per hour, 2 hours 785 | with pytest.raises(ValueError, match="Farm area cannot be zero."): # optional: matches Value Error message in emissions_per_hectare() 786 | farm.emissions_per_hectare() 787 | 788 | def test_radius_of_circle_with_farm_area(): 789 | farm = Farm("Circle Farm", 1) 790 | assert farm.radius_circle_with_farm_area() == pytest.approx(56.38, abs=0.1) 791 | farm = Farm("Circle Farm", 10) 792 | assert farm.radius_circle_with_farm_area() == pytest.approx(178.3, abs=0.01) 793 | ``` 794 | Adapt the `Farm` class definition and `test_farm_carbon_footprint.py` in order to: 795 | 796 | 1. Add a method `.number_of_activities()` to class `Farm` that returns the number of activities. Check the correctness of that method with a new test in `test_farm_carbon_footprint.py`. 797 | 2. Adapt the `Farm`class so `ValueError` should be raised if the property `area_hectares` is negative when you try to create an instance of `Farm`. Check with a new test in `test_farm_carbon_footprint.py` that the behavior of the class is as expected when `area_hectares` is negative. 798 | 799 |
800 | 801 |
802 | 803 | 804 | # Class 12 (December 6, 2024): Lists and dictionaries: packing, args and kwargs, comprehension 805 | 806 | 807 | 808 | ## 1. The packing/unpacking operators * and ** 809 | 810 | The packing/unpacking operators allows us to deal with structures of variable length. The example below illustrates *packing* several numbers into a list. 811 | ```python 812 | x=[1,2,3,4,5,6,7,8,9] 813 | a,*b,c=x # b is the list [2,3,4,5,6,7,8] 814 | print(a,b,c) 815 | ``` 816 | The same operator can be used to unpack: 817 | ```python 818 | list1=[1,2,3] 819 | list2=[6,7,8] 820 | new_list=[*list1,4,5,*list2] # values are unpacked 821 | print(new_list) 822 | ``` 823 | The * and ** operator are mostly used as arguments of functions that can accept a a variable number of arguments (like `print`): the operator * allows to pack all positional arguments into a *tuple* and the operator ** allows to pack all named arguments into a *dictionary*. In the example below, the variable `kwargs` refers to keyword arguments (i.e named arguments) . Note that one can have a combination of regular arguments, regular named arguments, *args, and **kwargs as arguments of a function, as long as keyword arguments follow positional arguments. 824 | 825 | ```python 826 | def pack(*args, **kwargs): 827 | return args,kwargs 828 | 829 | x,y=pack(1,2,10, num_years=10,rate=0.03) 830 | 831 | print('Positional arguments are packed into tuple',x) 832 | print('Named arguments are packed into dictionary',y) 833 | ``` 834 | 835 | This can be used for instance to perform computations over a variable length sequence at in the following example. 836 | ```python 837 | # Compute accumulated interest on a sequence of borrowed amounts 838 | def main(*args, **kwargs): 839 | ''' 840 | args is a tuple of amounts borrowed 841 | kwargs is a dictionary with keys num_years and rate 842 | ''' 843 | S=add(args) 844 | # Call function debt with **kwargs or kwargs 845 | D=compute_debt(S,**kwargs) # D expects a number and two named arguments with names num_years and rate 846 | # same as: 847 | D=compute_debt(S,kwargs['num_years'],kwargs['rate']) 848 | # print results 849 | print('Borrowed:',S) 850 | print('Debt:',round(D,3)) 851 | 852 | def add(values): 853 | s=0 854 | for x in values: 855 | s+=x 856 | return s 857 | 858 | def compute_debt(s,num_years,rate): 859 | for i in range(num_years): 860 | s+=s*rate 861 | return s 862 | 863 | if __name__=='__main__': 864 | main(1,2,10,5,4,num_years=10, rate=0.05) 865 | ``` 866 | 867 | ### Exercise i) Summing Arguments with `*args` 868 | Write a function `sum_all` that takes any number of positional arguments and returns their sum. 869 | 870 | ```python 871 | def sum_all(*args): 872 | pass # Your code here 873 | 874 | # Example usage: 875 | print(sum_all(1, 2, 3)) # Output: 6 876 | print(sum_all(10, 20, 30, 5)) # Output: 65 877 | ``` 878 | 879 | ### Exercise ii) Concatenate Strings with `*args` 880 | Create a function `concat_strings` that takes any number of string arguments using `*args` and concatenates them into a single string. 881 | 882 | ```python 883 | def concat_strings(*args): 884 | pass # Your code here 885 | 886 | # Example usage: 887 | print(concat_strings("Hello", " ", "world", "!")) # Output: "Hello world!" 888 | print(concat_strings("Python", " is", " fun!")) # Output: "Python is fun!" 889 | ``` 890 | 891 | ### Exercise iii) Handling Default Keyword Arguments with `**kwargs` 892 | Write a function `greet` that accepts a keyword argument `name` (default value: `"Guest"`) and an optional keyword argument `greeting` (default value: `"Hello"`). Return the formatted greeting message. 893 | 894 | ```python 895 | def greet(**kwargs): 896 | pass # Your code here 897 | 898 | # Example usage: 899 | print(greet(name="Alice", greeting="Hi")) # Output: "Hi Alice" 900 | print(greet(name="Bob")) # Output: "Hello Bob" 901 | print(greet()) # Output: "Hello Guest" 902 | ``` 903 | 904 | ### Exercise iv) Combine `*args` and `**kwargs` 905 | Write a function `describe_person` that takes positional arguments (`*args`) for hobbies and keyword arguments (`**kwargs`) for personal details (e.g., name, age). Return a formatted string describing the person. 906 | 907 | ```python 908 | def describe_person(*args, **kwargs): 909 | pass # Your code here 910 | 911 | # Example usage: 912 | print(describe_person("reading", "traveling", name="Alice", age=30)) 913 | # Output: "Alice (30 years old) enjoys reading, traveling." 914 | ``` 915 | 916 | ### Exercise v) Filter Keyword Arguments with `**kwargs` 917 | Create a function `filter_kwargs` that takes any number of keyword arguments and returns a new dictionary containing only those with values greater than 10. 918 | 919 | ```python 920 | def filter_kwargs(**kwargs): 921 | pass # Your code here 922 | 923 | # Example usage: 924 | print(filter_kwargs(a=5, b=15, c=20, d=3)) # Output: {'b': 15, 'c': 20} 925 | ``` 926 | 927 | ## 2. List and dictionary comprehension, map and filter 928 | 929 | Suppose one wants to create a list with all the cubes of even numbers up to *N*. The following scripts show how this can be done with different operators that replace the traditional *loop* structure: *list comprehension*, `filter`, `map` and `lambda` 930 | 931 | Operator `map` applies a given function to each element of a list. Likewise, `filter` applies a boolean function to filter elements of a list. Both function can be executed in parallel over the elements of the list since each output is independent of the outputs for the remainder elements of the list. 932 | 933 | * With list comprehension: 934 | ```python 935 | def cube(x): 936 | return x*x*x 937 | L=[cube(x) for x in range(N) if x%2==0] 938 | ``` 939 | 940 | * With `filter` to select even numbers and `map`to compute cubes: 941 | ```python 942 | def even(x): 943 | return x%2==0 944 | numbers=list(range(N)) 945 | even_numbers=list(filter(even, numbers)) 946 | cubes=list(map(cube,even_numbers)) 947 | ``` 948 | 949 | * Also with `filter` and `map` but defining implicitly the *cube* and *even* functions with `lambda` instead of `def`: 950 | ```python 951 | numbers=list(range(N)) 952 | even_numbers=list(filter(lambda x: x%2==0, numbers)) 953 | cubes=list(map(lambda x: x*x*x,even_numbers)) 954 | ``` 955 | 956 | * The most compact way of solving the problem involves `lambda` and list comprehension. In the example below, one needs to indicate that the $\lambda$ function has to be applied to the variable `x` in the list comprehension, using `(lambda x: x*x*x)(x)`. Otherwise, the output list would be a list of lambda functions. 957 | 958 | ```python 959 | cubes=[(lambda x: x*x*x)(x) for x in range(N) if x%2==0] 960 | ``` 961 | 962 | ### Exercise i) Convert a For Loop to List Comprehension 963 | Convert the following for loop into a list comprehension: 964 | 965 | ```python 966 | result = [] 967 | for x in range(10): 968 | result.append(x**2) 969 | # output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 970 | ``` 971 | 972 | ### Exercise ii) Filter Numbers with List Comprehension 973 | Rewrite this code using a list comprehension: 974 | 975 | ```python 976 | result = [] 977 | for x in range(20): 978 | if x % 2 == 0: 979 | result.append(x) 980 | # output: [0, 4, 16, 36, 64] 981 | ``` 982 | 983 | ### Exercise iii) Dictionary Comprehension 984 | Convert the following code to a dictionary comprehension: 985 | 986 | ```python 987 | squares = {} 988 | for x in range(5): 989 | squares[x] = x**2 990 | # output: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} 991 | ``` 992 | 993 | ### Exercise iv) Nested Loops with List Comprehension 994 | Rewrite the nested loop as a list comprehension: 995 | 996 | ```python 997 | pairs = [] 998 | for x in range(3): 999 | for y in range(2): 1000 | pairs.append((x, y)) 1001 | # output: [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)] 1002 | ``` 1003 | 1004 | ### Exercise v) Conditional Dictionary Comprehension 1005 | Transform the following code into a dictionary comprehension with a condition: 1006 | 1007 | ```python 1008 | filtered_squares = {} 1009 | for x in range(10): 1010 | if x % 2 == 0: 1011 | filtered_squares[x] = x**2 1012 | # output: {0: 0, 2: 4, 4: 16, 6: 36, 8: 64} 1013 | ``` 1014 | 1015 | ### Exercise vi) Conditional Transformation in List Comprehension 1016 | Convert the following loop into a list comprehension that includes a conditional transformation: 1017 | 1018 | ```python 1019 | result = [] 1020 | for x in range(15): 1021 | if x % 3 == 0: 1022 | result.append(x**2) 1023 | else: 1024 | result.append(x) 1025 | # output: [0, 1, 2, 9, 4, 5, 36, 7, 8, 81, 10, 11, 144, 13, 14] 1026 | ``` 1027 | 1028 | ### Exercise vii) Dictionary Comprehension with String Keys 1029 | Transform the following loop into a dictionary comprehension, using strings as keys: 1030 | 1031 | ```python 1032 | word_lengths = {} 1033 | words = ["apple", "banana", "cherry", "date"] 1034 | for word in words: 1035 | word_lengths[word] = len(word) 1036 | # output: {'apple': 5, 'banana': 6, 'cherry': 6, 'date': 4} 1037 | ``` 1038 | 1039 | ### Exercise viii) Flatten a Nested List with List Comprehension 1040 | Rewrite this code using a single list comprehension to flatten the nested list: 1041 | 1042 | ```python 1043 | nested_list = [[1, 2, 3], [4, 5], [6, 7, 8, 9]] 1044 | flattened = [] 1045 | for sublist in nested_list: 1046 | for item in sublist: 1047 | flattened.append(item) 1048 | # output: [1, 2, 3, 4, 5, 6, 7, 8, 9] 1049 | ``` 1050 | 1051 | ### Exercise ix) Conditional Dictionary Comprehension with Nested Loops 1052 | Convert the following nested loop into a dictionary comprehension with a condition: 1053 | 1054 | ```python 1055 | result = {} 1056 | for i in range(1,3): 1057 | for j in range(3, 6): 1058 | if j % i != 0: 1059 | result[(i, j)] = i + j 1060 | # {(2, 3): 5, (2, 5): 7} 1061 | ``` 1062 | 1063 | 1064 | ### Exercise x) Filter and Transform Nested Dictionaries 1065 | Use a dictionary comprehension to filter and transform the following dictionary of dictionaries: 1066 | 1067 | ```python 1068 | data = { 1069 | "A": {"score": 90, "passed": True}, 1070 | "B": {"score": 65, "passed": False}, 1071 | "C": {"score": 75, "passed": True}, 1072 | "D": {"score": 50, "passed": False}, 1073 | } 1074 | 1075 | # Goal: Include only students who passed, and create a dictionary of their scores. 1076 | result = {} 1077 | for key, value in data.items(): 1078 | if value["passed"]: 1079 | result[key] = value["score"] 1080 | # output: {'A': 90, 'C': 75} 1081 | ``` 1082 |
1083 | 1084 |
1085 | 1086 | 1087 | # Class 13 (December 13, 2024): Introduction to IoT with Raspberry Pi 1088 | 1089 | 1090 | 1091 | In this class we use Python to control physical devices through GPIO (general-purpose input/output) ports on a Raspberry Pi microcomputer. We will rely on the `gpiozero` Python package [https://gpiozero.readthedocs.io/en/latest/recipes.html](https://gpiozero.readthedocs.io/en/latest/recipes.html). 1092 | 1093 | Topics of the class: 1094 | - Raspberry Pi (RPi) and PiOS (Linux) 1095 | - Retrive local address of the Raspberry Pi with `hostname -I` 1096 | - Accessing RPi remotely with `ssh` (secure shell) 1097 | - Connecting RPi to a breadboard using the *gpio* pins 1098 | - Using the *nano* text editor to create scripts 1099 | - Running scripts in RPi with `sudo python3 test.py` 1100 | - Implementing some basic recipes from `gpio zero` documentation that use the following physical devices: leds, buttons, and a line sensor 1101 | 1102 | ### Exercises with Raspberry Pi, breadboard, led, button and connection wires: 1103 | 1104 | 1. [Blink LED](https://gpiozero.readthedocs.io/en/latest/recipes.html#led) 1105 | 2. [Check if button is pressed](https://gpiozero.readthedocs.io/en/latest/recipes.html#button) 1106 | 3. [Button controlled LED](https://gpiozero.readthedocs.io/en/latest/recipes.html#button-controlled-led) 1107 | 1108 |
1109 | 1110 |
1111 | 1112 | 1113 | # Class 14 (December 20, 2024): Introduction to IoT with Raspberry Pi (cont'd) 1114 | 1115 | 1116 | 1117 | ### Exercises for led board with gpiozero (cont'd) 1118 | 1. [LED_board](https://gpiozero.readthedocs.io/en/latest/recipes.html#ledboard). Interpret the code and verify that it is behaving as expected. 1119 | 1120 | 2. Look at the [advanced recipes for LEDboard](https://gpiozero.readthedocs.io/en/latest/recipes_advanced.html#ledboard-advanced). Create a "pyramid" of lights 5-3-1-3-5, that turn on and off and pause 1 second. You can build a loop such that the pyramid runs only 4 times and the execution stops. 1121 | 1122 | 3. Adapt the code `LED_board.py` so if you execute `sudo python3 LED_morse.py some_word` the LEDs should turn on and off to encode the input word: a *dah* (-) has a duration of 2 seconds and a *dit* (.) has a duration of 1 second. After each letter, there should be a 3 second pause before the next letter. The example below should correspond to LEDs 1 and 2 being on for 3 seconds, then LEDs 1, 2 and 3 being on for 3 seconds, then LEDs 1 and 3 being on for 1 second while LED 2 is on for 3 seconds, and so on. 1123 | 1124 | ``` 1125 | −− −−− ·−· ··· · −·−· −−− −·· · 1126 | M O R S E C O D E 1127 | ``` 1128 | ### Other sensors 1129 | 1130 | There are many hardware adapters that make it easier to connect sensors to a microcomputer. Here we look at the *Raspberry Pi hat* included in the [Grove_Base_Kit_for_Raspberry_Pi](https://wiki.seeedstudio.com/Grove_Base_Kit_for_Raspberry_Pi/). The [Grove Base Hat for Raspberry Pi](https://wiki.seeedstudio.com/Grove_Base_Hat_for_Raspberry_Pi/) provides Digital/Analog/I2C/PWM/UART [ports](https://wiki.seeedstudio.com/Grove_Base_Hat_for_Raspberry_Pi/#hardware-overview) to the RPi allowing it to be connected a large range of modules. 1131 | 1132 | The following code show how to access a [temperature and humidity sensor](https://www.seeedstudio.com/Grove-Temperature-Humidity-Sensor-DHT1-p-745.html) readings programmatically. The sensor is connected to digital port D5. This code also allows access to gpio pin 17 to power a LED. 1133 | 1134 | ```python 1135 | import time 1136 | from seeed_dht import DHT 1137 | from gpiozero import LED 1138 | 1139 | led=LED(17) 1140 | # Grove - Temperature&Humidity Sensor connected to port D5 1141 | sensor = DHT('11', 5) 1142 | while True: 1143 | humi, temp = sensor.read() 1144 | print('temperature {}C, humidity {}%'.format(temp, humi)) 1145 | if humi > 85: 1146 | led.on() 1147 | else: 1148 | led.off() 1149 | time.sleep(0.5) 1150 | ``` 1151 | ### Exercises 1152 | 1153 | 1. Adapt the code above such that the LED is on when the temperature is above 24 Celsius or below 20 and is off otherwise. 1154 | 2. Interpret the code below. Create a new script that combines the temperature/humidity sensor with the ultrasonic ranger sensor and the LED. 1155 | 1156 | ```python 1157 | import time 1158 | from grove.grove_ultrasonic_ranger import GroveUltrasonicRanger 1159 | from gpiozero import LED 1160 | led=LED(17) 1161 | # Grove - Ultrasonic Ranger connected to port D5 1162 | sensor = GroveUltrasonicRanger(5) 1163 | while True: 1164 | distance = sensor.get_distance() 1165 | print('{} cm'.format(distance)) 1166 | if distance < 20: 1167 | led.on() 1168 | print('LED on') 1169 | time.sleep(0.5) 1170 | led.off() 1171 | print('LED off') 1172 | continue 1173 | time.sleep(1) 1174 | ``` 1175 | 1176 |
1177 | 1178 | 1563 | -------------------------------------------------------------------------------- /args_kwargs_exercises.js: -------------------------------------------------------------------------------- 1 | Here’s a list of 5 simple exercises to practice using `*args` and `**kwargs` in Python: 2 | 3 | --- 4 | 5 | ### **Exercise 1: Summing Arguments with `*args`** 6 | Write a function `sum_all` that takes any number of positional arguments and returns their sum. 7 | 8 | ```python 9 | def sum_all(*args): 10 | pass # Your code here 11 | 12 | # Example usage: 13 | print(sum_all(1, 2, 3)) # Output: 6 14 | print(sum_all(10, 20, 30, 5)) # Output: 65 15 | ``` 16 | 17 | --- 18 | 19 | ### **Exercise 2: Concatenate Strings with `*args`** 20 | Create a function `concat_strings` that takes any number of string arguments using `*args` and concatenates them into a single string. 21 | 22 | ```python 23 | def concat_strings(*args): 24 | pass # Your code here 25 | 26 | # Example usage: 27 | print(concat_strings("Hello", " ", "world", "!")) # Output: "Hello world!" 28 | print(concat_strings("Python", " is", " fun!")) # Output: "Python is fun!" 29 | ``` 30 | 31 | --- 32 | 33 | ### **Exercise 3: Handling Default Keyword Arguments with `**kwargs`** 34 | Write a function `greet` that accepts a keyword argument `name` (default value: `"Guest"`) and an optional keyword argument `greeting` (default value: `"Hello"`). Return the formatted greeting message. 35 | 36 | ```python 37 | def greet(**kwargs): 38 | pass # Your code here 39 | 40 | # Example usage: 41 | print(greet(name="Alice", greeting="Hi")) # Output: "Hi Alice" 42 | print(greet(name="Bob")) # Output: "Hello Bob" 43 | print(greet()) # Output: "Hello Guest" 44 | ``` 45 | 46 | --- 47 | 48 | ### **Exercise 4: Combine `*args` and `**kwargs`** 49 | Write a function `describe_person` that takes positional arguments (`*args`) for hobbies and keyword arguments (`**kwargs`) for personal details (e.g., name, age). Return a formatted string describing the person. 50 | 51 | ```python 52 | def describe_person(*args, **kwargs): 53 | pass # Your code here 54 | 55 | # Example usage: 56 | print(describe_person("reading", "traveling", name="Alice", age=30)) 57 | # Output: "Alice (30 years old) enjoys reading, traveling." 58 | ``` 59 | 60 | --- 61 | 62 | ### **Exercise 5: Filter Keyword Arguments with `**kwargs`** 63 | Create a function `filter_kwargs` that takes any number of keyword arguments and returns a new dictionary containing only those with values greater than 10. 64 | 65 | ```python 66 | def filter_kwargs(**kwargs): 67 | pass # Your code here 68 | 69 | # Example usage: 70 | print(filter_kwargs(a=5, b=15, c=20, d=3)) # Output: {'b': 15, 'c': 20} 71 | ``` 72 | 73 | --- 74 | 75 | These exercises progressively build skills in handling `*args` and `**kwargs`, covering positional and keyword arguments, defaults, and combining both! 76 | -------------------------------------------------------------------------------- /forestfires.csv: -------------------------------------------------------------------------------- 1 | X,Y,month,day,FFMC,DMC,DC,ISI,temp,RH,wind,rain,area 2 | 7,5,mar,fri,86.2,26.2,94.3,5.1,8.2,51,6.7,0,0 3 | 7,4,oct,tue,90.6,35.4,669.1,6.7,18,33,0.9,0,0 4 | 7,4,oct,sat,90.6,43.7,686.9,6.7,14.6,33,1.3,0,0 5 | 8,6,mar,fri,91.7,33.3,77.5,9,8.3,97,4,0.2,0 6 | 8,6,mar,sun,89.3,51.3,102.2,9.6,11.4,99,1.8,0,0 7 | 8,6,aug,sun,92.3,85.3,488,14.7,22.2,29,5.4,0,0 8 | 8,6,aug,mon,92.3,88.9,495.6,8.5,24.1,27,3.1,0,0 9 | 8,6,aug,mon,91.5,145.4,608.2,10.7,8,86,2.2,0,0 10 | 8,6,sep,tue,91,129.5,692.6,7,13.1,63,5.4,0,0 11 | 7,5,sep,sat,92.5,88,698.6,7.1,22.8,40,4,0,0 12 | 7,5,sep,sat,92.5,88,698.6,7.1,17.8,51,7.2,0,0 13 | 7,5,sep,sat,92.8,73.2,713,22.6,19.3,38,4,0,0 14 | 6,5,aug,fri,63.5,70.8,665.3,0.8,17,72,6.7,0,0 15 | 6,5,sep,mon,90.9,126.5,686.5,7,21.3,42,2.2,0,0 16 | 6,5,sep,wed,92.9,133.3,699.6,9.2,26.4,21,4.5,0,0 17 | 6,5,sep,fri,93.3,141.2,713.9,13.9,22.9,44,5.4,0,0 18 | 5,5,mar,sat,91.7,35.8,80.8,7.8,15.1,27,5.4,0,0 19 | 8,5,oct,mon,84.9,32.8,664.2,3,16.7,47,4.9,0,0 20 | 6,4,mar,wed,89.2,27.9,70.8,6.3,15.9,35,4,0,0 21 | 6,4,apr,sat,86.3,27.4,97.1,5.1,9.3,44,4.5,0,0 22 | 6,4,sep,tue,91,129.5,692.6,7,18.3,40,2.7,0,0 23 | 5,4,sep,mon,91.8,78.5,724.3,9.2,19.1,38,2.7,0,0 24 | 7,4,jun,sun,94.3,96.3,200,56.1,21,44,4.5,0,0 25 | 7,4,aug,sat,90.2,110.9,537.4,6.2,19.5,43,5.8,0,0 26 | 7,4,aug,sat,93.5,139.4,594.2,20.3,23.7,32,5.8,0,0 27 | 7,4,aug,sun,91.4,142.4,601.4,10.6,16.3,60,5.4,0,0 28 | 7,4,sep,fri,92.4,117.9,668,12.2,19,34,5.8,0,0 29 | 7,4,sep,mon,90.9,126.5,686.5,7,19.4,48,1.3,0,0 30 | 6,3,sep,sat,93.4,145.4,721.4,8.1,30.2,24,2.7,0,0 31 | 6,3,sep,sun,93.5,149.3,728.6,8.1,22.8,39,3.6,0,0 32 | 6,3,sep,fri,94.3,85.1,692.3,15.9,25.4,24,3.6,0,0 33 | 6,3,sep,mon,88.6,91.8,709.9,7.1,11.2,78,7.6,0,0 34 | 6,3,sep,fri,88.6,69.7,706.8,5.8,20.6,37,1.8,0,0 35 | 6,3,sep,sun,91.7,75.6,718.3,7.8,17.7,39,3.6,0,0 36 | 6,3,sep,mon,91.8,78.5,724.3,9.2,21.2,32,2.7,0,0 37 | 6,3,sep,tue,90.3,80.7,730.2,6.3,18.2,62,4.5,0,0 38 | 6,3,oct,tue,90.6,35.4,669.1,6.7,21.7,24,4.5,0,0 39 | 7,4,oct,fri,90,41.5,682.6,8.7,11.3,60,5.4,0,0 40 | 7,3,oct,sat,90.6,43.7,686.9,6.7,17.8,27,4,0,0 41 | 4,4,mar,tue,88.1,25.7,67.6,3.8,14.1,43,2.7,0,0 42 | 4,4,jul,tue,79.5,60.6,366.7,1.5,23.3,37,3.1,0,0 43 | 4,4,aug,sat,90.2,96.9,624.2,8.9,18.4,42,6.7,0,0 44 | 4,4,aug,tue,94.8,108.3,647.1,17,16.6,54,5.4,0,0 45 | 4,4,sep,sat,92.5,88,698.6,7.1,19.6,48,2.7,0,0 46 | 4,4,sep,wed,90.1,82.9,735.7,6.2,12.9,74,4.9,0,0 47 | 5,6,sep,wed,94.3,85.1,692.3,15.9,25.9,24,4,0,0 48 | 5,6,sep,mon,90.9,126.5,686.5,7,14.7,70,3.6,0,0 49 | 6,6,jul,mon,94.2,62.3,442.9,11,23,36,3.1,0,0 50 | 4,4,mar,mon,87.2,23.9,64.7,4.1,11.8,35,1.8,0,0 51 | 4,4,mar,mon,87.6,52.2,103.8,5,11,46,5.8,0,0 52 | 4,4,sep,thu,92.9,137,706.4,9.2,20.8,17,1.3,0,0 53 | 4,3,aug,sun,90.2,99.6,631.2,6.3,21.5,34,2.2,0,0 54 | 4,3,aug,wed,92.1,111.2,654.1,9.6,20.4,42,4.9,0,0 55 | 4,3,aug,wed,92.1,111.2,654.1,9.6,20.4,42,4.9,0,0 56 | 4,3,aug,thu,91.7,114.3,661.3,6.3,17.6,45,3.6,0,0 57 | 4,3,sep,thu,92.9,137,706.4,9.2,27.7,24,2.2,0,0 58 | 4,3,sep,tue,90.3,80.7,730.2,6.3,17.8,63,4.9,0,0 59 | 4,3,oct,sun,92.6,46.5,691.8,8.8,13.8,50,2.7,0,0 60 | 2,2,feb,mon,84,9.3,34,2.1,13.9,40,5.4,0,0 61 | 2,2,feb,fri,86.6,13.2,43,5.3,12.3,51,0.9,0,0 62 | 2,2,mar,sun,89.3,51.3,102.2,9.6,11.5,39,5.8,0,0 63 | 2,2,mar,sun,89.3,51.3,102.2,9.6,5.5,59,6.3,0,0 64 | 2,2,aug,thu,93,75.3,466.6,7.7,18.8,35,4.9,0,0 65 | 2,2,aug,sun,90.2,99.6,631.2,6.3,20.8,33,2.7,0,0 66 | 2,2,aug,mon,91.1,103.2,638.8,5.8,23.1,31,3.1,0,0 67 | 2,2,aug,thu,91.7,114.3,661.3,6.3,18.6,44,4.5,0,0 68 | 2,2,sep,fri,92.4,117.9,668,12.2,23,37,4.5,0,0 69 | 2,2,sep,fri,92.4,117.9,668,12.2,19.6,33,5.4,0,0 70 | 2,2,sep,fri,92.4,117.9,668,12.2,19.6,33,6.3,0,0 71 | 4,5,mar,fri,91.7,33.3,77.5,9,17.2,26,4.5,0,0 72 | 4,5,mar,fri,91.2,48.3,97.8,12.5,15.8,27,7.6,0,0 73 | 4,5,sep,fri,94.3,85.1,692.3,15.9,17.7,37,3.6,0,0 74 | 5,4,mar,fri,91.7,33.3,77.5,9,15.6,25,6.3,0,0 75 | 5,4,aug,tue,88.8,147.3,614.5,9,17.3,43,4.5,0,0 76 | 5,4,sep,fri,93.3,141.2,713.9,13.9,27.6,30,1.3,0,0 77 | 9,9,feb,thu,84.2,6.8,26.6,7.7,6.7,79,3.1,0,0 78 | 9,9,feb,fri,86.6,13.2,43,5.3,15.7,43,3.1,0,0 79 | 1,3,mar,mon,87.6,52.2,103.8,5,8.3,72,3.1,0,0 80 | 1,2,aug,fri,90.1,108,529.8,12.5,14.7,66,2.7,0,0 81 | 1,2,aug,tue,91,121.2,561.6,7,21.6,19,6.7,0,0 82 | 1,2,aug,sun,91.4,142.4,601.4,10.6,19.5,39,6.3,0,0 83 | 1,2,aug,sun,90.2,99.6,631.2,6.3,17.9,44,2.2,0,0 84 | 1,2,aug,tue,94.8,108.3,647.1,17,18.6,51,4.5,0,0 85 | 1,2,aug,wed,92.1,111.2,654.1,9.6,16.6,47,0.9,0,0 86 | 1,2,aug,thu,91.7,114.3,661.3,6.3,20.2,45,3.6,0,0 87 | 1,2,sep,thu,92.9,137,706.4,9.2,21.5,15,0.9,0,0 88 | 1,2,sep,thu,92.9,137,706.4,9.2,25.4,27,2.2,0,0 89 | 1,2,sep,thu,92.9,137,706.4,9.2,22.4,34,2.2,0,0 90 | 1,2,sep,sun,93.5,149.3,728.6,8.1,25.3,36,3.6,0,0 91 | 6,5,mar,sat,91.7,35.8,80.8,7.8,17.4,25,4.9,0,0 92 | 6,5,aug,sat,90.2,96.9,624.2,8.9,14.7,59,5.8,0,0 93 | 8,6,mar,fri,91.7,35.8,80.8,7.8,17.4,24,5.4,0,0 94 | 8,6,aug,sun,92.3,85.3,488,14.7,20.8,32,6.3,0,0 95 | 8,6,aug,sun,91.4,142.4,601.4,10.6,18.2,43,4.9,0,0 96 | 8,6,aug,mon,91.1,103.2,638.8,5.8,23.4,22,2.7,0,0 97 | 4,4,sep,sun,89.7,90,704.4,4.8,17.8,64,1.3,0,0 98 | 3,4,feb,sat,83.9,8,30.2,2.6,12.7,48,1.8,0,0 99 | 3,4,mar,sat,69,2.4,15.5,0.7,17.4,24,5.4,0,0 100 | 3,4,aug,sun,91.4,142.4,601.4,10.6,11.6,87,4.5,0,0 101 | 3,4,aug,sun,91.4,142.4,601.4,10.6,19.8,39,5.4,0,0 102 | 3,4,aug,sun,91.4,142.4,601.4,10.6,19.8,39,5.4,0,0 103 | 3,4,aug,tue,88.8,147.3,614.5,9,14.4,66,5.4,0,0 104 | 2,4,aug,tue,94.8,108.3,647.1,17,20.1,40,4,0,0 105 | 2,4,sep,sat,92.5,121.1,674.4,8.6,24.1,29,4.5,0,0 106 | 2,4,jan,sat,82.1,3.7,9.3,2.9,5.3,78,3.1,0,0 107 | 4,5,mar,fri,85.9,19.5,57.3,2.8,12.7,52,6.3,0,0 108 | 4,5,mar,thu,91.4,30.7,74.3,7.5,18.2,29,3.1,0,0 109 | 4,5,aug,sun,90.2,99.6,631.2,6.3,21.4,33,3.1,0,0 110 | 4,5,sep,sat,92.5,88,698.6,7.1,20.3,45,3.1,0,0 111 | 4,5,sep,mon,88.6,91.8,709.9,7.1,17.4,56,5.4,0,0 112 | 4,4,mar,fri,85.9,19.5,57.3,2.8,13.7,43,5.8,0,0 113 | 3,4,mar,fri,91.7,33.3,77.5,9,18.8,18,4.5,0,0 114 | 3,4,sep,sun,89.7,90,704.4,4.8,22.8,39,3.6,0,0 115 | 3,4,sep,mon,91.8,78.5,724.3,9.2,18.9,35,2.7,0,0 116 | 3,4,mar,tue,88.1,25.7,67.6,3.8,15.8,27,7.6,0,0 117 | 3,5,mar,tue,88.1,25.7,67.6,3.8,15.5,27,6.3,0,0 118 | 3,4,mar,sat,91.7,35.8,80.8,7.8,11.6,30,6.3,0,0 119 | 3,4,mar,sat,91.7,35.8,80.8,7.8,15.2,27,4.9,0,0 120 | 3,4,mar,mon,90.1,39.7,86.6,6.2,10.6,30,4,0,0 121 | 3,4,aug,thu,93,75.3,466.6,7.7,19.6,36,3.1,0,0 122 | 3,4,aug,mon,91.5,145.4,608.2,10.7,10.3,74,2.2,0,0 123 | 3,4,aug,mon,91.5,145.4,608.2,10.7,17.1,43,5.4,0,0 124 | 3,4,sep,sun,92.4,124.1,680.7,8.5,22.5,42,5.4,0,0 125 | 3,4,sep,tue,84.4,73.4,671.9,3.2,17.9,45,3.1,0,0 126 | 3,4,sep,fri,94.3,85.1,692.3,15.9,19.8,50,5.4,0,0 127 | 3,4,oct,sun,92.6,46.5,691.8,8.8,20.6,24,5.4,0,0 128 | 3,5,mar,mon,87.6,52.2,103.8,5,9,49,2.2,0,0 129 | 3,5,sep,fri,93.5,149.3,728.6,8.1,17.2,43,3.1,0,0 130 | 3,5,oct,wed,91.4,37.9,673.8,5.2,15.9,46,3.6,0,0 131 | 2,5,oct,sun,92.6,46.5,691.8,8.8,15.4,35,0.9,0,0 132 | 4,6,feb,sat,68.2,21.5,87.2,0.8,15.4,40,2.7,0,0 133 | 4,6,mar,mon,87.2,23.9,64.7,4.1,14,39,3.1,0,0 134 | 4,6,mar,sun,89.3,51.3,102.2,9.6,10.6,46,4.9,0,0 135 | 4,6,sep,thu,93.7,80.9,685.2,17.9,17.6,42,3.1,0,0 136 | 3,5,mar,tue,88.1,25.7,67.6,3.8,14.9,38,2.7,0,0 137 | 3,5,aug,sat,93.5,139.4,594.2,20.3,17.6,52,5.8,0,0 138 | 3,6,sep,sun,92.4,124.1,680.7,8.5,17.2,58,1.3,0,0 139 | 3,6,sep,mon,90.9,126.5,686.5,7,15.6,66,3.1,0,0 140 | 9,9,jul,tue,85.8,48.3,313.4,3.9,18,42,2.7,0,0.36 141 | 1,4,sep,tue,91,129.5,692.6,7,21.7,38,2.2,0,0.43 142 | 2,5,sep,mon,90.9,126.5,686.5,7,21.9,39,1.8,0,0.47 143 | 1,2,aug,wed,95.5,99.9,513.3,13.2,23.3,31,4.5,0,0.55 144 | 8,6,aug,fri,90.1,108,529.8,12.5,21.2,51,8.9,0,0.61 145 | 1,2,jul,sat,90,51.3,296.3,8.7,16.6,53,5.4,0,0.71 146 | 2,5,aug,wed,95.5,99.9,513.3,13.2,23.8,32,5.4,0,0.77 147 | 6,5,aug,thu,95.2,131.7,578.8,10.4,27.4,22,4,0,0.9 148 | 5,4,mar,mon,90.1,39.7,86.6,6.2,13.2,40,5.4,0,0.95 149 | 8,3,sep,tue,84.4,73.4,671.9,3.2,24.2,28,3.6,0,0.96 150 | 2,2,aug,tue,94.8,108.3,647.1,17,17.4,43,6.7,0,1.07 151 | 8,6,sep,thu,93.7,80.9,685.2,17.9,23.7,25,4.5,0,1.12 152 | 6,5,jun,fri,92.5,56.4,433.3,7.1,23.2,39,5.4,0,1.19 153 | 9,9,jul,sun,90.1,68.6,355.2,7.2,24.8,29,2.2,0,1.36 154 | 3,4,jul,sat,90.1,51.2,424.1,6.2,24.6,43,1.8,0,1.43 155 | 5,4,sep,fri,94.3,85.1,692.3,15.9,20.1,47,4.9,0,1.46 156 | 1,5,sep,sat,93.4,145.4,721.4,8.1,29.6,27,2.7,0,1.46 157 | 7,4,aug,sun,94.8,108.3,647.1,17,16.4,47,1.3,0,1.56 158 | 2,4,sep,sat,93.4,145.4,721.4,8.1,28.6,27,2.2,0,1.61 159 | 2,2,aug,wed,92.1,111.2,654.1,9.6,18.4,45,3.6,0,1.63 160 | 2,4,aug,wed,92.1,111.2,654.1,9.6,20.5,35,4,0,1.64 161 | 7,4,sep,fri,92.4,117.9,668,12.2,19,34,5.8,0,1.69 162 | 7,4,mar,mon,90.1,39.7,86.6,6.2,16.1,29,3.1,0,1.75 163 | 6,4,aug,thu,95.2,131.7,578.8,10.4,20.3,41,4,0,1.9 164 | 6,3,mar,sat,90.6,50.1,100.4,7.8,15.2,31,8.5,0,1.94 165 | 8,6,sep,sat,92.5,121.1,674.4,8.6,17.8,56,1.8,0,1.95 166 | 8,5,sep,sun,89.7,90,704.4,4.8,17.8,67,2.2,0,2.01 167 | 6,5,mar,thu,84.9,18.2,55,3,5.3,70,4.5,0,2.14 168 | 6,5,aug,wed,92.1,111.2,654.1,9.6,16.6,47,0.9,0,2.29 169 | 6,5,aug,wed,96,127.1,570.5,16.5,23.4,33,4.5,0,2.51 170 | 6,5,mar,fri,91.2,48.3,97.8,12.5,14.6,26,9.4,0,2.53 171 | 8,6,aug,thu,95.2,131.7,578.8,10.4,20.7,45,2.2,0,2.55 172 | 5,4,sep,wed,92.9,133.3,699.6,9.2,21.9,35,1.8,0,2.57 173 | 8,6,aug,wed,85.6,90.4,609.6,6.6,17.4,50,4,0,2.69 174 | 7,4,aug,sun,91.4,142.4,601.4,10.6,20.1,39,5.4,0,2.74 175 | 4,4,sep,mon,90.9,126.5,686.5,7,17.7,39,2.2,0,3.07 176 | 1,4,aug,sat,90.2,96.9,624.2,8.9,14.2,53,1.8,0,3.5 177 | 1,4,aug,sat,90.2,96.9,624.2,8.9,20.3,39,4.9,0,4.53 178 | 6,5,apr,thu,81.5,9.1,55.2,2.7,5.8,54,5.8,0,4.61 179 | 2,5,aug,sun,90.2,99.6,631.2,6.3,19.2,44,2.7,0,4.69 180 | 2,5,sep,wed,90.1,82.9,735.7,6.2,18.3,45,2.2,0,4.88 181 | 8,6,aug,tue,88.8,147.3,614.5,9,14.4,66,5.4,0,5.23 182 | 1,3,sep,sun,92.4,124.1,680.7,8.5,23.9,32,6.7,0,5.33 183 | 8,6,oct,mon,84.9,32.8,664.2,3,19.1,32,4,0,5.44 184 | 5,4,feb,sun,86.8,15.6,48.3,3.9,12.4,53,2.2,0,6.38 185 | 7,4,oct,mon,91.7,48.5,696.1,11.1,16.8,45,4.5,0,6.83 186 | 8,6,aug,fri,93.9,135.7,586.7,15.1,20.8,34,4.9,0,6.96 187 | 2,5,sep,tue,91,129.5,692.6,7,17.6,46,3.1,0,7.04 188 | 8,6,mar,sun,89.3,51.3,102.2,9.6,11.5,39,5.8,0,7.19 189 | 1,5,sep,mon,90.9,126.5,686.5,7,21,42,2.2,0,7.3 190 | 6,4,mar,sat,90.8,41.9,89.4,7.9,13.3,42,0.9,0,7.4 191 | 7,4,mar,sun,90.7,44,92.4,5.5,11.5,60,4,0,8.24 192 | 6,5,mar,fri,91.2,48.3,97.8,12.5,11.7,33,4,0,8.31 193 | 2,5,aug,thu,95.2,131.7,578.8,10.4,24.2,28,2.7,0,8.68 194 | 2,2,aug,tue,94.8,108.3,647.1,17,24.6,22,4.5,0,8.71 195 | 4,5,sep,wed,92.9,133.3,699.6,9.2,24.3,25,4,0,9.41 196 | 2,2,aug,tue,94.8,108.3,647.1,17,24.6,22,4.5,0,10.01 197 | 2,5,aug,fri,93.9,135.7,586.7,15.1,23.5,36,5.4,0,10.02 198 | 6,5,apr,thu,81.5,9.1,55.2,2.7,5.8,54,5.8,0,10.93 199 | 4,5,sep,thu,92.9,137,706.4,9.2,21.5,15,0.9,0,11.06 200 | 3,4,sep,tue,91,129.5,692.6,7,13.9,59,6.3,0,11.24 201 | 2,4,sep,mon,63.5,70.8,665.3,0.8,22.6,38,3.6,0,11.32 202 | 1,5,sep,tue,91,129.5,692.6,7,21.6,33,2.2,0,11.53 203 | 6,5,mar,sun,90.1,37.6,83.7,7.2,12.4,54,3.6,0,12.1 204 | 7,4,feb,sun,83.9,8.7,32.1,2.1,8.8,68,2.2,0,13.05 205 | 8,6,oct,wed,91.4,37.9,673.8,5.2,20.2,37,2.7,0,13.7 206 | 5,6,mar,sat,90.6,50.1,100.4,7.8,15.1,64,4,0,13.99 207 | 4,5,sep,thu,92.9,137,706.4,9.2,22.1,34,1.8,0,14.57 208 | 2,2,aug,sat,93.5,139.4,594.2,20.3,22.9,31,7.2,0,15.45 209 | 7,5,sep,tue,91,129.5,692.6,7,20.7,37,2.2,0,17.2 210 | 6,5,sep,fri,92.4,117.9,668,12.2,19.6,33,6.3,0,19.23 211 | 8,3,sep,thu,93.7,80.9,685.2,17.9,23.2,26,4.9,0,23.41 212 | 4,4,oct,sat,90.6,43.7,686.9,6.7,18.4,25,3.1,0,24.23 213 | 7,4,aug,sat,93.5,139.4,594.2,20.3,5.1,96,5.8,0,26 214 | 7,4,sep,fri,94.3,85.1,692.3,15.9,20.1,47,4.9,0,26.13 215 | 7,3,mar,mon,87.6,52.2,103.8,5,11,46,5.8,0,27.35 216 | 4,4,mar,sat,91.7,35.8,80.8,7.8,17,27,4.9,0,28.66 217 | 4,4,mar,sat,91.7,35.8,80.8,7.8,17,27,4.9,0,28.66 218 | 4,4,sep,sun,92.4,124.1,680.7,8.5,16.9,60,1.3,0,29.48 219 | 1,3,sep,mon,88.6,91.8,709.9,7.1,12.4,73,6.3,0,30.32 220 | 4,5,sep,wed,92.9,133.3,699.6,9.2,19.4,19,1.3,0,31.72 221 | 6,5,mar,mon,90.1,39.7,86.6,6.2,15.2,27,3.1,0,31.86 222 | 8,6,aug,sun,90.2,99.6,631.2,6.3,16.2,59,3.1,0,32.07 223 | 3,4,sep,fri,93.3,141.2,713.9,13.9,18.6,49,3.6,0,35.88 224 | 4,3,mar,mon,87.6,52.2,103.8,5,11,46,5.8,0,36.85 225 | 2,2,jul,fri,88.3,150.3,309.9,6.8,13.4,79,3.6,0,37.02 226 | 7,4,sep,wed,90.1,82.9,735.7,6.2,15.4,57,4.5,0,37.71 227 | 4,4,sep,sun,93.5,149.3,728.6,8.1,22.9,39,4.9,0,48.55 228 | 7,5,oct,mon,91.7,48.5,696.1,11.1,16.1,44,4,0,49.37 229 | 8,6,aug,sat,92.2,81.8,480.8,11.9,20.1,34,4.5,0,58.3 230 | 4,6,sep,sun,93.5,149.3,728.6,8.1,28.3,26,3.1,0,64.1 231 | 8,6,aug,sat,92.2,81.8,480.8,11.9,16.4,43,4,0,71.3 232 | 4,4,sep,wed,92.9,133.3,699.6,9.2,26.4,21,4.5,0,88.49 233 | 1,5,sep,sun,93.5,149.3,728.6,8.1,27.8,27,3.1,0,95.18 234 | 6,4,sep,tue,91,129.5,692.6,7,18.7,43,2.7,0,103.39 235 | 9,4,sep,tue,84.4,73.4,671.9,3.2,24.3,36,3.1,0,105.66 236 | 4,5,sep,sat,92.5,121.1,674.4,8.6,17.7,25,3.1,0,154.88 237 | 8,6,aug,sun,91.4,142.4,601.4,10.6,19.6,41,5.8,0,196.48 238 | 2,2,sep,sat,92.5,121.1,674.4,8.6,18.2,46,1.8,0,200.94 239 | 1,2,sep,tue,91,129.5,692.6,7,18.8,40,2.2,0,212.88 240 | 6,5,sep,sat,92.5,121.1,674.4,8.6,25.1,27,4,0,1090.84 241 | 7,5,apr,sun,81.9,3,7.9,3.5,13.4,75,1.8,0,0 242 | 6,3,apr,wed,88,17.2,43.5,3.8,15.2,51,2.7,0,0 243 | 4,4,apr,fri,83,23.3,85.3,2.3,16.7,20,3.1,0,0 244 | 2,4,aug,sun,94.2,122.3,589.9,12.9,15.4,66,4,0,10.13 245 | 7,4,aug,sun,91.8,175.1,700.7,13.8,21.9,73,7.6,1,0 246 | 2,4,aug,sun,91.8,175.1,700.7,13.8,22.4,54,7.6,0,2.87 247 | 3,4,aug,sun,91.8,175.1,700.7,13.8,26.8,38,6.3,0,0.76 248 | 5,4,aug,sun,91.8,175.1,700.7,13.8,25.7,39,5.4,0,0.09 249 | 2,4,aug,wed,92.2,91.6,503.6,9.6,20.7,70,2.2,0,0.75 250 | 8,6,aug,wed,93.1,157.3,666.7,13.5,28.7,28,2.7,0,0 251 | 3,4,aug,wed,93.1,157.3,666.7,13.5,21.7,40,0.4,0,2.47 252 | 8,5,aug,wed,93.1,157.3,666.7,13.5,26.8,25,3.1,0,0.68 253 | 8,5,aug,wed,93.1,157.3,666.7,13.5,24,36,3.1,0,0.24 254 | 6,5,aug,wed,93.1,157.3,666.7,13.5,22.1,37,3.6,0,0.21 255 | 7,4,aug,thu,91.9,109.2,565.5,8,21.4,38,2.7,0,1.52 256 | 6,3,aug,thu,91.6,138.1,621.7,6.3,18.9,41,3.1,0,10.34 257 | 2,5,aug,thu,87.5,77,694.8,5,22.3,46,4,0,0 258 | 8,6,aug,sat,94.2,117.2,581.1,11,23.9,41,2.2,0,8.02 259 | 4,3,aug,sat,94.2,117.2,581.1,11,21.4,44,2.7,0,0.68 260 | 3,4,aug,sat,91.8,170.9,692.3,13.7,20.6,59,0.9,0,0 261 | 7,4,aug,sat,91.8,170.9,692.3,13.7,23.7,40,1.8,0,1.38 262 | 2,4,aug,mon,93.6,97.9,542,14.4,28.3,32,4,0,8.85 263 | 3,4,aug,fri,91.6,112.4,573,8.9,11.2,84,7.6,0,3.3 264 | 2,4,aug,fri,91.6,112.4,573,8.9,21.4,42,3.1,0,4.25 265 | 6,3,aug,fri,91.1,141.1,629.1,7.1,19.3,39,3.6,0,1.56 266 | 4,4,aug,fri,94.3,167.6,684.4,13,21.8,53,3.1,0,6.54 267 | 4,4,aug,tue,93.7,102.2,550.3,14.6,22.1,54,7.6,0,0.79 268 | 6,5,aug,tue,94.3,131.7,607.1,22.7,19.4,55,4,0,0.17 269 | 2,2,aug,tue,92.1,152.6,658.2,14.3,23.7,24,3.1,0,0 270 | 3,4,aug,tue,92.1,152.6,658.2,14.3,21,32,3.1,0,0 271 | 4,4,aug,tue,92.1,152.6,658.2,14.3,19.1,53,2.7,0,4.4 272 | 2,2,aug,tue,92.1,152.6,658.2,14.3,21.8,56,3.1,0,0.52 273 | 8,6,aug,tue,92.1,152.6,658.2,14.3,20.1,58,4.5,0,9.27 274 | 2,5,aug,tue,92.1,152.6,658.2,14.3,20.2,47,4,0,3.09 275 | 4,6,dec,sun,84.4,27.2,353.5,6.8,4.8,57,8.5,0,8.98 276 | 8,6,dec,wed,84,27.8,354.6,5.3,5.1,61,8,0,11.19 277 | 4,6,dec,thu,84.6,26.4,352,2,5.1,61,4.9,0,5.38 278 | 4,4,dec,mon,85.4,25.4,349.7,2.6,4.6,21,8.5,0,17.85 279 | 3,4,dec,mon,85.4,25.4,349.7,2.6,4.6,21,8.5,0,10.73 280 | 4,4,dec,mon,85.4,25.4,349.7,2.6,4.6,21,8.5,0,22.03 281 | 4,4,dec,mon,85.4,25.4,349.7,2.6,4.6,21,8.5,0,9.77 282 | 4,6,dec,fri,84.7,26.7,352.6,4.1,2.2,59,4.9,0,9.27 283 | 6,5,dec,tue,85.4,25.4,349.7,2.6,5.1,24,8.5,0,24.77 284 | 6,3,feb,sun,84.9,27.5,353.5,3.4,4.2,51,4,0,0 285 | 3,4,feb,wed,86.9,6.6,18.7,3.2,8.8,35,3.1,0,1.1 286 | 5,4,feb,fri,85.2,4.9,15.8,6.3,7.5,46,8,0,24.24 287 | 2,5,jul,sun,93.9,169.7,411.8,12.3,23.4,40,6.3,0,0 288 | 7,6,jul,wed,91.2,183.1,437.7,12.5,12.6,90,7.6,0.2,0 289 | 7,4,jul,sat,91.6,104.2,474.9,9,22.1,49,2.7,0,0 290 | 7,4,jul,sat,91.6,104.2,474.9,9,24.2,32,1.8,0,0 291 | 7,4,jul,sat,91.6,104.2,474.9,9,24.3,30,1.8,0,0 292 | 2,5,jul,sat,91.6,104.2,474.9,9,18.7,53,1.8,0,0 293 | 9,4,jul,sat,91.6,104.2,474.9,9,25.3,39,0.9,0,8 294 | 4,5,jul,fri,91.6,100.2,466.3,6.3,22.9,40,1.3,0,2.64 295 | 7,6,jul,tue,93.1,180.4,430.8,11,26.9,28,5.4,0,86.45 296 | 8,6,jul,tue,92.3,88.8,440.9,8.5,17.1,67,3.6,0,6.57 297 | 7,5,jun,sun,93.1,180.4,430.8,11,22.2,48,1.3,0,0 298 | 6,4,jun,sun,90.4,89.5,290.8,6.4,14.3,46,1.8,0,0.9 299 | 8,6,jun,sun,90.4,89.5,290.8,6.4,15.4,45,2.2,0,0 300 | 8,6,jun,wed,91.2,147.8,377.2,12.7,19.6,43,4.9,0,0 301 | 6,5,jun,sat,53.4,71,233.8,0.4,10.6,90,2.7,0,0 302 | 6,5,jun,mon,90.4,93.3,298.1,7.5,20.7,25,4.9,0,0 303 | 6,5,jun,mon,90.4,93.3,298.1,7.5,19.1,39,5.4,0,3.52 304 | 3,6,jun,fri,91.1,94.1,232.1,7.1,19.2,38,4.5,0,0 305 | 3,6,jun,fri,91.1,94.1,232.1,7.1,19.2,38,4.5,0,0 306 | 6,5,may,sat,85.1,28,113.8,3.5,11.3,94,4.9,0,0 307 | 1,4,sep,sun,89.6,84.1,714.3,5.7,19,52,2.2,0,0 308 | 7,4,sep,sun,89.6,84.1,714.3,5.7,17.1,53,5.4,0,0.41 309 | 3,4,sep,sun,89.6,84.1,714.3,5.7,23.8,35,3.6,0,5.18 310 | 2,4,sep,sun,92.4,105.8,758.1,9.9,16,45,1.8,0,0 311 | 2,4,sep,sun,92.4,105.8,758.1,9.9,24.9,27,2.2,0,0 312 | 7,4,sep,sun,92.4,105.8,758.1,9.9,25.3,27,2.7,0,0 313 | 6,3,sep,sun,92.4,105.8,758.1,9.9,24.8,28,1.8,0,14.29 314 | 2,4,sep,sun,50.4,46.2,706.6,0.4,12.2,78,6.3,0,0 315 | 6,5,sep,wed,92.6,115.4,777.1,8.8,24.3,27,4.9,0,0 316 | 4,4,sep,wed,92.6,115.4,777.1,8.8,19.7,41,1.8,0,1.58 317 | 3,4,sep,wed,91.2,134.7,817.5,7.2,18.5,30,2.7,0,0 318 | 4,5,sep,thu,92.4,96.2,739.4,8.6,18.6,24,5.8,0,0 319 | 4,4,sep,thu,92.4,96.2,739.4,8.6,19.2,24,4.9,0,3.78 320 | 6,5,sep,thu,92.8,119,783.5,7.5,21.6,27,2.2,0,0 321 | 5,4,sep,thu,92.8,119,783.5,7.5,21.6,28,6.3,0,4.41 322 | 6,3,sep,thu,92.8,119,783.5,7.5,18.9,34,7.2,0,34.36 323 | 1,4,sep,thu,92.8,119,783.5,7.5,16.8,28,4,0,7.21 324 | 6,5,sep,thu,92.8,119,783.5,7.5,16.8,28,4,0,1.01 325 | 3,5,sep,thu,90.7,136.9,822.8,6.8,12.9,39,2.7,0,2.18 326 | 6,5,sep,thu,88.1,53.3,726.9,5.4,13.7,56,1.8,0,4.42 327 | 1,4,sep,sat,92.2,102.3,751.5,8.4,24.2,27,3.1,0,0 328 | 5,4,sep,sat,92.2,102.3,751.5,8.4,24.1,27,3.1,0,0 329 | 6,5,sep,sat,92.2,102.3,751.5,8.4,21.2,32,2.2,0,0 330 | 6,5,sep,sat,92.2,102.3,751.5,8.4,19.7,35,1.8,0,0 331 | 4,3,sep,sat,92.2,102.3,751.5,8.4,23.5,27,4,0,3.33 332 | 3,3,sep,sat,92.2,102.3,751.5,8.4,24.2,27,3.1,0,6.58 333 | 7,4,sep,sat,91.2,124.4,795.3,8.5,21.5,28,4.5,0,15.64 334 | 4,4,sep,sat,91.2,124.4,795.3,8.5,17.1,41,2.2,0,11.22 335 | 1,4,sep,mon,92.1,87.7,721.1,9.5,18.1,54,3.1,0,2.13 336 | 2,3,sep,mon,91.6,108.4,764,6.2,18,51,5.4,0,0 337 | 4,3,sep,mon,91.6,108.4,764,6.2,9.8,86,1.8,0,0 338 | 7,4,sep,mon,91.6,108.4,764,6.2,19.3,44,2.2,0,0 339 | 6,3,sep,mon,91.6,108.4,764,6.2,23,34,2.2,0,56.04 340 | 8,6,sep,mon,91.6,108.4,764,6.2,22.7,35,2.2,0,7.48 341 | 2,4,sep,mon,91.6,108.4,764,6.2,20.4,41,1.8,0,1.47 342 | 2,5,sep,mon,91.6,108.4,764,6.2,19.3,44,2.2,0,3.93 343 | 8,6,sep,mon,91.9,111.7,770.3,6.5,15.7,51,2.2,0,0 344 | 6,3,sep,mon,91.5,130.1,807.1,7.5,20.6,37,1.8,0,0 345 | 8,6,sep,mon,91.5,130.1,807.1,7.5,15.9,51,4.5,0,2.18 346 | 6,3,sep,mon,91.5,130.1,807.1,7.5,12.2,66,4.9,0,6.1 347 | 2,2,sep,mon,91.5,130.1,807.1,7.5,16.8,43,3.1,0,5.83 348 | 1,4,sep,mon,91.5,130.1,807.1,7.5,21.3,35,2.2,0,28.19 349 | 5,4,sep,fri,92.1,99,745.3,9.6,10.1,75,3.6,0,0 350 | 3,4,sep,fri,92.1,99,745.3,9.6,17.4,57,4.5,0,0 351 | 5,4,sep,fri,92.1,99,745.3,9.6,12.8,64,3.6,0,1.64 352 | 5,4,sep,fri,92.1,99,745.3,9.6,10.1,75,3.6,0,3.71 353 | 4,4,sep,fri,92.1,99,745.3,9.6,15.4,53,6.3,0,7.31 354 | 7,4,sep,fri,92.1,99,745.3,9.6,20.6,43,3.6,0,2.03 355 | 7,4,sep,fri,92.1,99,745.3,9.6,19.8,47,2.7,0,1.72 356 | 7,4,sep,fri,92.1,99,745.3,9.6,18.7,50,2.2,0,5.97 357 | 4,4,sep,fri,92.1,99,745.3,9.6,20.8,35,4.9,0,13.06 358 | 4,4,sep,fri,92.1,99,745.3,9.6,20.8,35,4.9,0,1.26 359 | 6,3,sep,fri,92.5,122,789.7,10.2,15.9,55,3.6,0,0 360 | 6,3,sep,fri,92.5,122,789.7,10.2,19.7,39,2.7,0,0 361 | 1,4,sep,fri,92.5,122,789.7,10.2,21.1,39,2.2,0,8.12 362 | 6,5,sep,fri,92.5,122,789.7,10.2,18.4,42,2.2,0,1.09 363 | 4,3,sep,fri,92.5,122,789.7,10.2,17.3,45,4,0,3.94 364 | 7,4,sep,fri,88.2,55.2,732.3,11.6,15.2,64,3.1,0,0.52 365 | 4,3,sep,tue,91.9,111.7,770.3,6.5,15.9,53,2.2,0,2.93 366 | 6,5,sep,tue,91.9,111.7,770.3,6.5,21.1,35,2.7,0,5.65 367 | 6,5,sep,tue,91.9,111.7,770.3,6.5,19.6,45,3.1,0,20.03 368 | 4,5,sep,tue,91.1,132.3,812.1,12.5,15.9,38,5.4,0,1.75 369 | 4,5,sep,tue,91.1,132.3,812.1,12.5,16.4,27,3.6,0,0 370 | 6,5,sep,sat,91.2,94.3,744.4,8.4,16.8,47,4.9,0,12.64 371 | 4,5,sep,sun,91,276.3,825.1,7.1,13.8,77,7.6,0,0 372 | 7,4,sep,sun,91,276.3,825.1,7.1,13.8,77,7.6,0,11.06 373 | 3,4,jul,wed,91.9,133.6,520.5,8,14.2,58,4,0,0 374 | 4,5,aug,sun,92,203.2,664.5,8.1,10.4,75,0.9,0,0 375 | 5,4,aug,thu,94.8,222.4,698.6,13.9,20.3,42,2.7,0,0 376 | 6,5,sep,fri,90.3,290,855.3,7.4,10.3,78,4,0,18.3 377 | 6,5,sep,sat,91.2,94.3,744.4,8.4,15.4,57,4.9,0,39.35 378 | 8,6,aug,mon,92.1,207,672.6,8.2,21.1,54,2.2,0,0 379 | 2,2,aug,sat,93.7,231.1,715.1,8.4,21.9,42,2.2,0,174.63 380 | 6,5,mar,thu,90.9,18.9,30.6,8,8.7,51,5.8,0,0 381 | 4,5,jan,sun,18.7,1.1,171.4,0,5.2,100,0.9,0,0 382 | 5,4,jul,wed,93.7,101.3,458.8,11.9,19.3,39,7.2,0,7.73 383 | 8,6,aug,thu,90.7,194.1,643,6.8,16.2,63,2.7,0,16.33 384 | 8,6,aug,wed,95.2,217.7,690,18,28.2,29,1.8,0,5.86 385 | 9,6,aug,thu,91.6,248.4,753.8,6.3,20.5,58,2.7,0,42.87 386 | 8,4,aug,sat,91.6,273.8,819.1,7.7,21.3,44,4.5,0,12.18 387 | 2,4,aug,sun,91.6,181.3,613,7.6,20.9,50,2.2,0,16 388 | 3,4,sep,sun,90.5,96.7,750.5,11.4,20.6,55,5.4,0,24.59 389 | 5,5,mar,thu,90.9,18.9,30.6,8,11.6,48,5.4,0,0 390 | 6,4,aug,fri,94.8,227,706.7,12,23.3,34,3.1,0,28.74 391 | 7,4,aug,fri,94.8,227,706.7,12,23.3,34,3.1,0,0 392 | 7,4,feb,mon,84.7,9.5,58.3,4.1,7.5,71,6.3,0,9.96 393 | 8,6,sep,fri,91.1,91.3,738.1,7.2,20.7,46,2.7,0,30.18 394 | 1,3,sep,sun,91,276.3,825.1,7.1,21.9,43,4,0,70.76 395 | 2,4,mar,tue,93.4,15,25.6,11.4,15.2,19,7.6,0,0 396 | 6,5,feb,mon,84.1,4.6,46.7,2.2,5.3,68,1.8,0,0 397 | 4,5,feb,sun,85,9,56.9,3.5,10.1,62,1.8,0,51.78 398 | 4,3,sep,sun,90.5,96.7,750.5,11.4,20.4,55,4.9,0,3.64 399 | 5,6,aug,sun,91.6,181.3,613,7.6,24.3,33,3.6,0,3.63 400 | 1,2,aug,sat,93.7,231.1,715.1,8.4,25.9,32,3.1,0,0 401 | 9,5,jun,wed,93.3,49.5,297.7,14,28,34,4.5,0,0 402 | 9,5,jun,wed,93.3,49.5,297.7,14,28,34,4.5,0,8.16 403 | 3,4,sep,thu,91.1,88.2,731.7,8.3,22.8,46,4,0,4.95 404 | 9,9,aug,fri,94.8,227,706.7,12,25,36,4,0,0 405 | 8,6,aug,thu,90.7,194.1,643,6.8,21.3,41,3.6,0,0 406 | 2,4,sep,wed,87.9,84.8,725.1,3.7,21.8,34,2.2,0,6.04 407 | 2,2,aug,tue,94.6,212.1,680.9,9.5,27.9,27,2.2,0,0 408 | 6,5,sep,sat,87.1,291.3,860.6,4,17,67,4.9,0,3.95 409 | 4,5,feb,sat,84.7,8.2,55,2.9,14.2,46,4,0,0 410 | 4,3,sep,fri,90.3,290,855.3,7.4,19.9,44,3.1,0,7.8 411 | 1,4,jul,tue,92.3,96.2,450.2,12.1,23.4,31,5.4,0,0 412 | 6,3,feb,fri,84.1,7.3,52.8,2.7,14.7,42,2.7,0,0 413 | 7,4,feb,fri,84.6,3.2,43.6,3.3,8.2,53,9.4,0,4.62 414 | 9,4,jul,mon,92.3,92.1,442.1,9.8,22.8,27,4.5,0,1.63 415 | 7,5,aug,sat,93.7,231.1,715.1,8.4,26.4,33,3.6,0,0 416 | 5,4,aug,sun,93.6,235.1,723.1,10.1,24.1,50,4,0,0 417 | 8,6,aug,thu,94.8,222.4,698.6,13.9,27.5,27,4.9,0,746.28 418 | 6,3,jul,tue,92.7,164.1,575.8,8.9,26.3,39,3.1,0,7.02 419 | 6,5,mar,wed,93.4,17.3,28.3,9.9,13.8,24,5.8,0,0 420 | 2,4,aug,sun,92,203.2,664.5,8.1,24.9,42,5.4,0,2.44 421 | 2,5,aug,sun,91.6,181.3,613,7.6,24.8,36,4,0,3.05 422 | 8,8,aug,wed,91.7,191.4,635.9,7.8,26.2,36,4.5,0,185.76 423 | 2,4,aug,wed,95.2,217.7,690,18,30.8,19,4.5,0,0 424 | 8,6,jul,sun,88.9,263.1,795.9,5.2,29.3,27,3.6,0,6.3 425 | 1,3,sep,sat,91.2,94.3,744.4,8.4,22.3,48,4,0,0.72 426 | 8,6,aug,sat,93.7,231.1,715.1,8.4,26.9,31,3.6,0,4.96 427 | 2,2,aug,thu,91.6,248.4,753.8,6.3,20.4,56,2.2,0,0 428 | 8,6,aug,thu,91.6,248.4,753.8,6.3,20.4,56,2.2,0,0 429 | 2,4,aug,mon,92.1,207,672.6,8.2,27.9,33,2.2,0,2.35 430 | 1,3,aug,thu,94.8,222.4,698.6,13.9,26.2,34,5.8,0,0 431 | 3,4,aug,sun,91.6,181.3,613,7.6,24.6,44,4,0,3.2 432 | 7,4,sep,thu,89.7,287.2,849.3,6.8,19.4,45,3.6,0,0 433 | 1,3,aug,sat,92.1,178,605.3,9.6,23.3,40,4,0,6.36 434 | 8,6,aug,thu,94.8,222.4,698.6,13.9,23.9,38,6.7,0,0 435 | 2,4,aug,sun,93.6,235.1,723.1,10.1,20.9,66,4.9,0,15.34 436 | 1,4,aug,fri,90.6,269.8,811.2,5.5,22.2,45,3.6,0,0 437 | 2,5,jul,sat,90.8,84.7,376.6,5.6,23.8,51,1.8,0,0 438 | 8,6,aug,mon,92.1,207,672.6,8.2,26.8,35,1.3,0,0.54 439 | 8,6,aug,sat,89.4,253.6,768.4,9.7,14.2,73,2.7,0,0 440 | 2,5,aug,sat,93.7,231.1,715.1,8.4,23.6,53,4,0,6.43 441 | 1,3,sep,fri,91.1,91.3,738.1,7.2,19.1,46,2.2,0,0.33 442 | 5,4,sep,fri,90.3,290,855.3,7.4,16.2,58,3.6,0,0 443 | 8,6,aug,mon,92.1,207,672.6,8.2,25.5,29,1.8,0,1.23 444 | 6,5,apr,mon,87.9,24.9,41.6,3.7,10.9,64,3.1,0,3.35 445 | 1,2,jul,fri,90.7,80.9,368.3,16.8,14.8,78,8,0,0 446 | 2,5,sep,fri,90.3,290,855.3,7.4,16.2,58,3.6,0,9.96 447 | 5,5,aug,sun,94,47.9,100.7,10.7,17.3,80,4.5,0,0 448 | 6,5,aug,sun,92,203.2,664.5,8.1,19.1,70,2.2,0,0 449 | 3,4,mar,wed,93.4,17.3,28.3,9.9,8.9,35,8,0,0 450 | 7,4,sep,wed,89.7,284.9,844,10.1,10.5,77,4,0,0 451 | 7,4,aug,sun,91.6,181.3,613,7.6,19.3,61,4.9,0,0 452 | 4,5,aug,wed,95.2,217.7,690,18,23.4,49,5.4,0,6.43 453 | 1,4,aug,fri,90.5,196.8,649.9,16.3,11.8,88,4.9,0,9.71 454 | 7,4,aug,mon,91.5,238.2,730.6,7.5,17.7,65,4,0,0 455 | 4,5,aug,thu,89.4,266.2,803.3,5.6,17.4,54,3.1,0,0 456 | 3,4,aug,thu,91.6,248.4,753.8,6.3,16.8,56,3.1,0,0 457 | 3,4,jul,mon,94.6,160,567.2,16.7,17.9,48,2.7,0,0 458 | 2,4,aug,thu,91.6,248.4,753.8,6.3,16.6,59,2.7,0,0 459 | 1,4,aug,wed,91.7,191.4,635.9,7.8,19.9,50,4,0,82.75 460 | 8,6,aug,sat,93.7,231.1,715.1,8.4,18.9,64,4.9,0,3.32 461 | 7,4,aug,sat,91.6,273.8,819.1,7.7,15.5,72,8,0,1.94 462 | 2,5,aug,sat,93.7,231.1,715.1,8.4,18.9,64,4.9,0,0 463 | 8,6,aug,sat,93.7,231.1,715.1,8.4,18.9,64,4.9,0,0 464 | 1,4,sep,sun,91,276.3,825.1,7.1,14.5,76,7.6,0,3.71 465 | 6,5,feb,tue,75.1,4.4,16.2,1.9,4.6,82,6.3,0,5.39 466 | 6,4,feb,tue,75.1,4.4,16.2,1.9,5.1,77,5.4,0,2.14 467 | 2,2,feb,sat,79.5,3.6,15.3,1.8,4.6,59,0.9,0,6.84 468 | 6,5,mar,mon,87.2,15.1,36.9,7.1,10.2,45,5.8,0,3.18 469 | 3,4,mar,wed,90.2,18.5,41.1,7.3,11.2,41,5.4,0,5.55 470 | 6,5,mar,thu,91.3,20.6,43.5,8.5,13.3,27,3.6,0,6.61 471 | 6,3,apr,sun,91,14.6,25.6,12.3,13.7,33,9.4,0,61.13 472 | 5,4,apr,sun,91,14.6,25.6,12.3,17.6,27,5.8,0,0 473 | 4,3,may,fri,89.6,25.4,73.7,5.7,18,40,4,0,38.48 474 | 8,3,jun,mon,88.2,96.2,229,4.7,14.3,79,4,0,1.94 475 | 9,4,jun,sat,90.5,61.1,252.6,9.4,24.5,50,3.1,0,70.32 476 | 4,3,jun,thu,93,103.8,316.7,10.8,26.4,35,2.7,0,10.08 477 | 2,5,jun,thu,93.7,121.7,350.2,18,22.7,40,9.4,0,3.19 478 | 4,3,jul,thu,93.5,85.3,395,9.9,27.2,28,1.3,0,1.76 479 | 4,3,jul,sun,93.7,101.3,423.4,14.7,26.1,45,4,0,7.36 480 | 7,4,jul,sun,93.7,101.3,423.4,14.7,18.2,82,4.5,0,2.21 481 | 7,4,jul,mon,89.2,103.9,431.6,6.4,22.6,57,4.9,0,278.53 482 | 9,9,jul,thu,93.2,114.4,560,9.5,30.2,25,4.5,0,2.75 483 | 4,3,jul,thu,93.2,114.4,560,9.5,30.2,22,4.9,0,0 484 | 3,4,aug,sun,94.9,130.3,587.1,14.1,23.4,40,5.8,0,1.29 485 | 8,6,aug,sun,94.9,130.3,587.1,14.1,31,27,5.4,0,0 486 | 2,5,aug,sun,94.9,130.3,587.1,14.1,33.1,25,4,0,26.43 487 | 2,4,aug,mon,95,135.5,596.3,21.3,30.6,28,3.6,0,2.07 488 | 5,4,aug,tue,95.1,141.3,605.8,17.7,24.1,43,6.3,0,2 489 | 5,4,aug,tue,95.1,141.3,605.8,17.7,26.4,34,3.6,0,16.4 490 | 4,4,aug,tue,95.1,141.3,605.8,17.7,19.4,71,7.6,0,46.7 491 | 4,4,aug,wed,95.1,141.3,605.8,17.7,20.6,58,1.3,0,0 492 | 4,4,aug,wed,95.1,141.3,605.8,17.7,28.7,33,4,0,0 493 | 4,4,aug,thu,95.8,152,624.1,13.8,32.4,21,4.5,0,0 494 | 1,3,aug,fri,95.9,158,633.6,11.3,32.4,27,2.2,0,0 495 | 1,3,aug,fri,95.9,158,633.6,11.3,27.5,29,4.5,0,43.32 496 | 6,6,aug,sat,96,164,643,14,30.8,30,4.9,0,8.59 497 | 6,6,aug,mon,96.2,175.5,661.8,16.8,23.9,42,2.2,0,0 498 | 4,5,aug,mon,96.2,175.5,661.8,16.8,32.6,26,3.1,0,2.77 499 | 3,4,aug,tue,96.1,181.1,671.2,14.3,32.3,27,2.2,0,14.68 500 | 6,5,aug,tue,96.1,181.1,671.2,14.3,33.3,26,2.7,0,40.54 501 | 7,5,aug,tue,96.1,181.1,671.2,14.3,27.3,63,4.9,6.4,10.82 502 | 8,6,aug,tue,96.1,181.1,671.2,14.3,21.6,65,4.9,0.8,0 503 | 7,5,aug,tue,96.1,181.1,671.2,14.3,21.6,65,4.9,0.8,0 504 | 4,4,aug,tue,96.1,181.1,671.2,14.3,20.7,69,4.9,0.4,0 505 | 2,4,aug,wed,94.5,139.4,689.1,20,29.2,30,4.9,0,1.95 506 | 4,3,aug,wed,94.5,139.4,689.1,20,28.9,29,4.9,0,49.59 507 | 1,2,aug,thu,91,163.2,744.4,10.1,26.7,35,1.8,0,5.8 508 | 1,2,aug,fri,91,166.9,752.6,7.1,18.5,73,8.5,0,0 509 | 2,4,aug,fri,91,166.9,752.6,7.1,25.9,41,3.6,0,0 510 | 1,2,aug,fri,91,166.9,752.6,7.1,25.9,41,3.6,0,0 511 | 5,4,aug,fri,91,166.9,752.6,7.1,21.1,71,7.6,1.4,2.17 512 | 6,5,aug,fri,91,166.9,752.6,7.1,18.2,62,5.4,0,0.43 513 | 8,6,aug,sun,81.6,56.7,665.6,1.9,27.8,35,2.7,0,0 514 | 4,3,aug,sun,81.6,56.7,665.6,1.9,27.8,32,2.7,0,6.44 515 | 2,4,aug,sun,81.6,56.7,665.6,1.9,21.9,71,5.8,0,54.29 516 | 7,4,aug,sun,81.6,56.7,665.6,1.9,21.2,70,6.7,0,11.16 517 | 1,4,aug,sat,94.4,146,614.7,11.3,25.6,42,4,0,0 518 | 6,3,nov,tue,79.5,3,106.7,1.1,11.8,31,4.5,0,0 519 | -------------------------------------------------------------------------------- /led_board.py: -------------------------------------------------------------------------------- 1 | from gpiozero import LEDBoard 2 | from time import sleep 3 | import sys 4 | 5 | # Define Morse code dictionary 6 | MORSE_CODE = { 7 | 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 8 | 'F': '..-.', 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 9 | 'K': '-.-', 'L': '.-..', 'M': '--', 'N': '-.', 'O': '---', 10 | 'P': '.--.', 'Q': '--.-', 'R': '.-.', 'S': '...', 'T': '-', 11 | 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', 'Y': '-.--', 'Z': '--..', 12 | '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', 13 | '6': '-....', '7': '--...', '8': '---..', '9': '----.', '0': '-----', 14 | ' ': ' ' 15 | } 16 | 17 | def encode_to_leds(leds, word): 18 | word = word.upper() 19 | for char in word: 20 | if char not in MORSE_CODE: 21 | print(f"Warning: Character '{char}' is not valid Morse code. Skipping.") 22 | continue 23 | 24 | code = MORSE_CODE[char] 25 | # turn on 26 | for i, symbol in enumerate(code): 27 | if i >= len(leds): 28 | break 29 | if symbol == '-' or symbol == '.': 30 | leds[i].on() 31 | sleep(1) 32 | 33 | # turn off '.' 34 | for i, symbol in enumerate(code): 35 | if i >= len(leds): 36 | break 37 | if symbol == '.': 38 | leds[i].off() 39 | sleep(1) 40 | 41 | # turn off '-' 42 | for i, symbol in enumerate(code): 43 | if i >= len(leds): 44 | break 45 | leds[i].off() 46 | 47 | sleep(3) 48 | 49 | if __name__ == "__main__": 50 | if len(sys.argv) != 2: 51 | print("Usage: sudo python3 LEDboard.py ") 52 | sys.exit(1) 53 | 54 | input_word = sys.argv[1] 55 | 56 | # Initialize LEDBoard with 5 GPIO pins 57 | leds = LEDBoard(5, 6, 13, 19, 26) 58 | 59 | 60 | try: 61 | encode_to_leds(leds, input_word) 62 | except KeyboardInterrupt: 63 | pass 64 | finally: 65 | leds.off() 66 | -------------------------------------------------------------------------------- /list_dict_comprehension_exercises.md: -------------------------------------------------------------------------------- 1 | Here are 5 simple exercises that focus on converting basic Python code into list or dictionary comprehensions: 2 | 3 | --- 4 | 5 | ### **Exercise 1: Convert a For Loop to List Comprehension** 6 | Convert the following for loop into a list comprehension: 7 | 8 | ```python 9 | result = [] 10 | for x in range(10): 11 | result.append(x**2) 12 | ``` 13 | 14 | --- 15 | 16 | ### **Exercise 2: Filter Numbers with List Comprehension** 17 | Rewrite this code using a list comprehension: 18 | 19 | ```python 20 | result = [] 21 | for x in range(20): 22 | if x % 2 == 0: 23 | result.append(x) 24 | ``` 25 | 26 | --- 27 | 28 | ### **Exercise 3: Dictionary Comprehension** 29 | Convert the following code to a dictionary comprehension: 30 | 31 | ```python 32 | squares = {} 33 | for x in range(5): 34 | squares[x] = x**2 35 | ``` 36 | 37 | --- 38 | 39 | ### **Exercise 4: Nested Loops with List Comprehension** 40 | Rewrite the nested loop as a list comprehension: 41 | 42 | ```python 43 | pairs = [] 44 | for x in range(3): 45 | for y in range(2): 46 | pairs.append((x, y)) 47 | ``` 48 | 49 | --- 50 | 51 | ### **Exercise 5: Conditional Dictionary Comprehension** 52 | Transform the following code into a dictionary comprehension with a condition: 53 | 54 | ```python 55 | filtered_squares = {} 56 | for x in range(10): 57 | if x % 2 == 0: 58 | filtered_squares[x] = x**2 59 | ``` 60 | 61 | --- 62 | 63 | Certainly! Here's a set of slightly more challenging exercises involving list and dictionary comprehensions: 64 | 65 | --- 66 | 67 | ### **Exercise 1: Conditional Transformation in List Comprehension** 68 | Convert the following loop into a list comprehension that includes a conditional transformation: 69 | 70 | ```python 71 | result = [] 72 | for x in range(15): 73 | if x % 3 == 0: 74 | result.append(x**2) 75 | else: 76 | result.append(x) 77 | ``` 78 | 79 | --- 80 | 81 | ### **Exercise 2: Dictionary Comprehension with String Keys** 82 | Transform the following loop into a dictionary comprehension, using strings as keys: 83 | 84 | ```python 85 | word_lengths = {} 86 | words = ["apple", "banana", "cherry", "date"] 87 | for word in words: 88 | word_lengths[word] = len(word) 89 | ``` 90 | 91 | --- 92 | 93 | ### **Exercise 3: Flatten a Nested List with List Comprehension** 94 | Rewrite this code using a single list comprehension to flatten the nested list: 95 | 96 | ```python 97 | nested_list = [[1, 2, 3], [4, 5], [6, 7, 8, 9]] 98 | flattened = [] 99 | for sublist in nested_list: 100 | for item in sublist: 101 | flattened.append(item) 102 | ``` 103 | 104 | --- 105 | 106 | ### **Exercise 4: Conditional Dictionary Comprehension with Nested Loops** 107 | Convert the following nested loop into a dictionary comprehension with a condition: 108 | 109 | ```python 110 | result = {} 111 | for i in range(3): 112 | for j in range(3, 6): 113 | if j % i != 0: # Avoid division by zero 114 | result[(i, j)] = i + j 115 | ``` 116 | 117 | --- 118 | 119 | ### **Exercise 5: Filter and Transform Nested Dictionaries** 120 | Use a dictionary comprehension to filter and transform the following dictionary of dictionaries: 121 | 122 | ```python 123 | data = { 124 | "A": {"score": 90, "passed": True}, 125 | "B": {"score": 65, "passed": False}, 126 | "C": {"score": 75, "passed": True}, 127 | "D": {"score": 50, "passed": False}, 128 | } 129 | 130 | # Goal: Include only students who passed, and create a dictionary of their scores. 131 | result = {} 132 | for key, value in data.items(): 133 | if value["passed"]: 134 | result[key] = value["score"] 135 | ``` 136 | 137 | --- 138 | 139 | These exercises require a bit more thinking about conditions, transformations, and handling nested structures, but they're still approachable for intermediate learners! 140 | -------------------------------------------------------------------------------- /nursery_v1.py: -------------------------------------------------------------------------------- 1 | class Plant: 2 | def __init__(self, species): 3 | self.species = species 4 | 5 | class Tray: 6 | def __init__(self, species, count): 7 | self.species = species 8 | self.count = count # Number of plants of the same species in the tray 9 | 10 | def add_plants(self, number): 11 | """Add plants to the tray.""" 12 | self.count += number 13 | 14 | def remove_plants(self, number): 15 | """Remove plants from the tray. Returns the number removed.""" 16 | if number > self.count: 17 | removed = self.count 18 | self.count = 0 19 | else: 20 | self.count -= number 21 | removed = number 22 | return removed 23 | 24 | def __repr__(self): 25 | return f"Tray(species={self.species}, count={self.count})" 26 | 27 | class Pot: 28 | def __init__(self, species): 29 | self.species = species 30 | 31 | class Nursery: 32 | def __init__(self): 33 | self.trays = [] # A list of trays in the nursery 34 | self.pots = [] # A list of pots in the nursery 35 | self.tray_inventory = {} # Dictionary to track inventory of each species in the nursery 36 | self.pot_inventory = {} # Dictionary to track inventory of each species in the nursery 37 | 38 | def add_tray(self, species, count): 39 | # Add a tray of a given species and count. 40 | tray = Tray(species, count) 41 | self.trays.append(tray) 42 | # Update the inventory 43 | if species in self.tray_inventory: 44 | self.tray_inventory[species] += count 45 | else: 46 | self.tray_inventory[species] = count 47 | 48 | def remove_plants_from_tray(self, species, count): 49 | # Remove plants of a given species from trays. 50 | removed_count = 0 51 | for tray in self.trays: 52 | if tray.species == species: 53 | number_removed = tray.remove_plants(count) 54 | removed_count += number_removed 55 | count -= number_removed 56 | if number_removed > count: 57 | break 58 | # Update the inventory 59 | if species in self.tray_inventory: 60 | self.tray_inventory[species] -= removed_count 61 | if self.tray_inventory[species] <= 0: 62 | del self.tray_inventory[species] 63 | 64 | def get_inventory(self): 65 | """Returns the current inventory of plants in the nursery.""" 66 | return self.tray_inventory 67 | 68 | # Create a nursery 69 | nursery = Nursery() 70 | 71 | # Add trays to the nursery 72 | nursery.add_tray('Tomato', 20) 73 | nursery.add_tray('Cucumber', 15) 74 | nursery.add_tray('Tomato', 30) 75 | 76 | # View the nursery's inventory 77 | print(nursery.get_inventory()) # {'Tomato': 50, 'Cucumber': 15} 78 | 79 | # Remove some plants from a tray 80 | nursery.remove_plants_from_tray('Tomato', 40) 81 | 82 | # View updated inventory 83 | print(nursery.get_inventory()) # {'Tomato': 40, 'Cucumber': 15} 84 | 85 | # View the trays to see how many plants are left 86 | print(nursery.trays) # [Tray(species=Tomato, count=10), Tray(species=Cucumber, count=15), Tray(species=Tomato, count=30)] 87 | -------------------------------------------------------------------------------- /rural_fires.csv: -------------------------------------------------------------------------------- 1 | Statistical table extracted on October 17, 2024 (23:02:41),, 2 | http://www.ine.pt,,, 3 | ,,, 4 | ,,, 5 | ,,, 6 | Geographic localization (NUTS - 2024);Rural fires (No.) by Geographic localization (NUTS - 2024) and Cause of fire - Annual;;;;;;;,,, 7 | ;Data reference period;;;;;;;,,, 8 | ;2023;;;;;;;,,, 9 | ;Cause of fire;;;;;;;,,, 10 | ;Total;Negligence;Intentional;Naturais;Re-ignition;Undetermined;Not investigated;,,, 11 | ;No. ;No. ;No. ;No. ;No. ;No. ;No. ;,,, 12 | PT: Portugal;7559 &;3046 &;1524 &;77 &;256 &;2393 &;263 &;,,, 13 | 1: Continente;7520 &;3040 &;1522 &;77 &;256 &;2362 &;263 &;,,, 14 | 11: Norte;3986 &;1480 &;707 &;25 &;189 &;1409 &;176 &;,,, 15 | 111: Alto Minho;629 &;370 &;219 &;0 &;26 &;14 &;0 &;,,, 16 | 1111601: Arcos de Valdevez;104 &;73 &;27 &;0 &;4 &;0 &;0 &;,,, 17 | 1111602: Caminha;17 &;10 &;6 &;0 &;1 &;0 &;0 &;,,, 18 | 1111603: Melga�o;25 &;24 &;0 &;0 &;1 &;0 &;0 &;,,, 19 | 1111604: Mon��o;35 &;25 &;9 &;0 &;1 &;0 &;0 &;,,, 20 | 1111605: Paredes de Coura;23 &;16 &;6 &;0 &;0 &;1 &;0 &;,,, 21 | 1111606: Ponte da Barca;215 &;92 &;110 &;0 &;13 &;0 &;0 &;,,, 22 | 1111607: Ponte de Lima;98 &;39 &;40 &;0 &;6 &;13 &;0 &;,,, 23 | 1111608: Valen�a;33 &;27 &;6 &;0 &;0 &;0 &;0 &;,,, 24 | 1111609: Viana do Castelo;72 &;57 &;15 &;0 &;0 &;0 &;0 &;,,, 25 | 1111610: Vila Nova de Cerveira;7 &;7 &;0 &;0 &;0 &;0 &;0 &;,,, 26 | 112: C�vado;252 &;120 &;70 &;1 &;15 &;45 &;1 &;,,, 27 | 1120301: Amares;12 &;4 &;5 &;0 &;0 &;2 &;1 &;,,, 28 | 1120302: Barcelos;58 &;19 &;15 &;1 &;5 &;18 &;0 &;,,, 29 | 1120303: Braga;35 &;11 &;9 &;0 &;6 &;9 &;0 &;,,, 30 | 1120306: Esposende;9 &;6 &;0 &;0 &;0 &;3 &;0 &;,,, 31 | 1120310: Terras de Bouro;36 &;27 &;6 &;0 &;2 &;1 &;0 &;,,, 32 | 1120313: Vila Verde;102 &;53 &;35 &;0 &;2 &;12 &;0 &;,,, 33 | 119: Ave;468 &;202 &;173 &;3 &;39 &;50 &;1 &;,,, 34 | 1190304: Cabeceiras de Basto;44 &;27 &;10 &;1 &;6 &;0 &;0 &;,,, 35 | 1190307: Fafe;116 &;42 &;63 &;0 &;11 &;0 &;0 &;,,, 36 | 1190308: Guimar�es;54 &;23 &;22 &;0 &;4 &;4 &;1 &;,,, 37 | 1191705: Mondim de Basto;14 &;9 &;2 &;2 &;1 &;0 &;0 &;,,, 38 | 1190309: P�voa de Lanhoso;73 &;54 &;5 &;0 &;8 &;6 &;0 &;,,, 39 | 1190311: Vieira do Minho;98 &;34 &;57 &;0 &;3 &;4 &;0 &;,,, 40 | 1190312: Vila Nova de Famalic�o;61 &;10 &;9 &;0 &;6 &;36 &;0 &;,,, 41 | 1190314: Vizela;8 &;3 &;5 &;0 &;0 &;0 &;0 &;,,, 42 | 11A: �rea Metropolitana do Porto;1072 &;159 &;21 &;1 &;40 &;677 &;174 &;,,, 43 | 11A0104: Arouca;69 &;43 &;1 &;0 &;1 &;24 &;0 &;,,, 44 | 11A0107: Espinho;1 &;0 &;1 &;0 &;0 &;0 &;0 &;,,, 45 | 11A1304: Gondomar;127 &;7 &;1 &;0 &;1 &;118 &;0 &;,,, 46 | 11A1306: Maia;65 &;5 &;5 &;0 &;2 &;1 &;52 &;,,, 47 | 11A1308: Matosinhos;56 &;2 &;0 &;0 &;16 &;2 &;36 &;,,, 48 | 11A0113: Oliveira de Azem�is;63 &;13 &;0 &;0 &;0 &;50 &;0 &;,,, 49 | 11A1310: Paredes;164 &;6 &;3 &;0 &;11 &;144 &;0 &;,,, 50 | 11A1312: Porto;16 &;0 &;0 &;0 &;0 &;0 &;16 &;,,, 51 | 11A1313: P�voa de Varzim;29 &;0 &;0 &;0 &;0 &;0 &;29 &;,,, 52 | 11A0109: Santa Maria da Feira;64 &;26 &;3 &;0 &;8 &;27 &;0 &;,,, 53 | 11A1314: Santo Tirso;85 &;22 &;0 &;0 &;0 &;63 &;0 &;,,, 54 | 11A0116: S�o Jo�o da Madeira;4 &;2 &;0 &;0 &;0 &;2 &;0 &;,,, 55 | 11A1318: Trofa;44 &;5 &;1 &;0 &;0 &;38 &;0 &;,,, 56 | 11A0119: Vale de Cambra;37 &;10 &;0 &;1 &;0 &;26 &;0 &;,,, 57 | 11A1315: Valongo;52 &;4 &;0 &;0 &;1 &;47 &;0 &;,,, 58 | 11A1316: Vila do Conde;49 &;2 &;6 &;0 &;0 &;0 &;41 &;,,, 59 | 11A1317: Vila Nova de Gaia;147 &;12 &;0 &;0 &;0 &;135 &;0 &;,,, 60 | 11B: Alto T�mega e Barroso;317 &;254 &;39 &;3 &;16 &;5 &;0 &;,,, 61 | 11B1702: Boticas;47 &;41 &;3 &;1 &;2 &;0 &;0 &;,,, 62 | 11B1703: Chaves;36 &;29 &;5 &;0 &;2 &;0 &;0 &;,,, 63 | 11B1706: Montalegre;117 &;104 &;10 &;0 &;3 &;0 &;0 &;,,, 64 | 11B1709: Ribeira de Pena;23 &;15 &;4 &;1 &;1 &;2 &;0 &;,,, 65 | 11B1712: Valpa�os;51 &;45 &;2 &;1 &;3 &;0 &;0 &;,,, 66 | 11B1713: Vila Pouca de Aguiar;43 &;20 &;15 &;0 &;5 &;3 &;0 &;,,, 67 | 11C: T�mega e Sousa;878 &;158 &;103 &;0 &;37 &;580 &;0 &;,,, 68 | 11C1301: Amarante;132 &;7 &;32 &;0 &;4 &;89 &;0 &;,,, 69 | 11C1302: Bai�o;80 &;5 &;25 &;0 &;0 &;50 &;0 &;,,, 70 | 11C0106: Castelo de Paiva;33 &;9 &;0 &;0 &;0 &;24 &;0 &;,,, 71 | 11C0305: Celorico de Basto;40 &;22 &;16 &;0 &;2 &;0 &;0 &;,,, 72 | 11C1804: Cinf�es;66 &;45 &;18 &;0 &;3 &;0 &;0 &;,,, 73 | 11C1303: Felgueiras;74 &;15 &;0 &;0 &;5 &;54 &;0 &;,,, 74 | 11C1305: Lousada;129 &;18 &;1 &;0 &;3 &;107 &;0 &;,,, 75 | 11C1307: Marco de Canaveses;102 &;8 &;2 &;0 &;10 &;82 &;0 &;,,, 76 | 11C1309: Pa�os de Ferreira;69 &;5 &;0 &;0 &;0 &;64 &;0 &;,,, 77 | 11C1311: Penafiel;132 &;11 &;2 &;0 &;9 &;110 &;0 &;,,, 78 | 11C1813: Resende;21 &;13 &;7 &;0 &;1 &;0 &;0 &;,,, 79 | 11D: Douro;266 &;138 &;76 &;14 &;13 &;25 &;0 &;,,, 80 | 11D1701: Alij�;15 &;8 &;0 &;1 &;0 &;6 &;0 &;,,, 81 | 11D1801: Armamar;5 &;2 &;3 &;0 &;0 &;0 &;0 &;,,, 82 | 11D0403: Carrazeda de Ansi�es;8 &;3 &;3 &;1 &;0 &;1 &;0 &;,,, 83 | 11D0404: Freixo de Espada � Cinta;10 &;10 &;0 &;0 &;0 &;0 &;0 &;,,, 84 | 11D1805: Lamego;39 &;25 &;13 &;0 &;1 &;0 &;0 &;,,, 85 | 11D1704: Mes�o Frio;8 &;0 &;4 &;0 &;1 &;3 &;0 &;,,, 86 | 11D1807: Moimenta da Beira;18 &;13 &;3 &;0 &;2 &;0 &;0 &;,,, 87 | 11D1707: Mur�a;8 &;5 &;0 &;1 &;1 &;1 &;0 &;,,, 88 | 11D1812: Penedono;7 &;2 &;5 &;0 &;0 &;0 &;0 &;,,, 89 | 11D1708: Peso da R�gua;15 &;6 &;3 &;0 &;2 &;4 &;0 &;,,, 90 | 11D1710: Sabrosa;16 &;2 &;6 &;0 &;3 &;5 &;0 &;,,, 91 | 11D1711: Santa Marta de Penagui�o;11 &;3 &;4 &;0 &;0 &;4 &;0 &;,,, 92 | 11D1815: S�o Jo�o da Pesqueira;11 &;9 &;1 &;1 &;0 &;0 &;0 &;,,, 93 | 11D1818: Sernancelhe;14 &;5 &;5 &;4 &;0 &;0 &;0 &;,,, 94 | 11D1819: Tabua�o;10 &;8 &;1 &;1 &;0 &;0 &;0 &;,,, 95 | 11D1820: Tarouca;13 &;9 &;2 &;1 &;1 &;0 &;0 &;,,, 96 | 11D0409: Torre de Moncorvo;11 &;2 &;6 &;2 &;0 &;1 &;0 &;,,, 97 | 11D0914: Vila Nova de Foz C�a;5 &;5 &;0 &;0 &;0 &;0 &;0 &;,,, 98 | 11D1714: Vila Real;42 &;21 &;17 &;2 &;2 &;0 &;0 &;,,, 99 | 11E: Terras de Tr�s-os-Montes;104 &;79 &;6 &;3 &;3 &;13 &;0 &;,,, 100 | 11E0401: Alf�ndega da F�;1 &;0 &;0 &;0 &;0 &;1 &;0 &;,,, 101 | 11E0402: Bragan�a;22 &;18 &;1 &;0 &;0 &;3 &;0 &;,,, 102 | 11E0405: Macedo de Cavaleiros;14 &;10 &;1 &;1 &;0 &;2 &;0 &;,,, 103 | 11E0406: Miranda do Douro;5 &;4 &;0 &;0 &;0 &;1 &;0 &;,,, 104 | 11E0407: Mirandela;4 &;4 &;0 &;0 &;0 &;0 &;0 &;,,, 105 | 11E0408: Mogadouro;12 &;8 &;0 &;2 &;1 &;1 &;0 &;,,, 106 | 11E0410: Vila Flor;1 &;1 &;0 &;0 &;0 &;0 &;0 &;,,, 107 | 11E0411: Vimioso;6 &;6 &;0 &;0 &;0 &;0 &;0 &;,,, 108 | 11E0412: Vinhais;39 &;28 &;4 &;0 &;2 &;5 &;0 &;,,, 109 | 19: Centro;1460 &;672 &;479 &;47 &;31 &;231 &;0 &;,,, 110 | 191: Regi�o de Aveiro;290 &;97 &;73 &;2 &;13 &;105 &;0 &;,,, 111 | 1910101: �gueda;32 &;16 &;11 &;0 &;3 &;2 &;0 &;,,, 112 | 1910102: Albergaria-a-Velha;38 &;11 &;21 &;0 &;4 &;2 &;0 &;,,, 113 | 1910103: Anadia;19 &;5 &;1 &;1 &;1 &;11 &;0 &;,,, 114 | 1910105: Aveiro;44 &;18 &;0 &;0 &;0 &;26 &;0 &;,,, 115 | 1910108: Estarreja;43 &;10 &;18 &;0 &;3 &;12 &;0 &;,,, 116 | 1910110: �lhavo;23 &;5 &;0 &;0 &;0 &;18 &;0 &;,,, 117 | 1910112: Murtosa;4 &;3 &;0 &;0 &;0 &;1 &;0 &;,,, 118 | 1910114: Oliveira do Bairro;20 &;8 &;7 &;0 &;0 &;5 &;0 &;,,, 119 | 1910115: Ovar;23 &;5 &;9 &;0 &;0 &;9 &;0 &;,,, 120 | 1910117: Sever do Vouga;15 &;7 &;6 &;1 &;1 &;0 &;0 &;,,, 121 | 1910118: Vagos;29 &;9 &;0 &;0 &;1 &;19 &;0 &;,,, 122 | 192: Regi�o de Coimbra;277 &;94 &;151 &;5 &;3 &;24 &;0 &;,,, 123 | 1920601: Arganil;2 &;1 &;1 &;0 &;0 &;0 &;0 &;,,, 124 | 1920602: Cantanhede;64 &;10 &;49 &;0 &;0 &;5 &;0 &;,,, 125 | 1920603: Coimbra;33 &;20 &;12 &;0 &;0 &;1 &;0 &;,,, 126 | 1920604: Condeixa-a-Nova;6 &;5 &;1 &;0 &;0 &;0 &;0 &;,,, 127 | 1920605: Figueira da Foz;32 &;14 &;18 &;0 &;0 &;0 &;0 &;,,, 128 | 1920606: G�is;6 &;2 &;3 &;0 &;0 &;1 &;0 &;,,, 129 | 1920607: Lous�;21 &;3 &;16 &;0 &;0 &;2 &;0 &;,,, 130 | 1920111: Mealhada;18 &;1 &;12 &;0 &;0 &;5 &;0 &;,,, 131 | 1920608: Mira;11 &;5 &;3 &;0 &;0 &;3 &;0 &;,,, 132 | 1920609: Miranda do Corvo;11 &;4 &;3 &;0 &;0 &;4 &;0 &;,,, 133 | 1920610: Montemor-o-Velho;26 &;7 &;16 &;0 &;3 &;0 &;0 &;,,, 134 | 1921808: Mort�gua;6 &;3 &;0 &;3 &;0 &;0 &;0 &;,,, 135 | 1920611: Oliveira do Hospital;13 &;3 &;7 &;2 &;0 &;1 &;0 &;,,, 136 | 1920612: Pampilhosa da Serra;3 &;0 &;1 &;0 &;0 &;2 &;0 &;,,, 137 | 1920613: Penacova;5 &;4 &;1 &;0 &;0 &;0 &;0 &;,,, 138 | 1920614: Penela;8 &;3 &;5 &;0 &;0 &;0 &;0 &;,,, 139 | 1920615: Soure;7 &;4 &;3 &;0 &;0 &;0 &;0 &;,,, 140 | 1920616: T�bua;3 &;3 &;0 &;0 &;0 &;0 &;0 &;,,, 141 | 1920617: Vila Nova de Poiares;2 &;2 &;0 &;0 &;0 &;0 &;0 &;,,, 142 | 193: Regi�o de Leiria;171 &;79 &;60 &;1 &;9 &;22 &;0 &;,,, 143 | 1931002: Alvai�zere;6 &;3 &;1 &;0 &;1 &;1 &;0 &;,,, 144 | 1931003: Ansi�o;5 &;1 &;3 &;0 &;0 &;1 &;0 &;,,, 145 | 1931004: Batalha;6 &;2 &;1 &;0 &;0 &;3 &;0 &;,,, 146 | 1931007: Castanheira de P�ra;4 &;1 &;1 &;0 &;0 &;2 &;0 &;,,, 147 | 1931008: Figueir� dos Vinhos;5 &;4 &;1 &;0 &;0 &;0 &;0 &;,,, 148 | 1931009: Leiria;70 &;30 &;23 &;0 &;6 &;11 &;0 &;,,, 149 | 1931010: Marinha Grande;16 &;11 &;3 &;0 &;0 &;2 &;0 &;,,, 150 | 1931013: Pedr�g�o Grande;7 &;3 &;4 &;0 &;0 &;0 &;0 &;,,, 151 | 1931015: Pombal;35 &;13 &;19 &;1 &;1 &;1 &;0 &;,,, 152 | 1931016: Porto de M�s;17 &;11 &;4 &;0 &;1 &;1 &;0 &;,,, 153 | 194: Viseu D�o Laf�es;324 &;175 &;106 &;6 &;4 &;33 &;0 &;,,, 154 | 1940901: Aguiar da Beira;11 &;6 &;5 &;0 &;0 &;0 &;0 &;,,, 155 | 1941802: Carregal do Sal;7 &;4 &;3 &;0 &;0 &;0 &;0 &;,,, 156 | 1941803: Castro Daire;80 &;65 &;10 &;0 &;0 &;5 &;0 &;,,, 157 | 1941806: Mangualde;23 &;9 &;12 &;0 &;1 &;1 &;0 &;,,, 158 | 1941809: Nelas;17 &;5 &;11 &;0 &;0 &;1 &;0 &;,,, 159 | 1941810: Oliveira de Frades;10 &;2 &;7 &;0 &;0 &;1 &;0 &;,,, 160 | 1941811: Penalva do Castelo;12 &;2 &;10 &;0 &;0 &;0 &;0 &;,,, 161 | 1941814: Santa Comba D�o;2 &;1 &;1 &;0 &;0 &;0 &;0 &;,,, 162 | 1941816: S�o Pedro do Sul;10 &;6 &;1 &;2 &;1 &;0 &;0 &;,,, 163 | 1941817: S�t�o;18 &;7 &;10 &;0 &;1 &;0 &;0 &;,,, 164 | 1941821: Tondela;28 &;16 &;7 &;1 &;0 &;4 &;0 &;,,, 165 | 1941822: Vila Nova de Paiva;41 &;23 &;17 &;1 &;0 &;0 &;0 &;,,, 166 | 1941823: Viseu;58 &;26 &;12 &;1 &;0 &;19 &;0 &;,,, 167 | 1941824: Vouzela;7 &;3 &;0 &;1 &;1 &;2 &;0 &;,,, 168 | 195: Beira Baixa;143 &;93 &;26 &;13 &;1 &;10 &;0 &;,,, 169 | 1950502: Castelo Branco;58 &;35 &;11 &;4 &;0 &;8 &;0 &;,,, 170 | 1950505: Idanha-a-Nova;18 &;15 &;1 &;1 &;1 &;0 &;0 &;,,, 171 | 1950506: Oleiros;9 &;2 &;4 &;2 &;0 &;1 &;0 &;,,, 172 | 1950507: Penamacor;11 &;4 &;5 &;2 &;0 &;0 &;0 &;,,, 173 | 1950508: Proen�a-a-Nova;10 &;7 &;1 &;1 &;0 &;1 &;0 &;,,, 174 | 1950509: Sert�;19 &;16 &;3 &;0 &;0 &;0 &;0 &;,,, 175 | 1950510: Vila de Rei;6 &;4 &;1 &;1 &;0 &;0 &;0 &;,,, 176 | 1950511: Vila Velha de R�d�o;12 &;10 &;0 &;2 &;0 &;0 &;0 &;,,, 177 | 196: Beiras e Serra da Estrela;255 &;134 &;63 &;20 &;1 &;37 &;0 &;,,, 178 | 1960902: Almeida;8 &;6 &;1 &;1 &;0 &;0 &;0 &;,,, 179 | 1960501: Belmonte;10 &;8 &;0 &;0 &;0 &;2 &;0 &;,,, 180 | 1960903: Celorico da Beira;6 &;4 &;1 &;1 &;0 &;0 &;0 &;,,, 181 | 1960503: Covilh�;68 &;27 &;11 &;3 &;0 &;27 &;0 &;,,, 182 | 1960904: Figueira de Castelo Rodrigo;17 &;9 &;7 &;0 &;0 &;1 &;0 &;,,, 183 | 1960905: Fornos de Algodres;7 &;2 &;4 &;1 &;0 &;0 &;0 &;,,, 184 | 1960504: Fund�o;36 &;25 &;6 &;2 &;1 &;2 &;0 &;,,, 185 | 1960906: Gouveia;6 &;6 &;0 &;0 &;0 &;0 &;0 &;,,, 186 | 1960907: Guarda;23 &;9 &;10 &;2 &;0 &;2 &;0 &;,,, 187 | 1960908: Manteigas;1 &;0 &;0 &;1 &;0 &;0 &;0 &;,,, 188 | 1960909: M�da;11 &;3 &;6 &;2 &;0 &;0 &;0 &;,,, 189 | 1960910: Pinhel;11 &;5 &;3 &;3 &;0 &;0 &;0 &;,,, 190 | 1960911: Sabugal;27 &;18 &;6 &;1 &;0 &;2 &;0 &;,,, 191 | 1960912: Seia;11 &;5 &;4 &;1 &;0 &;1 &;0 &;,,, 192 | 1960913: Trancoso;13 &;7 &;4 &;2 &;0 &;0 &;0 &;,,, 193 | 1D: Oeste e Vale do Tejo;829 &;333 &;255 &;1 &;10 &;144 &;86 &;,,, 194 | 1D1: Oeste;342 &;79 &;106 &;0 &;5 &;66 &;86 &;,,, 195 | 1D11001: Alcoba�a;26 &;16 &;7 &;0 &;0 &;3 &;0 &;,,, 196 | 1D11101: Alenquer;42 &;8 &;13 &;0 &;0 &;21 &;0 &;,,, 197 | 1D11102: Arruda dos Vinhos;2 &;0 &;0 &;0 &;0 &;2 &;0 &;,,, 198 | 1D11005: Bombarral;9 &;6 &;2 &;0 &;0 &;1 &;0 &;,,, 199 | 1D11104: Cadaval;48 &;3 &;29 &;0 &;4 &;12 &;0 &;,,, 200 | 1D11006: Caldas da Rainha;58 &;26 &;30 &;0 &;0 &;2 &;0 &;,,, 201 | 1D11108: Lourinh�;30 &;1 &;0 &;0 &;0 &;5 &;24 &;,,, 202 | 1D11011: Nazar�;7 &;4 &;2 &;0 &;0 &;1 &;0 &;,,, 203 | 1D11012: �bidos;32 &;8 &;20 &;0 &;1 &;3 &;0 &;,,, 204 | 1D11014: Peniche;5 &;2 &;3 &;0 &;0 &;0 &;0 &;,,, 205 | 1D11112: Sobral de Monte Agra�o;14 &;0 &;0 &;0 &;0 &;1 &;13 &;,,, 206 | 1D11113: Torres Vedras;69 &;5 &;0 &;0 &;0 &;15 &;49 &;,,, 207 | 1D2: M�dio Tejo;240 &;113 &;99 &;1 &;4 &;23 &;0 &;,,, 208 | 1D21401: Abrantes;41 &;23 &;14 &;0 &;1 &;3 &;0 &;,,, 209 | 1D21402: Alcanena;22 &;14 &;5 &;0 &;0 &;3 &;0 &;,,, 210 | 1D21408: Const�ncia;11 &;2 &;2 &;0 &;0 &;7 &;0 &;,,, 211 | 1D21410: Entroncamento;7 &;3 &;3 &;0 &;0 &;1 &;0 &;,,, 212 | 1D21411: Ferreira do Z�zere;10 &;3 &;6 &;1 &;0 &;0 &;0 &;,,, 213 | 1D21413: Ma��o;8 &;7 &;1 &;0 &;0 &;0 &;0 &;,,, 214 | 1D21421: Our�m;70 &;22 &;44 &;0 &;3 &;1 &;0 &;,,, 215 | 1D21417: Sardoal;6 &;6 &;0 &;0 &;0 &;0 &;0 &;,,, 216 | 1D21418: Tomar;33 &;19 &;11 &;0 &;0 &;3 &;0 &;,,, 217 | 1D21419: Torres Novas;26 &;10 &;11 &;0 &;0 &;5 &;0 &;,,, 218 | 1D21420: Vila Nova da Barquinha;6 &;4 &;2 &;0 &;0 &;0 &;0 &;,,, 219 | 1D3: Lez�ria do Tejo;247 &;141 &;50 &;0 &;1 &;55 &;0 &;,,, 220 | 1D31403: Almeirim;10 &;7 &;2 &;0 &;0 &;1 &;0 &;,,, 221 | 1D31404: Alpiar�a;8 &;6 &;1 &;0 &;0 &;1 &;0 &;,,, 222 | 1D31103: Azambuja;27 &;8 &;2 &;0 &;0 &;17 &;0 &;,,, 223 | 1D31405: Benavente;31 &;25 &;2 &;0 &;0 &;4 &;0 &;,,, 224 | 1D31406: Cartaxo;18 &;11 &;3 &;0 &;1 &;3 &;0 &;,,, 225 | 1D31407: Chamusca;13 &;5 &;5 &;0 &;0 &;3 &;0 &;,,, 226 | 1D31409: Coruche;28 &;24 &;3 &;0 &;0 &;1 &;0 &;,,, 227 | 1D31412: Goleg�;3 &;1 &;0 &;0 &;0 &;2 &;0 &;,,, 228 | 1D31414: Rio Maior;24 &;6 &;12 &;0 &;0 &;6 &;0 &;,,, 229 | 1D31415: Salvaterra de Magos;26 &;16 &;3 &;0 &;0 &;7 &;0 &;,,, 230 | 1D31416: Santar�m;59 &;32 &;17 &;0 &;0 &;10 &;0 &;,,, 231 | 1A: Grande Lisboa;225 &;30 &;0 &;0 &;7 &;187 &;1 &;,,, 232 | 1A0: Grande Lisboa;225 &;30 &;0 &;0 &;7 &;187 &;1 &;,,, 233 | 1A01115: Amadora;21 &;0 &;0 &;0 &;0 &;20 &;1 &;,,, 234 | 1A01105: Cascais;24 &;2 &;0 &;0 &;3 &;19 &;0 &;,,, 235 | 1A01106: Lisboa;7 &;0 &;0 &;0 &;0 &;7 &;0 &;,,, 236 | 1A01107: Loures;14 &;4 &;0 &;0 &;1 &;9 &;0 &;,,, 237 | 1A01109: Mafra;30 &;13 &;0 &;0 &;1 &;16 &;0 &;,,, 238 | 1A01116: Odivelas;1 &;1 &;0 &;0 &;0 &;0 &;0 &;,,, 239 | 1A01110: Oeiras;18 &;0 &;0 &;0 &;0 &;18 &;0 &;,,, 240 | 1A01111: Sintra;85 &;1 &;0 &;0 &;0 &;84 &;0 &;,,, 241 | 1A01114: Vila Franca de Xira;25 &;9 &;0 &;0 &;2 &;14 &;0 &;,,, 242 | 1B: Pen�nsula de Set�bal;204 &;96 &;23 &;0 &;11 &;74 &;0 &;,,, 243 | 1B0: Pen�nsula de Set�bal;204 &;96 &;23 &;0 &;11 &;74 &;0 &;,,, 244 | 1B01502: Alcochete;13 &;13 &;0 &;0 &;0 &;0 &;0 &;,,, 245 | 1B01503: Almada;6 &;1 &;0 &;0 &;0 &;5 &;0 &;,,, 246 | 1B01504: Barreiro;16 &;5 &;5 &;0 &;0 &;6 &;0 &;,,, 247 | 1B01506: Moita;22 &;8 &;7 &;0 &;1 &;6 &;0 &;,,, 248 | 1B01507: Montijo;36 &;20 &;7 &;0 &;0 &;9 &;0 &;,,, 249 | 1B01508: Palmela;75 &;30 &;2 &;0 &;10 &;33 &;0 &;,,, 250 | 1B01510: Seixal;4 &;0 &;0 &;0 &;0 &;4 &;0 &;,,, 251 | 1B01511: Sesimbra;11 &;8 &;1 &;0 &;0 &;2 &;0 &;,,, 252 | 1B01512: Set�bal;21 &;11 &;1 &;0 &;0 &;9 &;0 &;,,, 253 | 1C: Alentejo;541 &;290 &;33 &;4 &;7 &;207 &;0 &;,,, 254 | 1C1: Alentejo Litoral;98 &;47 &;0 &;2 &;2 &;47 &;0 &;,,, 255 | 1C11501: Alc�cer do Sal;26 &;11 &;0 &;0 &;0 &;15 &;0 &;,,, 256 | 1C11505: Gr�ndola;23 &;9 &;0 &;0 &;0 &;14 &;0 &;,,, 257 | 1C10211: Odemira;23 &;13 &;0 &;2 &;0 &;8 &;0 &;,,, 258 | 1C11509: Santiago do Cac�m;16 &;11 &;0 &;0 &;1 &;4 &;0 &;,,, 259 | 1C11513: Sines;10 &;3 &;0 &;0 &;1 &;6 &;0 &;,,, 260 | 1C2: Baixo Alentejo;156 &;101 &;15 &;0 &;0 &;40 &;0 &;,,, 261 | 1C20201: Aljustrel;13 &;12 &;0 &;0 &;0 &;1 &;0 &;,,, 262 | 1C20202: Almod�var;10 &;7 &;3 &;0 &;0 &;0 &;0 &;,,, 263 | 1C20203: Alvito;6 &;2 &;0 &;0 &;0 &;4 &;0 &;,,, 264 | 1C20204: Barrancos;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 265 | 1C20205: Beja;34 &;12 &;7 &;0 &;0 &;15 &;0 &;,,, 266 | 1C20206: Castro Verde;7 &;5 &;1 &;0 &;0 &;1 &;0 &;,,, 267 | 1C20207: Cuba;5 &;4 &;0 &;0 &;0 &;1 &;0 &;,,, 268 | 1C20208: Ferreira do Alentejo;12 &;11 &;0 &;0 &;0 &;1 &;0 &;,,, 269 | 1C20209: M�rtola;4 &;0 &;1 &;0 &;0 &;3 &;0 &;,,, 270 | 1C20210: Moura;17 &;14 &;2 &;0 &;0 &;1 &;0 &;,,, 271 | 1C20212: Ourique;12 &;12 &;0 &;0 &;0 &;0 &;0 &;,,, 272 | 1C20213: Serpa;24 &;16 &;1 &;0 &;0 &;7 &;0 &;,,, 273 | 1C20214: Vidigueira;12 &;6 &;0 &;0 &;0 &;6 &;0 &;,,, 274 | 1C3: Alto Alentejo;145 &;105 &;9 &;2 &;3 &;26 &;0 &;,,, 275 | 1C31201: Alter do Ch�o;2 &;2 &;0 &;0 &;0 &;0 &;0 &;,,, 276 | 1C31202: Arronches;7 &;7 &;0 &;0 &;0 &;0 &;0 &;,,, 277 | 1C31203: Avis;8 &;6 &;0 &;0 &;0 &;2 &;0 &;,,, 278 | 1C31204: Campo Maior;21 &;17 &;1 &;0 &;0 &;3 &;0 &;,,, 279 | 1C31205: Castelo de Vide;3 &;2 &;0 &;0 &;0 &;1 &;0 &;,,, 280 | 1C31206: Crato;3 &;3 &;0 &;0 &;0 &;0 &;0 &;,,, 281 | 1C31207: Elvas;34 &;26 &;1 &;0 &;1 &;6 &;0 &;,,, 282 | 1C31208: Fronteira;4 &;4 &;0 &;0 &;0 &;0 &;0 &;,,, 283 | 1C31209: Gavi�o;5 &;2 &;3 &;0 &;0 &;0 &;0 &;,,, 284 | 1C31210: Marv�o;6 &;5 &;1 &;0 &;0 &;0 &;0 &;,,, 285 | 1C31211: Monforte;3 &;2 &;0 &;0 &;0 &;1 &;0 &;,,, 286 | 1C31212: Nisa;6 &;1 &;3 &;0 &;0 &;2 &;0 &;,,, 287 | 1C31213: Ponte de Sor;20 &;11 &;0 &;1 &;1 &;7 &;0 &;,,, 288 | 1C31214: Portalegre;10 &;8 &;0 &;1 &;1 &;0 &;0 &;,,, 289 | 1C31215: Sousel;13 &;9 &;0 &;0 &;0 &;4 &;0 &;,,, 290 | 1C4: Alentejo Central;142 &;37 &;9 &;0 &;2 &;94 &;0 &;,,, 291 | 1C40701: Alandroal;6 &;5 &;0 &;0 &;0 &;1 &;0 &;,,, 292 | 1C40702: Arraiolos;10 &;1 &;0 &;0 &;0 &;9 &;0 &;,,, 293 | 1C40703: Borba;4 &;1 &;0 &;0 &;0 &;3 &;0 &;,,, 294 | 1C40704: Estremoz;6 &;1 &;0 &;0 &;0 &;5 &;0 &;,,, 295 | 1C40705: �vora;30 &;4 &;0 &;0 &;0 &;26 &;0 &;,,, 296 | 1C40706: Montemor-o-Novo;11 &;3 &;0 &;0 &;0 &;8 &;0 &;,,, 297 | 1C40707: Mora;3 &;1 &;0 &;0 &;0 &;2 &;0 &;,,, 298 | 1C40708: Mour�o;13 &;2 &;3 &;0 &;0 &;8 &;0 &;,,, 299 | 1C40709: Portel;11 &;4 &;0 &;0 &;1 &;6 &;0 &;,,, 300 | 1C40710: Redondo;12 &;2 &;0 &;0 &;1 &;9 &;0 &;,,, 301 | 1C40711: Reguengos de Monsaraz;17 &;6 &;6 &;0 &;0 &;5 &;0 &;,,, 302 | 1C40712: Vendas Novas;9 &;3 &;0 &;0 &;0 &;6 &;0 &;,,, 303 | 1C40713: Viana do Alentejo;4 &;3 &;0 &;0 &;0 &;1 &;0 &;,,, 304 | 1C40714: Vila Vi�osa;6 &;1 &;0 &;0 &;0 &;5 &;0 &;,,, 305 | 15: Algarve;275 &;139 &;25 &;0 &;1 &;110 &;0 &;,,, 306 | 150: Algarve;275 &;139 &;25 &;0 &;1 &;110 &;0 &;,,, 307 | 1500801: Albufeira;34 &;6 &;0 &;0 &;0 &;28 &;0 &;,,, 308 | 1500802: Alcoutim;5 &;2 &;1 &;0 &;0 &;2 &;0 &;,,, 309 | 1500803: Aljezur;8 &;3 &;3 &;0 &;0 &;2 &;0 &;,,, 310 | 1500804: Castro Marim;16 &;8 &;3 &;0 &;0 &;5 &;0 &;,,, 311 | 1500805: Faro;27 &;20 &;0 &;0 &;0 &;7 &;0 &;,,, 312 | 1500806: Lagoa;6 &;3 &;1 &;0 &;0 &;2 &;0 &;,,, 313 | 1500807: Lagos;8 &;4 &;1 &;0 &;0 &;3 &;0 &;,,, 314 | 1500808: Loul�;64 &;26 &;8 &;0 &;1 &;29 &;0 &;,,, 315 | 1500809: Monchique;11 &;8 &;3 &;0 &;0 &;0 &;0 &;,,, 316 | 1500810: Olh�o;24 &;21 &;0 &;0 &;0 &;3 &;0 &;,,, 317 | 1500811: Portim�o;8 &;4 &;1 &;0 &;0 &;3 &;0 &;,,, 318 | 1500812: S�o Br�s de Alportel;4 &;2 &;0 &;0 &;0 &;2 &;0 &;,,, 319 | 1500813: Silves;31 &;21 &;2 &;0 &;0 &;8 &;0 &;,,, 320 | 1500814: Tavira;19 &;8 &;0 &;0 &;0 &;11 &;0 &;,,, 321 | 1500815: Vila do Bispo;4 &;3 &;0 &;0 &;0 &;1 &;0 &;,,, 322 | 1500816: Vila Real de Santo Ant�nio;6 &;0 &;2 &;0 &;0 &;4 &;0 &;,,, 323 | 2: Regi�o Aut�noma dos A�ores;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 324 | 20: Regi�o Aut�noma dos A�ores;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 325 | 200: Regi�o Aut�noma dos A�ores;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 326 | 2004301: Angra do Hero�smo;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 327 | 2004501: Calheta (R.A.A.);0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 328 | 2004901: Corvo;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 329 | 2004701: Horta;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 330 | 2004201: Lagoa (R.A.A.);0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 331 | 2004801: Lajes das Flores;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 332 | 2004601: Lajes do Pico;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 333 | 2004602: Madalena;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 334 | 2004202: Nordeste;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 335 | 2004203: Ponta Delgada;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 336 | 2004204: Povoa��o;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 337 | 2004205: Ribeira Grande;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 338 | 2004401: Santa Cruz da Graciosa;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 339 | 2004802: Santa Cruz das Flores;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 340 | 2004603: S�o Roque do Pico;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 341 | 2004502: Velas;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 342 | 2004302: Vila da Praia da Vit�ria;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 343 | 2004101: Vila do Porto;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 344 | 2004206: Vila Franca do Campo;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 345 | 3: Regi�o Aut�noma da Madeira;39 &;6 &;2 &;0 &;0 &;31 &;0 &;,,, 346 | 30: Regi�o Aut�noma da Madeira;39 &;6 &;2 &;0 &;0 &;31 &;0 &;,,, 347 | 300: Regi�o Aut�noma da Madeira;39 &;6 &;2 &;0 &;0 &;31 &;0 &;,,, 348 | 3003101: Calheta (R.A.M.);7 &;0 &;1 &;0 &;0 &;6 &;0 &;,,, 349 | 3003102: C�mara de Lobos;3 &;2 &;0 &;0 &;0 &;1 &;0 &;,,, 350 | 3003103: Funchal;1 &;1 &;0 &;0 &;0 &;0 &;0 &;,,, 351 | 3003104: Machico;1 &;1 &;0 &;0 &;0 &;0 &;0 &;,,, 352 | 3003105: Ponta do Sol;5 &;0 &;0 &;0 &;0 &;5 &;0 &;,,, 353 | 3003106: Porto Moniz;1 &;1 &;0 &;0 &;0 &;0 &;0 &;,,, 354 | 3003107: Ribeira Brava;20 &;0 &;1 &;0 &;0 &;19 &;0 &;,,, 355 | 3003108: Santa Cruz;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 356 | 3003109: Santana;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 357 | 3003110: S�o Vicente;1 &;1 &;0 &;0 &;0 &;0 &;0 &;,,, 358 | 3003201: Porto Santo;0 &;0 &;0 &;0 &;0 &;0 &;0 &;,,, 359 | ,,, 360 | Rural fires (No.) by Geographic localization (NUTS - 2024) and Cause of fire - Annual - ICNF, Forestry statistics,, 361 | ,,, 362 | ,,, 363 | This data last updated:october 16,2024,, 364 | ,,, 365 | ,,, 366 | Table Metadata,,, 367 | ,,, 368 | Rural fires (No.),,, 369 | Name;Rural fires (No.) by Geographic localization (NUTS - 2024) and Cause of fire - Annual,,, 370 | Regularity;Annual,,, 371 | Source;ICNF, Forestry statistics,, 372 | First available period;2001,,, 373 | Last available period;2023,,, 374 | Dimensions,,, 375 | Dimension 1;Data reference period,,, 376 | Dimension 2;Geographic localization (NUTS - 2024),,, 377 | Dimension 3;Cause of fire,,, 378 | Concepts,,, 379 | REFERENCE PERIOD;Period to which the information refers and which may be a specific day or a time interval (month, fiscal year, calendar year, among others). 380 | RURAL FIRE;Outbreak or progression of fire, in an unplanned or uncontrolled manner, in rural territory, requiring suppression actions. 381 | Definition;,,, 382 | Formule;,,, 383 | Measure unit (symbol);Number (No.),,, 384 | Power of 10;0,,, 385 | Last update date;16-Out-2024,,, 386 | --------------------------------------------------------------------------------