diff --git a/subjects/devops/append-output/README.md b/subjects/devops/append-output/README.md index e4612da67f..664a57eae2 100644 --- a/subjects/devops/append-output/README.md +++ b/subjects/devops/append-output/README.md @@ -2,9 +2,9 @@ ### Instructions -Create a file `append-output.sh` that will get the output of a file and parse it, and then write it to a file with a specific format using a single command. +Create a shell script named `append-output.sh` that processes the content of an existing file and writes the result into another file using a single command. -Get the content of the file `songs.txt`, parse it with the `grep` command to filter the file in order to get all the songs from the artist whose names start with `J`, and write the output to the existing file `results.txt`, check the example below: +Specifically, read the contents of the file `songs.txt`, filter them with the `grep` command to select only the songs by artists whose names begin with the letter **J**, and append the filtered output to the file `results.txt`. ### Usage diff --git a/subjects/devops/auto-exec-bin/README.md b/subjects/devops/auto-exec-bin/README.md index 7a242d8e97..a2b6cf6e87 100644 --- a/subjects/devops/auto-exec-bin/README.md +++ b/subjects/devops/auto-exec-bin/README.md @@ -15,7 +15,7 @@ $ ls -l ~/myBins # the binary 01exec $ 01exec error: command not found: 01exec -$ ./auto-exec-bin.sh +$ source ./auto-exec-bin.sh $ 01exec Hello 01 Scripting Pool $ cd /{random-path} && 01exec diff --git a/subjects/devops/candidates-checker/README.md b/subjects/devops/candidates-checker/README.md new file mode 100644 index 0000000000..f6cbfff0bf --- /dev/null +++ b/subjects/devops/candidates-checker/README.md @@ -0,0 +1,57 @@ +## Candidates checker + +### Instructions + +Create a file `candidates_checker.py` which will receive the number of candidates as the only argument. +If a wrong number of arguments is passed the script will print `Error: wrong number of arguments` and exit with `1`. + +When provided, the argument will always be convertible to `int`, the script will then ask for each candidate the name as string and the age as number. + +Once the information for each candidate is retrieved for each of them the script will check the age and print one of the following results: + +- `"[name] is not eligible (underaged)"` when the age is less than 18. +- `"[name] is not eligible (over the legal age)"` when the age is more than 60. +- `"[name] is eligible"` when the age is between 18 and 60 (included). + +> You must use dictionaries to save the data about the candidates. + +### Usage + +Here is an example of your script running: + +```console +$ python3 candidates_checker.py 3 +Add a new candidate: +name: Edoardo +age: 17 +Add a new candidate: +name: Michele +age: 60 +Add a new candidate: +name: Lea +age: 61 +Edoardo is not eligible (underaged) +Michele is eligible +Lea is not eligible (over the legal age) +$ +``` + +Here is an example of bad usage: + +```console +$ python3 candidates_checker.py +Error: wrong number of arguments +$ +``` + +### Hints + +- In order to succeed your script should print **exactly** the same output as the one in the usage section. So `Add a new candidate:`, `name: ` and `age: ` should be written in the exact same way and order. + +- Tough it is not mandatory you could use `if __name__ == '__main__':` to specify the entrypoint of your script. + +### References + +- [Function strip()](https://docs.python.org/3.11/library/stdtypes.html?highlight=strip#str.strip) +- [String multiplication](https://www.geeksforgeeks.org/create-multiple-copies-of-a-string-in-python-by-using-multiplication-operator/) +- [Entrypoint for a Python script](https://realpython.com/if-name-main-python/) diff --git a/subjects/devops/check-user/README.md b/subjects/devops/check-user/README.md index 7cd4db7ccb..be61417fe3 100644 --- a/subjects/devops/check-user/README.md +++ b/subjects/devops/check-user/README.md @@ -2,16 +2,16 @@ ### Instructions -In this exercise you will make a script `check-user.sh` that will take 2 arguments and return information about the selected user, always ended by a new line. +In this exercise, you will create a script called `check-user.sh` that accepts two arguments and returns information about a specified user. Each output should end with a newline. -The first argument will be a flag defining the behavior of the script: +The **first argument** is a flag that defines the script’s behavior: -- `-e`: check if the user exists, returns `yes` or `no` appropriately. -- `-i`: returns information about the user. +- `-e`: Check if the user exists, returning `yes` or `no` accordingly. +- `-i`: Display information about the user. -The second argument will be the name of the checked user. +The **second argument** is the username to be checked. -> The information about the user will be formatted in the same way it appears in `/etc/passwd`. +The user information must be displayed in the same format as it appears in `/etc/passwd`. ### Usage diff --git a/subjects/devops/cl-camp3/README.md b/subjects/devops/cl-camp3/README.md new file mode 100644 index 0000000000..daa974ff11 --- /dev/null +++ b/subjects/devops/cl-camp3/README.md @@ -0,0 +1,15 @@ +## cl-camp3 + +### Instructions + +"start looking ..." + +Create a file `look`, which will look for and show, in the current directory and its sub-folders: + +- everything that starts with an `a` or, +- all the files ending with a `z` or, +- all files starting with `z` and ending with `a!`. + +### Hint + +Read the `find` man... diff --git a/subjects/devops/cl-camp6/README.md b/subjects/devops/cl-camp6/README.md new file mode 100644 index 0000000000..4e98850247 --- /dev/null +++ b/subjects/devops/cl-camp6/README.md @@ -0,0 +1,15 @@ +## cl-camp6 + +### Instructions + +"Now, do your inventory" + +Create a file `countfiles.sh`, which will print the number **(and only the number)** of regular files and folders contained in the current directory and its sub-folders (the current directory must be included in the count): + +### Usage + +```console +$ ./countfiles.sh | cat -e +12$ +$ +``` diff --git a/subjects/devops/cl-camp8/README.md b/subjects/devops/cl-camp8/README.md new file mode 100644 index 0000000000..4749229d59 --- /dev/null +++ b/subjects/devops/cl-camp8/README.md @@ -0,0 +1,11 @@ +## cl-camp8 + +### Instructions + +"pick your equipment" + +Write a command line in a `skip.sh` file that prints the result of a `ls -l` skipping 1 line out of 2, starting with the **first** one. + +### Hint + +`awk` or `sed` can do the job. diff --git a/subjects/devops/clean-the-list/README.md b/subjects/devops/clean-the-list/README.md new file mode 100644 index 0000000000..a273800027 --- /dev/null +++ b/subjects/devops/clean-the-list/README.md @@ -0,0 +1,38 @@ +## Clean the list + +### Instructions + +Create a file `clean_the_list.py` that contains a function `clean_list` which takes and returns a list of strings and performs the following operations on each list item: + +- Removes all spaces before and after (but not between words). + +- Capitalizes the first letter (first letter only, other ones should be to lowercase). + +- Adds its index number before a separator `x/ `. + +- An empty list as input should return an empty list as output. + +- And don't forget the milk! (add it at the end of the list if missing). + +### Usage + +Here is an example of how to use the `clean_list` function: + +```python +import clean_the_list +shopping_list = ['tomatoes', 'pastas', 'milk', 'salt'] +print(clean_the_list.clean_list(shopping_list)) +``` + +This will output: + +```console +$ python test.py +['1/ Tomatoes', '2/ Pastas', '3/ Milk', '4/ Salt'] +$ +``` + +### References + +[String strip method](https://www.w3schools.com/python/ref_string_strip.asp) +[String capitalize method](https://www.w3schools.com/python/ref_string_capitalize.asp) diff --git a/subjects/devops/concat-string/README.md b/subjects/devops/concat-string/README.md new file mode 100644 index 0000000000..da5f101e64 --- /dev/null +++ b/subjects/devops/concat-string/README.md @@ -0,0 +1,32 @@ +## concat_string + +### Instructions + +Create a file `concat_string.py` that contains a function `concat` which takes in two strings as parameters and performs the following operations: + +- Concatenates the two strings by adding a comma and space between them. + +- Returns the resulting string. + +### Usage + +Here is an example of how to use the `concat` function in a `test.py` script: + +```python +import concat_string +string1 = "Hello" +string2 = "World" +print(concat_string.concat(string1, string2)) +``` + +Below is the expected output: + +```console +$ python3 test.py +Hello, World +$ +``` + +### References + +[string concatenation](https://docs.python.org/3/tutorial/introduction.html#text) diff --git a/subjects/devops/credentials-searches/README.md b/subjects/devops/credentials-searches/README.md new file mode 100644 index 0000000000..956a52f03f --- /dev/null +++ b/subjects/devops/credentials-searches/README.md @@ -0,0 +1,64 @@ +## credentials_searches + +### Instructions + +Create a file `credentials_searches.py` that contains a function `credentials_search` which takes no parameters and searches for the keys `password` and `secret` in a file called `logs.json`. + +- If both keys are found, the function should create a new json file named `credentials.json` and save the values of those keys in it. + +- If only one of the keys is found, the function should create a new json file named `credentials.json` and save the value of that key in it. + +- If neither key is found, the function should not create the `credentials.json` file. + +- If the `logs.json` file is empty or is not a json file, the function should not create the `credentials.json` file. + +- If the `logs.json` file does not exist, the function should not create the `credentials.json` file. + +- If the keys are found in a nested object, the function should create the `credentials.json` file and save the values of the keys in it. + +### Usage + +Here is an example of how to use the credentials_search function: + +With this file `logs.json`: + +```json +{ + "password": "test_password", + "other": "value", + "secret": "test_secret" +} +``` + +If you run your function: + +```python +credentials_search() +``` + +Your function should generate this file `credentials.json`: + +```json +{ + "password": "test_password", + "secret": "test_secret" +} +``` + +### Hints + +- The `json` module can be used to read and write JSON files. + +- The `os` module can be used to check if a file exists and remove a file. + +- Remember that the function should be able to search for the keys `password` and `secret` in nested json objects. + +- Using the `isinstance` function could be useful to check if a value is for example a dict. + +### References + +- [json module](https://www.w3schools.com/python/python_json.asp) + +- [os module](https://docs.python.org/3/library/os.html) + +- [isinstance function](https://www.w3schools.com/python/ref_func_isinstance.asp) diff --git a/subjects/devops/custom-calendar/README.md b/subjects/devops/custom-calendar/README.md new file mode 100644 index 0000000000..a835425728 --- /dev/null +++ b/subjects/devops/custom-calendar/README.md @@ -0,0 +1,99 @@ +## Custom calendar + +### Instructions + +Create a file `custom_calendar.py` which will have 2 functions: + +- `day_from_number(day_number)` +- `day_to_number(day)` + +Those functions perform conversion between day `index` and day `word`: + +- 1 = Monday +- 2 = Tuesday +- 3 = Wednesday +- 4 = Thursday +- 5 = Friday +- 6 = Saturday +- 7 = Sunday + +You should return `None` if the input is invalid (invalid number or day string). + +### Usage + +Here is a possible `test.py` to test your functions: + +```python +import custom_calendar + +print(custom_calendar.day_from_number(2)) +print(custom_calendar.day_from_number(1)) +print(custom_calendar.day_from_number(1000)) +print(custom_calendar.day_to_number('Sunday')) +print(custom_calendar.day_to_number('invalid day')) +``` + +```console +$ python test.py +Tuesday +Monday +None +7 +None +$ +``` + +### Hints + +Dictionaries: + +A dictionary is a data type similar to arrays, but works with keys and values instead of indexes. Each value stored in a dictionary can be accessed using a key, which is any type of object (a string, a number, a list, etc.) instead of using its index to address it. + +For example, a database of phone numbers could be stored using a dictionary like this: + +```python +phonebook = {} +phonebook["John"] = 938477566 +phonebook["Jack"] = 938377264 +phonebook["Jill"] = 947662781 +print(phonebook) +``` + +output: + +```console +{'John': 938477566, 'Jack': 938377264, 'Jill': 947662781} +``` + +Alternatively, a dictionary can be initialized with the same values in the following notation: + +```python +phonebook = { + "John" : 938477566, + "Jack" : 938377264, + "Jill" : 947662781 +} +print(phonebook) +``` + +Dictionaries can be iterated over, just like a list. To iterate over key value pairs, use the following syntax: + +```python +phonebook = {"John": 938477566, "Jack": 938377264, "Jill": 947662781} +for name, number in phonebook.items(): + print("Phone number of %s is %d" % (name, number)) +``` + +output: + +```console +Phone number of John is 938477566 +Phone number of Jack is 938377264 +Phone number of Jill is 947662781 +``` + +### References + +- [None type](https://www.w3schools.com/python/ref_keyword_none.asp) +- [Dictionaries](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) +- [Access an item in dictionary](https://www.w3schools.com/python/python_dictionaries_access.asp) diff --git a/subjects/devops/custom-ls/README.md b/subjects/devops/custom-ls/README.md index 7d5d6faab6..d1d62ac075 100644 --- a/subjects/devops/custom-ls/README.md +++ b/subjects/devops/custom-ls/README.md @@ -17,7 +17,7 @@ Expected behavior: ```console $ custom-ls error: command not found: custom-ls -$ ./custom-ls.sh +$ source ./custom-ls.sh $ custom-ls . total ... 7784 -rw-r--r-- 1 3983261 Dec 17 22:02 .file1 # just an example diff --git a/subjects/devops/division/README.md b/subjects/devops/division/README.md index ed04894475..699f31ee31 100644 --- a/subjects/devops/division/README.md +++ b/subjects/devops/division/README.md @@ -4,18 +4,15 @@ In this exercise, you will make a script `division.sh` that will take two arguments from the command line, and divide the first one by the second one. -If there is a remainder after doing the division, it should be ignored. +The division should return only the integer quotient (whole number part), ignoring any decimal remainder. You will need to handle what to do when the inputs are wrong: - If the divisor is `0` you will need to output `Error: division by zero is not allowed`. - -- If the arguments are not numbers, the output should be `Error: both arguments must be numeric`. - +- If the arguments are not integers, the output should be `Error: both arguments must be integers`. - In the case where the number of arguments are not enough, the output should be `Error: two numbers must be provided`. -Your script should handle very large numbers as well. - +Your script should handle very large integers as well. For this exercise the use of the `test` command is not allowed. ### Usage @@ -23,6 +20,10 @@ For this exercise the use of the `test` command is not allowed. ```console $ ./divide.sh 4 1 4 +$ ./divide.sh 7 3 +2 +$ ./divide.sh 100 7 +14 $ ``` @@ -35,9 +36,9 @@ You can use the following to help you solve this exercise: ```bash #!/usr/bin/env bash if [[ 1 > 2 ]]; then - echo "true" +echo "true" else - echo "false" +echo "false" fi ``` @@ -52,14 +53,14 @@ It is possible to combine several conditions with the **AND** (`&&`) and **OR** ```bash if [[ 1 > 2 ]] || [[ 1 == 1 ]]; then - echo "true" +echo "true" else - echo "false" +echo "false" fi if [[ 1 > 2 ]] && [[ 1 == 1 ]]; then - echo "true" +echo "true" else - echo "false" +echo "false" fi ``` diff --git a/subjects/devops/easy-conditions/README.md b/subjects/devops/easy-conditions/README.md index f9674e9d5f..4f04145e4e 100644 --- a/subjects/devops/easy-conditions/README.md +++ b/subjects/devops/easy-conditions/README.md @@ -7,10 +7,12 @@ For this exercise it will be given a variable "X" and "Y" and you have to create Expected output ```console +$ export X=6 Y=14 $ echo $X $Y 6 14 $ ./easy-conditions.sh false +$ X=29 Y=12 $ echo $X $Y 29 12 $ ./easy-conditions.sh diff --git a/subjects/devops/file-checker/README.md b/subjects/devops/file-checker/README.md index d8d47eb6c9..1682c6cf04 100644 --- a/subjects/devops/file-checker/README.md +++ b/subjects/devops/file-checker/README.md @@ -28,6 +28,8 @@ File is not writable File is not executable $ ls -l file.txt -r--r--r-- 1 user user 0 Jan 12 08:26 file.txt +$ ./file-checker.sh notExistingFile +File does not exist $ ./file-checker.sh Error: No file provided $ diff --git a/subjects/devops/file-details/README.md b/subjects/devops/file-details/README.md index 1d6e2cc803..89ee288d20 100644 --- a/subjects/devops/file-details/README.md +++ b/subjects/devops/file-details/README.md @@ -24,13 +24,10 @@ dr-------x 2023-02-07 15:34 A ### Hints - `ls -l --time-style=TIME_STYLE` - - Time conversion specifiers you need to know: - - `%R`, 24-hour hour and minute. Same as ‘%H:%M’. - Date conversion specifiers you need to know: - - `%F`, full date in ISO 8601 format; like ‘%+4Y-%m-%d’ except that any flags or field width override the ‘+’ and (after subtracting 6) the ‘4’. This is a good choice for a date format, as it is standard and is easy to sort in the usual case where years are in the range 0000…9999. - You can use `sed` to remove the first line of the output. diff --git a/subjects/devops/find-files-extension/README.md b/subjects/devops/find-files-extension/README.md index 7b2c611073..2cc5b280c5 100644 --- a/subjects/devops/find-files-extension/README.md +++ b/subjects/devops/find-files-extension/README.md @@ -4,9 +4,7 @@ Create a file `find-files-extension.sh`, which will look, from the current directory and its sub-folders for: -all the files with `.txt` extension. - -That command will only show the name of the files without the extension `.txt`. +Every file with a `.txt` extension and display only the file names. - You can use this for testing: https://assets.01-edu.org/devops-branch/find-files-extension-example.zip diff --git a/subjects/devops/find-files/README.md b/subjects/devops/find-files/README.md index 0eee4e2692..01e8047f89 100644 --- a/subjects/devops/find-files/README.md +++ b/subjects/devops/find-files/README.md @@ -6,8 +6,7 @@ Create a file `find-files.sh`, which will look for and show, in the current directory and its sub-folders: -everything (Regular file, Directory file, Link file,...) that starts with an `a` and, -all Regular files ending with a `z` +Any entry that starts with an `a` and regular files ending with a `z` - You can use this for testing: https://assets.01-edu.org/devops-branch/find-files-example.zip diff --git a/subjects/devops/flex-function/README.md b/subjects/devops/flex-function/README.md new file mode 100644 index 0000000000..6ad5c59809 --- /dev/null +++ b/subjects/devops/flex-function/README.md @@ -0,0 +1,51 @@ +## flex_function + +### Instructions + +Create a file `flex_function.py` that contains a function `create_person` which takes in first name and last name as required positional parameters, age and gender as positional or keyword parameters, size and job as keyword only parameters, with size and job default values: size=1.83, job="taxidermist", and returns a dictionary object like this: + +```python +{ + 'first_name': 'Kevin', + 'last_name': 'Boulin', + 'age': 34, + 'gender': 'male', + 'size': 1.83, + 'job': 'taxidermist', +} +``` + +### Usage + +Here is an example of how to use the create_person function: + +```python +person = create_person("Kevin", "Boulin", 34, "male") +print(person) +``` + +And its output: + +```console +$ python3 ./test.py +{'first_name': 'Kevin', 'last_name': 'Boulin', 'age': 34, 'gender': 'male', 'size': 1.83, 'job': 'taxidermist'} +$ +``` + +### Hints + +**Positional parameters** are the parameters that are passed to a function in the same order as they are defined in the function signature. In the create_person function, the first name and last name are considered as positional parameters. + +```python +print("Hello World") +``` + +In this example, "Hello World" is passed as the first and only positional parameter of the function. + +**Keyword parameters** are the parameters that are passed to a function by explicitly specifying the parameter name and its value. In the print() function, the end keyword parameter is used to specify the string to be printed at the end of the line. + +```python +print("Hello", end=" World") +``` + +In this example, the value " World" is passed as the value of the end keyword parameter. diff --git a/subjects/devops/grades/README.md b/subjects/devops/grades/README.md index 353ce3d437..db6489ec4b 100644 --- a/subjects/devops/grades/README.md +++ b/subjects/devops/grades/README.md @@ -2,11 +2,11 @@ ### Instructions -Create a script `grades.sh` which will ask, as an argument, for the user to give a specific number of students in order to evaluate them. After the number is set, the script will ask you to introduce the "names" and "grades" of the persons you wish to evaluate. +Create a script called `grades.sh` that takes, as an argument, the number of students to be evaluated. Once the number is specified, the script should prompt you to enter each student’s **name** and **grade**. -The grades will have a range between 0 and 100 and will be numeric values only. +Grades must be numeric values only, within the range of 0 to 100. -According to each student grade you will have to return the following: +For each student, the script should return an evaluation based on their grade as follows: - If the student grade is anything equal or greater than 90 you will return the string `": You did an excellent job!"`: diff --git a/subjects/devops/greatest-of-all/README.md b/subjects/devops/greatest-of-all/README.md index 2497fc9997..14c9bb2d93 100644 --- a/subjects/devops/greatest-of-all/README.md +++ b/subjects/devops/greatest-of-all/README.md @@ -2,10 +2,31 @@ ### Instructions -Create a script `greatest-of-all.sh` which will ask you to input 10 numbers and then it will check what was the biggest number given. You must ask for the number using the string "Enter a number: " and then use the string "The largest number is: " to print the output like in the example below. +Create a script named `greatest-of-all.sh` that prompts the user to enter **10 numbers** and determines the largest among them. -- Only positive numbers up to "10000" will be tested. -- If the given number is greater than "10000" you must print the error message "ERROR: The number entered is too large" and if its not a number or it is a negative number, print the error "ERROR: Invalid input only positive numerical characters are allowed". When either of these errors occurs, the script will print the error message, exit with an exit code of `1`, and will not continue to execute the next line. +- Each input must be requested using the prompt: + `"Enter a number: "` + +- Once all inputs are collected, display the result using: + `"The largest number is: "` + +#### Constraints + +- Only positive numbers up to **10000** will be tested. + +- If a number greater than **10000** is entered, the script must display: + `"ERROR: The number entered is too large"` + +- If the input is not a valid number, or if it is negative, the script must display: + `"ERROR: Invalid input only positive numerical characters are allowed"` + +#### Behavior on Error + +When an error occurs: + +1. Print the corresponding error message. +2. Exit immediately with an exit code of `1`. +3. Do not continue executing subsequent lines of the script. ### Usage diff --git a/subjects/devops/head-and-tail/README.md b/subjects/devops/head-and-tail/README.md index fadc4c6753..57ebca8842 100644 --- a/subjects/devops/head-and-tail/README.md +++ b/subjects/devops/head-and-tail/README.md @@ -4,7 +4,7 @@ Create the script `head-and-tail.sh` which will show the first and last lines of the file `HeadTail.txt` -- Where to look : https://assets.01-edu.org/devops-branch/HeadTail.txt +- Where to look : https://((DOMAIN))/assets/devops-branch/HeadTail.txt - What to use : `curl` and `head` and `tail` @@ -22,7 +22,7 @@ $ With `curl` you can get the content of the file from the url: ```console -$ curl https://assets.01-edu.org/devops-branch/HeadTail.txt +$ curl https://((DOMAIN))/assets/devops-branch/HeadTail.txt <...> $ ``` diff --git a/subjects/devops/hello-devops/README.md b/subjects/devops/hello-devops/README.md index 1a97dd4b70..89a51696cc 100644 --- a/subjects/devops/hello-devops/README.md +++ b/subjects/devops/hello-devops/README.md @@ -9,7 +9,7 @@ #### 1- get-ready -Create in your [Gitea]() account the repository named `((ROOT))`. +Create in your [Gitea]() account the repository named `((ROOT))`. This repository will be the folder where all the exercises must be uploaded. diff --git a/subjects/devops/hello-python/README.md b/subjects/devops/hello-python/README.md new file mode 100644 index 0000000000..1446869a4f --- /dev/null +++ b/subjects/devops/hello-python/README.md @@ -0,0 +1,56 @@ +## Hello Python + +### Welcome to Python (Finally!) + +After a week and a half of shell scripting, file permissions, and wrestling with Unix commands, you've earned yourself a change of scenery. Welcome to Python - where syntax errors are friendlier and you don't have to remember whether it's `chmod +x` or `chmod 755` anymore. + +### Instructions + +Create a file `hello_python.py` and write inside a function `say_hello_python` that returns the string `"Hello Python!"`. + +```python +def say_hello_python(): + # this is a function, + # write your code here +``` + +### Usage + +Here is a possible code to test your function. Put it in another file (ex: `test.py`): + +```python +from hello_python import say_hello_python + +print(say_hello_python()) +``` + +Run your test file with the following command: + +```console +$ python3 test.py +Hello Python! +$ +``` + +> `test.py` file should be in the same directory of `hello_python.py` in order to work. + +### A Moment of Relief + +Take a breath. No file permissions to debug. No mysterious shell variables to track down. No grep patterns to perfect. Just a simple function that returns a string. This should feel refreshingly straightforward after your recent adventures in the terminal. + +### Hints + +- Python uses indentation to indicate in which block your code will run (many other languages uses parenthesis instead). It is then very important to indent your code properly. + +- `return` is a special world used to say which value a function should return (a function could also not return anything). + For example `return 10` will return the number ten. + +- A string is a set of characters wrapped by `"`. + For example `"Ciao bella"` is a string containing the worlds `Ciao Bella`. + +- In `test.py` we are calling another function named `print`. This function is already present in Python standard library so we don't have to create it. This function at its core is made to write strings in the standard output. + +### References + +- [Indentation in Python](https://www.w3schools.com/python/gloss_python_indentation.asp) +- [Python print function](https://www.w3schools.com/python/ref_func_print.asp) diff --git a/subjects/devops/in-back-ground/README.md b/subjects/devops/in-back-ground/README.md index ea100aa25c..017770e894 100644 --- a/subjects/devops/in-back-ground/README.md +++ b/subjects/devops/in-back-ground/README.md @@ -2,13 +2,14 @@ ### Instructions -Create a script `in-back-ground.sh` which will execute a job in the background that will do the following: - -- Run the command `cat` on the file [facts](../../../sh/tests/left/facts) which will read the contents of the file and print it to `stdout`. -- The output of the cat command will be piped to the `grep` command, which will search for the string `"moon"` in the file. -- If the `grep` command succeeds (if it finds the string "moon"): - - You will print `"The moon fact was found!"` to the `output.txt` file. If it fails the file `output.txt` is not created. - - You should also print the line which contains the string to the `stdout`. +Create a script named `in-back-ground.sh` that executes a job in the background with the following behavior: + +1. Run the `cat` command on the file [facts](./facts). +2. Pipe the output of `cat` into the `grep` command to search for the string `"moon"`. +3. If the `grep` command succeeds (i.e., it finds a line containing `"moon"`): + - Append the message `"The moon fact was found!"` to the file `output.txt`. + - Also, print the matching line to **stdout**. +4. If the `grep` command does not find the string, the file `output.txt` should not be created. You must do all these steps running only one job and using the command `nohup`! diff --git a/subjects/devops/joker-num/README.md b/subjects/devops/joker-num/README.md index 9cd2d830b8..89b4c12e38 100644 --- a/subjects/devops/joker-num/README.md +++ b/subjects/devops/joker-num/README.md @@ -8,7 +8,7 @@ To achieve this you will have to use a `for` loop. When you're trying to guess the secret number with a valid input, your program must output some tips as follow: -- First you will need to prompt a message so that the player knows what he must do: `"Enter your guess ( tries left)`. +- First you will need to prompt a message so that the player knows what he must do: `"Enter your guess ( tries left)"`. - If the number is bigger than the secret one: `Go down`. - If the number si smaller than the secret one: `Go up`. - If the number is the correct one: `Congratulations, you found the number in moves!`. @@ -37,9 +37,9 @@ $ ### Error handling - If the player enters the wrong number of arguments or the number is not between `1` and `100`, the program will print `Error: wrong argument` and exit with `1`. -- If the player is writing something that is not a valid number as an answer, the program will ask again to enter a new a guess and the number of tries won't be decremented. +- If the player is writing something that is not a valid number as an answer, the program will ask again to enter a new guess and the number of tries won't be decremented. -Here an example for the last scenario: +Here's an example for the last scenario: ```console $ ./joker-num.sh 100 diff --git a/subjects/devops/master-the-ls/README.md b/subjects/devops/master-the-ls/README.md index dd4f86168e..29d34c79b6 100644 --- a/subjects/devops/master-the-ls/README.md +++ b/subjects/devops/master-the-ls/README.md @@ -15,7 +15,6 @@ Create a script `master-the-ls.sh`, that will do the following: Here are some Commands that can help you: - `tr`. Translate characters: run replacements based on single characters and character sets. - - Replace all occurrences of a character in a file, and print the result: `tr {{find_character}} {{replace_character}} < {{filename}}` diff --git a/subjects/devops/merge-two/README.md b/subjects/devops/merge-two/README.md new file mode 100644 index 0000000000..0ee9bd49c8 --- /dev/null +++ b/subjects/devops/merge-two/README.md @@ -0,0 +1,74 @@ +## Merge two + +One very useful data structure in Python are the dictionaries, in this exercise we will start to familiarize and use them. + +### Instructions + +Create a file `merge_two.py` which will have a function named `merge_two()`. This function will accept one dictionary. +It will prompt the user to create a new dictionary asking for keys and values. +The function will always convert the `values` into integers. + +As a return it will create a third one which will be the merge of the two dictionaries and return it as a serialized JSON string. + +> If the key entered by the user is `exit` the function will stop asking for new key/values pairs and proceed to generate the desired output. + +Here is the prototype of the function: + +```python +def merge_two(first_dict): + # this is a function, + # write your code here +``` + +### Usage + +Here is a possible code to test your function. Put it in another file (ex: `test.py`): + +```python +from merge_two import merge_two + +first = { + "Bob": 36, + "Louise": 23, + "Lea": 34 +} + +print(merge_two(first)) +``` + +Run your test file with the following command: + +```console +$ python3 test.py +Add a new entry: +key: Louise +value: 44 +Add a new entry: +key: Romolo +value: 30 +Add a new entry: +key: Lea +value: 22 +Add a new entry: +key: exit +{"Bob": 36, "Louise": 44, "Lea": 22, "Romolo": 30} +$ +``` + +### Hints + +- If a key is repeated in both dictionaries the value retained will be the last one. + +- There are different ways to merge dictionaries, take the time to understand the differences in between those techniques and try more than one technique to better retain it. + +- Add `import json` to use the standard functions for JSON manipulation. + +- Use the function `input()` to read from `stdin` and `int()` to convert the value to a number. + +> Your solution will be tested only for valid inputs (all the values will be convertible to `int`). + +### References + +- [Merging dictionaries in Python](https://www.geeksforgeeks.org/python-merging-two-dictionaries/) +- [JSON library in Python](https://docs.python.org/3/library/json.html) +- [Function input() in Python](https://www.w3schools.com/python/ref_func_input.asp) diff --git a/subjects/devops/numerical-operations-the-return/README.md b/subjects/devops/numerical-operations-the-return/README.md new file mode 100644 index 0000000000..24e3777150 --- /dev/null +++ b/subjects/devops/numerical-operations-the-return/README.md @@ -0,0 +1,44 @@ +## Numerical operations: the return! + +### Instructions + +Create a file `numerical_operations_the_return.py` containing the following functions: + +- `modulo(a, b)` +- `divide(a, b)` +- `integer_division(a, b)` + +We assume that `a` and `b` are numbers (`int` or `float`). + +> In case of a division by zero or modulo zero your functions should return `0`. + +### Usage + +Here is a possible `test.py` to test your functions: + +```python +import numerical_operations_the_return + +print(numerical_operations_the_return.modulo(10, 3)) +print(numerical_operations_the_return.divide(10, 3)) +print(numerical_operations_the_return.divide(10, 0)) +print(numerical_operations_the_return.integer_division(10, 3)) +``` + +```bash +$ python3 test.py +1 +3.3333333333333335 +0 +3 +$ +``` + +### Hints + +- Some operations will panic in special cases (like division by zero), it is very important to always account for those cases and handle them properly in order to avoid bugs. +- In `Python 2` a division with two integers will return an integer, in `Python 3` it will return a float. We assume you are using `Python 3`, in case you want to force the `Python 3` behavior you can cast one of the operands to float like so: `float(a)`. + +### References + +- [conditions](https://www.w3schools.com/python/python_conditions.asp) diff --git a/subjects/devops/numerical-operations/README.md b/subjects/devops/numerical-operations/README.md new file mode 100644 index 0000000000..7abd6a18fb --- /dev/null +++ b/subjects/devops/numerical-operations/README.md @@ -0,0 +1,72 @@ +## Numerical operation + +### Instructions + +Create a file `numerical_operations.py` containing the following functions: + +- `add(a, b)` +- `subtract(a, b)` +- `multiply(a, b)` +- `power(a, b)` +- `square_root(a)` + +We assume that `a` and `b` are numbers (`int` or `float`). + +### Usage + +Here is a possible `test.py` to test your functions: + +```python +import numerical_operations + +print(numerical_operations.add(2, 2)) +print(numerical_operations.subtract(10, 5)) +print(numerical_operations.multiply(3, 4)) +print(numerical_operations.power(3, 3)) +print(numerical_operations.square_root(3)) +``` + +```bash +$ python test.py +4 +5 +12 +27 +1.73205080757 +$ +``` + +### [Optional] Use a virtual environnement to run python code locally + +Virtual environments can help you to run your code locally. + +[Learn all you need about virtual environments](https://openclassrooms.com/fr/courses/6951236-mettez-en-place-votre-environnement-python/7013854-decouvrez-les-environnements-virtuels). + +Here, we setup a virtual environment with Miniconda. + +First, [download and install Miniconda](https://docs.conda.io/en/latest/miniconda.html). + +Then, use those commands to create a new environment: + +```bash +# create a new virtual environment for python 3.10 +$ conda create --name my_env python=3.10 + +# activate your new environment +$ conda activate my_env + +# From now, all python command use this python version in this terminal +$ python --version +Python 3.10.4 +``` + +> We advise you to create one virtual environment per python project. Later, we could also install external packages on our environment. + +### Hints + +- You could `import math` at the start of your file to use the functions defined in that library (for example `math.sqrt()`). + +### References + +- [Square root in Python](https://www.geeksforgeeks.org/python-math-function-sqrt/) +- [Operations in Python](https://www.geeksforgeeks.org/python-arithmetic-operators/) diff --git a/subjects/devops/object-to-json/README.md b/subjects/devops/object-to-json/README.md new file mode 100644 index 0000000000..ca91c278ff --- /dev/null +++ b/subjects/devops/object-to-json/README.md @@ -0,0 +1,72 @@ +## object_to_json + +A lot of information on the web are shared in the JSON format. This exercise will be about transforming object to JSON and vice-versa. + +### Instructions + +You just landed a new job, congrats! Your new task is to build two functions to allow new users to register to your new shiny website. + +The new registration information comes as string formatted as JSON. You need to create a file `object_to_json.py` that will have the following functions inside: + +1. `create_new_user` that will receive a `dict` and will return a new object of the class `User` provided below. To be valid, the input `dict` must have a `username` key and an `email` key. The new `User` will have the same `username` and `email` of the input `dict`. If the input `dict` is invalid, the default user will be returned. + +```python +class User: + username = 'user' + email = 'something@mail.com' +``` + +2. `user_to_json` that will receive a `User` and will return the object as a string in JSON format. Be aware of the Python types that can be converted to JSON! + +### Usage + +Here is a possible `test.py` to test your functions: + +```python +from object_to_json import create_new_user, user_to_json + +registration_0 = '{"username": "mario", "email": "mario@me.it"}' +registration_1 = '{"city": "Rome", "country": "Italy"}' + +user_0 = create_new_user(registration_0) +user_1 = create_new_user(registration_1) + +print(user_to_json(user_0)) +print(user_to_json(user_1)) +``` + +```console +$ python3 test.py +{"username": "mario", "email": "mario@me.it"} +{} +$ +``` + +### Hints + +- In python, it is possible to define a class and create a class object with the following syntax: + +```python +class MyCalss: # define a new class + attribute1 = 0 + attribute2 = 'something else' + +my_obj = MyClass() # create an object of MyClass +``` + +- It is possible to convert an object to `dict` using the `__dict__` casting. + +```python +class C: + a = 1 + b = 2 + +my_obj = C() +my_obj_dict = my_obj.__dict__ # my_obj_dict will be a dictionary with the object my_obj values +``` + +### References + +- [Class and Object](https://docs.python.org/3/tutorial/classes.html#a-first-look-at-classes) +- [json.loads()](https://www.geeksforgeeks.org/json-loads-in-python/) +- [json.dumps()](https://www.geeksforgeeks.org/json-dumps-in-python/) diff --git a/subjects/devops/punishment/README.md b/subjects/devops/punishment/README.md index b2271c1793..03a5823509 100644 --- a/subjects/devops/punishment/README.md +++ b/subjects/devops/punishment/README.md @@ -4,7 +4,7 @@ Often in schools we are asked to copy hundreds of sentences in order to better remember not to do something, this punishment is very old and quite boring! -Hopefully we now have Python that can do the job for us. +Thankfully we now have Python that can do the job for us. In order to do so create a file `punishment.py` which will contain a function `do_punishment` having 3 arguments: - `first_part`: which will be a string. diff --git a/subjects/devops/read-file/README.md b/subjects/devops/read-file/README.md new file mode 100644 index 0000000000..6992604fc9 --- /dev/null +++ b/subjects/devops/read-file/README.md @@ -0,0 +1,93 @@ +## Read file + +### Instructions + +Create a file `read_file.py` which will have a function `get_recipes(file_name)` that takes the `file name` as an argument. + +Create another file `recipes_data.json` and paste the following content on it: + +```json +[ + { + "title": "Vegetable Lasagna", + "ingredients": [ + "1 lb. lasagna noodles", + "1 onion, diced", + "2 cloves of garlic, minced", + "2 bell peppers, diced", + "1 zucchini, diced", + "1 eggplant, diced", + "1 (28 oz) can crushed tomatoes", + "1/4 cup chopped fresh basil", + "1/4 cup chopped fresh parsley", + "1/4 cup grated Parmesan cheese", + "1 cup ricotta cheese", + "2 cups shredded mozzarella cheese" + ], + "people": 6 + }, + { + "title": "Stir-Fried Shrimp with Vegetables", + "ingredients": [ + "1 lb. large shrimp, peeled and deveined", + "2 tbsp. vegetable oil", + "1 red bell pepper, sliced", + "1 onion, sliced", + "1 cup sliced mushrooms", + "2 cloves of garlic, minced", + "1/4 cup soy sauce", + "1/4 cup hoisin sauce", + "2 tbsp. rice vinegar", + "1 tsp. sesame oil", + "1 tsp. sugar", + "1/4 tsp. red pepper flakes" + ], + "people": 4 + }, + { + "title": "Spicy Chicken Tacos", + "ingredients": [ + "1 lb. boneless, skinless chicken breasts", + "1 tbsp. chili powder", + "1 tsp. cumin", + "1/2 tsp. paprika", + "1/4 tsp. salt", + "1/4 tsp. black pepper", + "1 tbsp. vegetable oil", + "8 small flour or corn tortillas", + "1 cup shredded lettuce", + "1/2 cup diced tomatoes", + "1/4 cup sour cream", + "1/4 cup chopped fresh cilantro" + ], + "people": 4 + } +] +``` + +Your function has to read the file `recipes_data.json` and load its content into a list of dictionaries. + +Expected output format: + +```python +[{...}, {...}, {...}] +``` + +### Usage + +Here is a possible `test.py` to test your functions: + +```python +import read_file + +print(read_file.get_recipes('recipes_data.json')) +``` + +```bash +$ python test.py +[{'title': 'Vegetable Lasagna', 'ingredients': ['1 lb. lasagna noodles', '1 onion, diced', '2 cloves of garlic, minced', '2 bell peppers, diced', '1 zucchini, diced', '1 eggplant, diced', '1 (28 oz) can crushed tomatoes', '1/4 cup chopped fresh basil', '1/4 cup chopped fresh parsley', '1/4 cup grated Parmesan cheese', '1 cup ricotta cheese', '2 cups shredded mozzarella cheese'], 'people': 6}, {'title': 'Stir-Fried Shrimp with Vegetables', 'ingredients': ['1 lb. large shrimp, peeled and deveined', '2 tbsp. vegetable oil', '1 red bell pepper, sliced', '1 onion, sliced', '1 cup sliced mushrooms', '2 cloves of garlic, minced', '1/4 cup soy sauce', '1/4 cup hoisin sauce', '2 tbsp. rice vinegar', '1 tsp. sesame oil', '1 tsp. sugar', '1/4 tsp. red pepper flakes'], 'people': 4}, {'title': 'Spicy Chicken Tacos', 'ingredients': ['1 lb. boneless, skinless chicken breasts', '1 tbsp. chili powder', '1 tsp. cumin', '1/2 tsp. paprika', '1/4 tsp. salt', '1/4 tsp. black pepper', '1 tbsp. vegetable oil', '8 small flour or corn tortillas', '1 cup shredded lettuce', '1/2 cup diced tomatoes', '1/4 cup sour cream', '1/4 cup chopped fresh cilantro'], 'people': 4}] +``` + +### References + +- [Python and json basics](https://www.w3schools.com/python/python_json.asp) diff --git a/subjects/devops/remake/README.md b/subjects/devops/remake/README.md index c45c4c3aaf..7e4bba3c57 100644 --- a/subjects/devops/remake/README.md +++ b/subjects/devops/remake/README.md @@ -9,6 +9,8 @@ If the number of given arguments is not one or if the directory given as argumen Below the expected behavior of your script: ```console +$ ls -a given-path +. .. $ bash remake.sh given-path $ ls -ltr given-path total 8 diff --git a/subjects/devops/right/README.md b/subjects/devops/right/README.md index 0bb8147ab7..337930b54b 100644 --- a/subjects/devops/right/README.md +++ b/subjects/devops/right/README.md @@ -2,9 +2,7 @@ ### Instructions -Create a file `right.sh` that will get the output of a file and parse it, and then write it to a file with a specific format using a single command. - -Get the output of the `ls` command, parse it with the `grep` command to filter for files without a `.txt` extension, and write the output to a file called `filtered_files.txt`, check the example below: +Create a file `right.sh` where you write a shell command that lists all the files in the current directory except those with the `.txt` extension, and save the resulting list into a file named `filtered_files.txt`. Check the example below: ### Usage diff --git a/subjects/devops/skip-lines/README.md b/subjects/devops/skip-lines/README.md index 2dc199fb18..fb01fbff68 100644 --- a/subjects/devops/skip-lines/README.md +++ b/subjects/devops/skip-lines/README.md @@ -2,7 +2,7 @@ ### Instructions -Write a command line in a `skip-lines.sh` file that prints the result of a `ls -l` skipping 1 line out of 2, starting with the **first** one. +Write a command line in a `skip-lines.sh` file that prints the result of a `ls -l` skipping every even line, starting with the **first** one. Example: @@ -29,7 +29,6 @@ drwxr-xr-x 2 User User 4096 set 29 10:34 Pictures Here are some Commands that can help you: - `sed`. Edit text in a scriptable manner. - - Print just a first line to stdout: `{{command}} | sed -n '1p'` diff --git a/subjects/devops/skip-secrets/README.md b/subjects/devops/skip-secrets/README.md new file mode 100644 index 0000000000..f186a061c8 --- /dev/null +++ b/subjects/devops/skip-secrets/README.md @@ -0,0 +1,73 @@ +## skip_secrets + +### Instructions + +You need to write a script, `skip_secrets.py`, that will be able to decrypt the text coming from a specific file. + +The script will receive a file name as the first argument, check if the file is readable, filter the content by skipping all the lines containing `pineapple` and save the result in a file `out.txt` + +If the file passed as argument is not readable or the number of arguments is not the one expected, the script should exit with a status code `1`. + +### Usage + +Below an example of how the script is supposed to work: + +```console +$ cat -e file.txt +A normal pizza $ +Another normal pizza$ +A pizza with pineapple$ +Yet another very normal and delicious pizza$ +$ python3 skip_secrets.py +$ echo $? +1 +$ python3 skip_secrets.py file.txt +$ cat out.txt +A normal pizza $ +Another normal pizza$ +A pizza with pineapple$ +Yet another very normal and delicious pizza$ +$ +``` + +### Hints + +- It is possible to read arguments passed to a python script using the `sys` module. Here is an example of script (`argv.py`): + +```python +import sys + +for argv in sys.argv: + print(argv) +``` + +And its output: + +```console +$ python3 argv.py 1 2 3 something else +argv.py +1 +2 +3 +something +else +$ +``` + +- It is possible to interrupt the execution of a script and returning a status code different from `0` with the function `exit()`. For example, consider the following `example.py`: + +```python +exit(1) +``` + +This would be the result: + +```console +$ python3 example.py +$ echo $? # check the status code +1 +``` + +### Reference + +[Python sys.argv](https://docs.python.org/3/library/sys.html#sys.argv) diff --git a/subjects/devops/string-processing/README.md b/subjects/devops/string-processing/README.md new file mode 100644 index 0000000000..fdc1ccd7d5 --- /dev/null +++ b/subjects/devops/string-processing/README.md @@ -0,0 +1,91 @@ +## String processing + +### Instructions + +Tokenization is the process of breaking down a string into smaller pieces, called tokens. In natural language processing, tokenization typically refers to the process of breaking down a sentence into words or breaking down a paragraph into sentences. + +Create a file `string_processing.py` which will have a function `tokenize(sentence)` that given a sentence will do the following: + +- remove all punctuation marks and special characters +- separate all words like so: `"it's not 3" => ['it', 's', 'not', '3']` +- put all the words in lowercase +- return a list of all the words. + +### Usage + +Here is a possible `test.py` to test your functions: + +```python +import string_processing + +if __name__ == '__main__': + my_sentence = "It's not possible, you can't ask for a raise" + print(string_processing.tokenize(my_sentence)) +``` + +```bash +$ python test.py +['it', 's', 'not', 'possible', 'you', 'can', 't', 'ask', 'for', 'a', 'raise'] +``` + +### Hints + +The `re` library is a module for working with regular expressions. It provides a set of functions for working with regular expressions, including: + +- `re.sub()` : Replaces all occurrences of a regular expression pattern in a string with a replacement string. + +```python +text = "This is a test sentence. It has multiple punctuation marks!" + +# Replace all exclamation marks with question marks +new_text = re.sub("!", "?", text) + +print(new_text) +``` + +and the output: + +```console +This is a test sentence. It has multiple punctuation marks? +``` + +The `.lower()` method is used to convert the sentence to lowercase before tokenizing it. + +```python +text = "This Is A TeST Sentence." + +lower_text = text.lower() + +print(lower_text) +``` + +and the output: + +```console +this is a test sentence. +``` + +The `.split()` method is used to split the sentence into a list of words. + +```python +text = "This is a test sentence." + +words = text.split() + +print(words) +``` + +and the output: + +```console +['This', 'is', 'a', 'test', 'sentence.'] +``` + +### References + +- [string methods](https://www.w3schools.com/python/python_ref_string.asp) +- [replace](https://www.w3schools.com/python/ref_string_replace.asp) +- [split](https://www.w3schools.com/python/ref_string_split.asp) +- [String punctuations](https://docs.python.org/3/library/string.html#string.punctuation) +- [Tokenization in text analysis](https://en.wikipedia.org/wiki/Lexical_analysis#Tokenization) +- [Word segmentation](https://en.wikipedia.org/wiki/Text_segmentation#Word_segmentation) diff --git a/subjects/devops/string-tokenizer-count/README.md b/subjects/devops/string-tokenizer-count/README.md new file mode 100644 index 0000000000..2fa78b6d61 --- /dev/null +++ b/subjects/devops/string-tokenizer-count/README.md @@ -0,0 +1,59 @@ +## string_tokenizer_count + +### Instructions + +Create a file `string_tokenizer_count.py` that contains a function `tokenizer_counter` which takes in a string as a parameter and returns a dictionary of words and their count in the string. + +- The function should remove any punctuation from the string and convert it to lowercase before counting the words. + +- The function should return a dictionary of words and their count, sorted alphabetically by word. + +### Usage + +Here is an example of how to use the function in a `test.py` script: + +```python +string = "This is a test sentence, with various words and 123 numbers!" +result = tokenizer_counter(string) +print(result) +``` + +And its output: + +```console +$ python3 test.py +{'123': 1, 'a': 1, 'and': 1, 'is': 1, 'numbers': 1, 'sentence': 1, 'test': 1, 'this': 1, 'various': 1, 'with': 1, 'words': 1} +$ +``` + +### Hints + +- The `re` module can be used to remove non-alphanumeric characters. + +- The `Counter` class of the `collections` module can be used to count the words. + +- The `operator` module can be used to sort the dictionary alphabetically by word. + +Here is an example of how to sort a dictionary in python, using a `test.py` script: + +```python +dictionary = {'a': 5, 'c': 1, 'b': 3} +sorted_dict = dict(sorted(d.items(), key=lambda item: item[1])) +print(sorted_dict) +``` + +And its output: + +```console +$ python3 ./test.py +{'c': 1, 'b': 3, 'a': 5} +$ +``` + +### References + +- [`re` module](https://docs.python.org/3/library/re.html) + +- [`collections` module](https://docs.python.org/3/library/collections.html) + +- [`operator` module](https://docs.python.org/3/library/operator.html) diff --git a/subjects/devops/write-file/README.md b/subjects/devops/write-file/README.md new file mode 100644 index 0000000000..1315436691 --- /dev/null +++ b/subjects/devops/write-file/README.md @@ -0,0 +1,86 @@ +## Write file + +### Instructions + +Create a file `write_file.py` which will have a function `to_do(input)` with one input as an argument `list[tuple[dt.date, str]]` which will be a to-do list like the following example: + +```python +[ + (dt.date(2022, 6, 1), "fix the seat"), + (dt.date(2022, 6, 2), "take the trash"), +] +``` + +Your function needs to format and write the input in a text file `output.txt` as follows: + +```bash +$ cat output.txt +Wednesday 01 June 2022: fix the seat +Thursday 02 June 2022: take the trash +$ +``` + +Make sure you follow the correct format for the output. The given lists will always have the correct format and will never be empty. + +### Usage + +Here is a possible `test.py` to test your function: + +```python +import datetime as dt +from write_file import to_do + +to_do_list = [ + (dt.date(2022, 6, 1), "fix the seat"), + (dt.date(2022, 6, 2), "take the trash"), +] +to_do(to_do_list) +``` + +```bash +$ python test.py +$ cat output.txt +Wednesday 01 June 2022: fix the seat +Thursday 02 June 2022: take the trash +$ +``` + +### Hints + +- The `strftime() `method is used to format the date object as a string. You can use this method to format the date in the desired format (e.g. %A %d %B %Y). + +```python +import datetime as dt + +date = dt.date(2022, 6, 1) +formatted_date = date.strftime("%A %d %B %Y") +print(formatted_date) +``` + +The output: + +```bash +Wednesday 01 June 2022 +``` + +- The `%A` and `%B` format codes are used to represent the full weekday and month name respectively. The `%d` format code is used to represent the day of the month. The `%Y` format code is used to represent the year. + +- The `write()` method is used to write a string to a file. You can use this method to write the formatted date and task to the output file. + +```py +with open("output.txt", "w") as file: + file.write("Hello World!") +``` + +In this example, the `open()` function is used to open the file named `output.txt` with the write mode `w`. The `with` statement is used to open the file, and automatically close it after the indented block of code is executed. + +The `write()` method is used to write the string "Hello World!" to the file. + +- Make sure to include a newline character `\n` at the end of each line of output, to separate the tasks in the output file. + +- Test your function with different input formats, different date and task length, different date range and make sure that it works as expected. + +### References + +- [open a file](https://docs.python.org/3/tutorial/inputoutput.html#tut-files) +- [write in a file](https://www.pythontutorial.net/python-basics/python-write-text-file/)