diff --git a/.github/workflows/ga-image-build-branch.yml b/.github/workflows/ga-image-build-branch.yml index fb0244b97e..6b1a30beac 100644 --- a/.github/workflows/ga-image-build-branch.yml +++ b/.github/workflows/ga-image-build-branch.yml @@ -14,17 +14,17 @@ jobs: steps: - name: 🐧 Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v5 - name: πŸ“¦ Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: 🐳 Login to docker.01-edu.org Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: docker.01-edu.org username: ${{ secrets.USER_DOCKER_01EDU_ORG }} diff --git a/.github/workflows/ga-image-build-master.yml b/.github/workflows/ga-image-build-master.yml index 8565c92adb..42770a8588 100644 --- a/.github/workflows/ga-image-build-master.yml +++ b/.github/workflows/ga-image-build-master.yml @@ -11,17 +11,17 @@ jobs: steps: - name: 🐧 Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v5 - name: πŸ“¦ Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: 🐳 Login to docker.01-edu.org Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: docker.01-edu.org username: ${{ secrets.USER_DOCKER_01EDU_ORG }} diff --git a/.github/workflows/ga-misc-check-compliance.yml b/.github/workflows/ga-misc-check-compliance.yml index 6224e1e21f..429beb5aed 100644 --- a/.github/workflows/ga-misc-check-compliance.yml +++ b/.github/workflows/ga-misc-check-compliance.yml @@ -21,7 +21,7 @@ jobs: steps: - name: 🐧 Check out repository code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 diff --git a/.github/workflows/ga-misc-check-links.yml b/.github/workflows/ga-misc-check-links.yml index 1cc8b53462..c82ac8cf6b 100644 --- a/.github/workflows/ga-misc-check-links.yml +++ b/.github/workflows/ga-misc-check-links.yml @@ -16,7 +16,7 @@ jobs: steps: - name: 🐧 Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 @@ -27,6 +27,6 @@ jobs: - name: πŸ”— Run Check Links if: steps.changed-md.outputs.changed_files != '' - uses: harryvasanth/markdown-link-checker@v1.2 + uses: harryvasanth/markdown-link-checker@main with: files: ${{ steps.changed-md.outputs.changed_files }} diff --git a/.github/workflows/ga-misc-check-prettier.yml b/.github/workflows/ga-misc-check-prettier.yml index 620729ffe1..9c6a5c374b 100644 --- a/.github/workflows/ga-misc-check-prettier.yml +++ b/.github/workflows/ga-misc-check-prettier.yml @@ -13,7 +13,7 @@ jobs: steps: - name: 🐧 Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 diff --git a/.github/workflows/ga-misc-check-shellcheck.yml b/.github/workflows/ga-misc-check-shellcheck.yml index ad0a43a57a..5b3a6b81e6 100644 --- a/.github/workflows/ga-misc-check-shellcheck.yml +++ b/.github/workflows/ga-misc-check-shellcheck.yml @@ -14,7 +14,7 @@ jobs: steps: - name: 🐧 Check out repository code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 diff --git a/js/tests/Dockerfile b/js/tests/Dockerfile index 05a241ecb9..c861c98a82 100644 --- a/js/tests/Dockerfile +++ b/js/tests/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.01-edu.org/alpine:3.17.0 +FROM alpine:3 # Installs latest Chromium package. RUN apk add --no-cache \ diff --git a/sh/tests/Dockerfile b/sh/tests/Dockerfile index 27d5dc2477..d6fd102bf3 100644 --- a/sh/tests/Dockerfile +++ b/sh/tests/Dockerfile @@ -1,4 +1,4 @@ -FROM docker.01-edu.org/debian:10-slim +FROM debian:stable-slim RUN apt-get update RUN apt-get -y install jq curl tree apt-utils diff --git a/subjects/ai/backtesting-sp500/README.md b/subjects/ai/backtesting-sp500/README.md index b9c59167d3..900472a914 100644 --- a/subjects/ai/backtesting-sp500/README.md +++ b/subjects/ai/backtesting-sp500/README.md @@ -36,7 +36,6 @@ The input files are: data. The adjusted close price may be unavailable for three main reasons: - - The company doesn't exist at date `d` - The company is not publicly traded - Its close price hasn't been reported @@ -68,7 +67,6 @@ There are four parts: #### 2. Data wrangling and preprocessing - Create a Jupyter Notebook to analyze the data sets and perform EDA (Exploratory Data Analysis). This notebook should contain at least: - - Missing values analysis - Outliers analysis (there are a lot of outliers) - Visualize and analyze the average price for companies over time or compare the price consistency across different companies within the dataset. Save the plot as an image. @@ -77,11 +75,9 @@ There are four parts: _Note: create functions that generate the plots and save them in the `images` directory. Add a parameter `plot` with a default value `False` which doesn't return the plot. This will be useful for the correction to let people run your code without overriding your plots._ - Here is how the `prices` data should be preprocessed: - - Resample data on month and keep the last value - Filter prices outliers: Remove prices outside the range 0.1$, 10k$ - Compute monthly returns: - - Historical returns. **returns(current month) = price(current month) - price(previous month) / price(previous month)** - Future returns. **returns(current month) = price(next month) - price(current month) / price(current month)** @@ -102,7 +98,6 @@ At this stage the DataFrame should look like this: - Print `prices.isna().sum()` - Here is how the `sp500.csv` data should be preprocessed: - - Resample data on month and keep the last value - Compute historical monthly returns on the adjusted close @@ -183,47 +178,38 @@ project ### Tips: 1. Data Quality Management: - - Be prepared to encounter messy data. Financial datasets often contain errors, outliers, and missing values. - Develop a systematic approach to identify and handle data quality issues. 2. Memory Optimization: - - When working with large datasets, optimize memory usage by selecting appropriate data types for each column. - Consider using smaller data types like np.float32 for floating-point numbers when precision allows. 3. Exploratory Data Analysis: - - Spend time understanding the data through visualization and statistical analysis before diving into strategy development. - Pay special attention to outliers and their potential impact on your strategy. 4. Preprocessing Financial Data: - - When resampling time series data, be mindful of which value to keep (e.g., last value for month-end prices). - Calculate both historical and future returns to avoid look-ahead bias in your strategy. 5. Handling Outliers: - - Develop a method to identify and handle outliers that is specific to each company's historical data. - Be cautious about removing outliers during periods of high market volatility (e.g., 2008-2009 financial crisis). 6. Signal Creation: - - Start with a simple signal (like past 12-month average returns) before exploring more complex strategies. - Ensure your signal doesn't use future information that wouldn't have been available at the time of decision. 7. Backtesting: - - Implement your backtesting logic without using loops for better performance. - Compare your strategy's performance against a relevant benchmark (in this case, the S&P 500). 8. Visualization: - - Create clear, informative visualizations to communicate your strategy's performance. - Include cumulative return plots to show how your strategy performs over time compared to the benchmark. 9. Code Structure: - - Organize your code into modular functions for better readability and reusability. - Use a main script to orchestrate the entire process from data loading to results visualization. @@ -232,3 +218,22 @@ project - Be prepared to explain any anomalies or unexpected results in your strategy's performance. Remember, the goal is not just to create a strategy that looks good on paper, but to develop a robust process for analyzing financial data and testing investment ideas. + +### Resources + +- **Python & Data Analysis** + - [pandas Documentation](https://pandas.pydata.org/docs/) – handling time series, resampling, returns. + - [NumPy Documentation](https://numpy.org/doc/) – vectorized operations and memory optimization. + - [Matplotlib Documentation](https://matplotlib.org/stable/index.html) – plotting cumulative returns and EDA visuals. + +- **Finance & Backtesting** + - [Investopedia – Backtesting](https://www.investopedia.com/terms/b/backtesting.asp) – introduction to strategy testing. + - [QuantStart – What is Backtesting?](https://corporatefinanceinstitute.com/resources/data-science/backtesting/#:~:text=Backtesting%20involves%20applying%20a%20strategy,employ%20and%20tweak%20successful%20strategies.) – practical overview of backtesting logic. + - [S&P 500 Index (Wikipedia)](https://en.wikipedia.org/wiki/S%26P_500) – background on the index and its historical changes. + +- **Data Cleaning & Outliers** + - [Handling Missing Data in Pandas](https://pandas.pydata.org/pandas-docs/stable/user_guide/missing_data.html). + +- **Quantitative Strategies** + - [Momentum Investing (Investopedia)](https://www.investopedia.com/terms/m/momentum_investing.asp) – theory behind using past returns as a signal. + - [Risk and Return Basics (CFA Institute)](https://www.investopedia.com/terms/r/riskadjustedreturn.asp) – risk-adjusted performance understanding. diff --git a/subjects/ai/classification/README.md b/subjects/ai/classification/README.md index 19a503aaed..a5e2a475d2 100644 --- a/subjects/ai/classification/README.md +++ b/subjects/ai/classification/README.md @@ -351,12 +351,10 @@ def predict_one_vs_all(X, clf0, clf1, clf2 ): ### Resources -- [Logistic regression](https://towardsdatascience.com/understanding-logistic-regression-9b02c2aec102) +- [Logistic regression](https://www.ibm.com/think/topics/logistic-regression) -- [Logloss](https://www.datacamp.com/tutorial/the-cross-entropy-loss-function-in-machine-learning) +- [Logloss](https://www.geeksforgeeks.org/machine-learning/what-is-cross-entropy-loss-function/) -- [More on logistic regression](https://medium.com/swlh/what-is-logistic-regression-62807de62efa) +- [More on logistic regression](https://www.stat.cmu.edu/~cshalizi/uADA/12/lectures/ch12.pdf) - [Logistic regression 1](https://www.kaggle.com/code/rahulrajpandey31/logistic-regression-from-scratch-iris-data-set) - -- [Logistic regression 2](https://towardsdatascience.com/logistic-regression-using-python-sklearn-numpy-mnist-handwriting-recognition-matplotlib-a6b31e2b166a) diff --git a/subjects/ai/credit-scoring/README.md b/subjects/ai/credit-scoring/README.md index 3ed8741a7a..7e45d7aeed 100644 --- a/subjects/ai/credit-scoring/README.md +++ b/subjects/ai/credit-scoring/README.md @@ -24,21 +24,19 @@ There are 3 expected deliverables associated with the scoring model: - An exploratory data analysis notebook that describes the insights you find out in the data set. - The trained machine learning model with the features engineering pipeline: - - Do not forget: **Coming up with features is difficult, time-consuming, requires expert knowledge. β€˜Applied machine learning’ is basically feature engineering.** - The model is validated if the **AUC on the test set is at minimum 55%, ideally to 62% included (or in best cases higher than 62% if you can !)**. - The labelled test data is not publicly available. However, a Kaggle competition uses the same data. The procedure to evaluate test set submission is the same as the one used for the project 1. - Here are the [DataSets](https://assets.01-edu.org/ai-branch/project5/home-credit-default-risk.zip). - A report on model training and evaluation: - - Include learning curves (training and validation scores vs. training set size or epochs) to demonstrate that the model is not overfitting. - Explain the measures taken to prevent overfitting, such as early stopping or regularization techniques. - Justify your choice of when to stop training based on the learning curves. #### Kaggle submission -The way the Kaggle platform works is explained in the challenge overview page. If you need more details, I suggest [this resource](https://towardsdatascience.com/getting-started-with-kaggle-f9138b35ae18) that gives detailed explanations. +The way the Kaggle platform works is explained in the challenge overview page. If you need more details, I suggest [this resource](https://www.kaggle.com/datasets/parisrohan/credit-score-classification) that gives detailed explanations. - Create a username following that structure: username*01EDU* location_MM_YYYY. Submit the description profile and push it on the Git platform the first day of the week. Do not touch this file anymore. @@ -55,7 +53,7 @@ There are different level of transparency: - **Global**: understand important variables in a model. This answers the question: "What are the key variables to the model ? ". In that case it will tell if the revenue is more important than the age to the model for example. This allows to check that the model relies on important variables. No one wants his credit to be refused because of the weather in Lisbon ! - **Local**: each observation gets its own set of interpretability factors. This greatly increases its transparency. We can explain why a case receives its prediction and the contributions of the predictors. Traditional variable importance algorithms only show the results across the entire population but not on each individual case. The local interpretability enables us to pinpoint and contrast the impacts of the factors. -There are 2 tools you can use to analyse your model and its predictions: - Features importance (available if you use a Scikit Learn model) - [SHAP library](https://towardsdatascience.com/explain-your-model-with-the-shap-values-bc36aac4de3d) +There are 2 tools you can use to analyse your model and its predictions: - Features importance (available if you use a Scikit Learn model) - [SHAP library](https://shap.readthedocs.io/en/latest/) Implement a program that takes as input the trained model, the customer id ... and returns: @@ -121,4 +119,4 @@ Remember, creating a great credit scoring model is like baking a perfect cake - ### Resources -- [Interpreting machine learning models](https://towardsdatascience.com/interpretability-in-machine-learning-70c30694a05f) +- [Interpreting machine learning models](https://neptune.ai/blog/ml-model-interpretation-tools) diff --git a/subjects/ai/data-wrangling/README.md b/subjects/ai/data-wrangling/README.md index 185aa86e2b..59e5eb42c4 100644 --- a/subjects/ai/data-wrangling/README.md +++ b/subjects/ai/data-wrangling/README.md @@ -309,4 +309,4 @@ The first 3 rows of the DataFrame should like this: - [Pandas tutorial](https://www.learndatasci.com/tutorials/python-pandas-tutorial-complete-introduction-for-beginners/) -- [Pandas iteration](https://towardsdatascience.com/different-ways-to-iterate-over-rows-in-a-pandas-dataframe-performance-comparison-dc0d5dcef8fe) +- [Pandas iteration](https://www.geeksforgeeks.org/pandas/different-ways-to-iterate-over-rows-in-pandas-dataframe/) diff --git a/subjects/ai/document-categorization/README.md b/subjects/ai/document-categorization/README.md index fdfa4c3483..1b47a73611 100644 --- a/subjects/ai/document-categorization/README.md +++ b/subjects/ai/document-categorization/README.md @@ -22,7 +22,6 @@ The project aims to develop skills in: #### Data Loading and Preprocessing 1. **Dataset Preparation**: - - Load a dataset containing various document types across multiple categories and languages. - Preprocess the data, including text normalization, tokenization, and handling multi-language support. @@ -33,12 +32,10 @@ The project aims to develop skills in: #### Model Development 1. **Text Classification Model**: - - Implement a **text classification model** using **TensorFlow** or **Keras**, starting with a baseline architecture. - Use **transfer learning** to enhance the model’s domain adaptability, incorporating pre-trained language models such as **BERT** or **DistilBERT**. 2. **Tagging with NLP Libraries**: - - Leverage **SpaCy** to develop an intelligent tagging system that can assign tags based on the document's content and context. - Ensure the tagging system supports multi-language functionality, utilizing language models for effective tagging in different languages. @@ -49,7 +46,6 @@ The project aims to develop skills in: #### Real-Time Document Categorization and Tagging 1. **Real-Time Processing Pipeline**: - - Develop a pipeline to handle real-time document classification and tagging, ensuring minimal latency. - Set up batching or streaming mechanisms to manage high-volume document input and optimize throughput. @@ -60,7 +56,6 @@ The project aims to develop skills in: #### Transfer Learning and Model Optimization 1. **Transfer Learning for Domain-Specific Contexts**: - - Fine-tune the pre-trained language models to specialize in specific document types or industry contexts. - Implement training routines to adapt the model to new domains without extensive retraining on each dataset. @@ -71,7 +66,6 @@ The project aims to develop skills in: #### Visualization and Monitoring 1. **Real-Time Dashboard**: - - Develop a **Streamlit** or **Flask** app to display real-time categorization and tagging results. - Include visualizations of category distributions, tag counts, and language breakdowns. @@ -107,22 +101,48 @@ document-categorization-tagging/ └── requirements.txt ``` -### Timeline (2-3 weeks) +### Tips + +1. **Data Quality & Preprocessing** + - Pay attention to encoding, text cleaning, and normalization, especially with multi-language data. + - Always remove unwanted characters, duplicated text, or formatting artifacts before training. + +2. **Multi-Language Handling** + - Use automatic language detection to route documents to the right SpaCy or Hugging Face model. + - Keep tokenization language-specific to avoid poor segmentation. + +3. **Model Training** + - Start with a small pre-trained model (e.g., DistilBERT) before moving to larger models like BERT. + - Regularly save checkpoints during fine-tuning to avoid losing progress. + +4. **Context-Aware Tagging** + - Use **Named Entity Recognition (NER)** results to enrich tag generation. + - Combine rule-based and machine learning approaches for higher tagging precision. + +5. **Real-Time Performance** + - Batch incoming documents to improve processing speed. + - Consider using asynchronous calls if you implement real-time tagging with Flask or Streamlit. -**Week 1**: +6. **Evaluation** + - Evaluate your model using precision, recall, and F1-score. + - Test the tagging accuracy separately from classification accuracy. -- **Days 1-3**: Dataset loading, EDA, and project structure setup. -- **Days 4-7**: Implement baseline text classification and tagging models with transfer learning. +7. **Visualization** + - Display model performance metrics in the dashboard (accuracy, latency, language stats). + - Visualize the frequency of categories and tags over time. -**Week 2**: +8. **Code Quality** + - Keep your scripts modular and well-documented. + - Use functions for data loading, preprocessing, and inference to simplify debugging and reusability. -- **Days 1-3**: Develop context-aware tagging and real-time processing pipeline. -- **Days 4-7**: Add multi-language support and optimize for high-volume document processing. +9. **Scalability** + - Plan for deployment β€” ensure the pipeline can handle large volumes of documents. + - Optimize models with pruning or quantization to reduce latency. -**Week 3**: +10. **Interpretability** -- **Days 1-4**: Develop the Streamlit/Flask app and integrate visualization and monitoring tools. -- **Days 5-7**: Document the project and prepare the README with usage instructions. +- Log top keywords or entities that influence categorization decisions. +- Make your dashboard explain how and why each document was categorized. ### Resources diff --git a/subjects/ai/emotions-detector/README.md b/subjects/ai/emotions-detector/README.md index f0bc4948d4..df2a0b791d 100644 --- a/subjects/ai/emotions-detector/README.md +++ b/subjects/ai/emotions-detector/README.md @@ -22,7 +22,7 @@ For this project we will focus on two tasks: With the computing power exponentially increasing the computer vision field has been developing exponentially. This is a key element because the computer power allows using more easily a type of neural networks very powerful on images: -- CNN's (Convolutional Neural Networks). Before the CNNs were democratized, the algorithms used relied a lot on human analysis to extract features which obviously time-consuming and not reliable. If you're interested in the "old school methodology" [this article](https://towardsdatascience.com/classifying-facial-emotions-via-machine-learning-5aac111932d3) explains it. +- CNN's (Convolutional Neural Networks). Before the CNNs were democratized, the algorithms used relied a lot on human analysis to extract features which obviously time-consuming and not reliable. If you're interested in the "old school methodology" [this article](https://www.edps.europa.eu/system/files/2021-05/21-05-26_techdispatch-facial-emotion-recognition_ref_en.pdf) explains it. - The history behind this field is fascinating! [Here](https://kapernikov.com/basic-introduction-to-computer-vision/) is a short summary of its history. @@ -65,7 +65,7 @@ Your goal is to implement a program that takes as input a video stream that cont - Download and unzip the [data here](https://assets.01-edu.org/ai-branch/project3/emotions-detector.zip). This dataset was provided for this past [Kaggle challenge](https://www.kaggle.com/competitions/challenges-in-representation-learning-facial-expression-recognition-challenge/overview). - It is possible to find more information about on the challenge page. Train a CNN on the dataset `train.csv`. Here is an [example of architecture](https://www.quora.com/What-is-the-VGG-neural-network) you can implement. + It is possible to find more information about on the challenge page. Train a CNN on the dataset `train.csv`. Here is an [example of architecture](https://viso.ai/deep-learning/vgg-very-deep-convolutional-networks/) you can implement. **The CNN has to perform more than 60% on the test set**. You can use the `test_with_emotions.csv` file for this. You will see that the CNNs take a lot of time to train. You don't want to overfit the neural network. I strongly suggest to use early stopping, callbacks and to monitor the training using the `TensorBoard`. @@ -81,7 +81,6 @@ It is also expected that you explain the iterations and how you end up choosing - Use the video stream outputted by your computer's webcam and preprocess it to make it compatible with the CNN you trained. One of the preprocessing steps is: face detection. As you may have seen the training samples are imaged centered on a face. To do so, I suggest using a pre-trained model to detect faces. OpenCV for image processing tasks where we identify a face from a live webcam feed which is then processed and fed into the trained neural network for emotion detection. The preprocessing pipeline will be corrected with a functional test in `preprocessing_test`: - - **Input**: Video stream of 20 sec with a face on it - **Output**: 20 (or 21) images cropped and centered on the face with 48 x 48 grayscale pixels @@ -166,7 +165,7 @@ Balance technical prowess with psychological insight: as you fine-tune your CNN ### Resources -- [What is computer vision](https://machinelearningmastery.com/what-is-computer-vision/) +- [What is computer vision](https://www.ibm.com/think/topics/computer-vision) - [Use a pre-trained CNN](https://arxiv.org/pdf/1812.06387.pdf) diff --git a/subjects/ai/keras-2/README.md b/subjects/ai/keras-2/README.md index 1263d34f5c..8531c7c35f 100644 --- a/subjects/ai/keras-2/README.md +++ b/subjects/ai/keras-2/README.md @@ -99,19 +99,18 @@ Hint: ### Exercise 2: Regression example The goal of this exercise is to learn to train a neural network to perform a regression on a data set. -The data set is [Auto MPG Dataset](auto-mpg.csv) and the go is to build a model to predict the fuel efficiency of late-1970s and early 1980s automobiles. To do this, provide the model with a description of many automobiles from that time period. This description includes attributes like: cylinders, displacement, horsepower, and weight. +The data set is [Auto MPG Dataset](auto-mpg.csv) and the goal is to build a model to predict the fuel efficiency of late-1970s and early 1980s automobiles. To do this, provide the model with a description of many automobiles from that time period. This description includes attributes like: cylinders, displacement, horsepower, and weight. - [Keras](https://www.tensorflow.org/tutorials/keras/regression) 1. Preprocess the data set as follow: - - Drop the columns: **model year**, **origin**, **car name** - Split train test without shuffling the data. Keep 20% for the test set. - Scale the data using Standard Scaler 2. Train a neural network on the train set and predict on the test set. The neural network should have 2 hidden layers and the loss should be **mean_squared_error**. The expected **mean absolute error** on the test set is maximum 10. _Hint_: increase the number of epochs - **Warning**: Do no forget to evaluate the neural network on the **SCALED** test set. + **Warning**: Do not forget to evaluate the neural network on the **SCALED** test set. --- @@ -126,7 +125,6 @@ The goal of this exercise is to learn to a neural network architecture for multi Let us assume we want to classify images and we know they contain either apples, bears, candies, eggs or dogs (extension of the example in the link above). 1. Create the architecture for a multi-class neural network with the following architecture and return `print(model.summary())`: - - Five inputs variables. - Hidden layer 1: 16 neurons and sigmoid as activation function. - Hidden layer 2: 8 neurons and sigmoid as activation function. @@ -138,7 +136,7 @@ Let us assume we want to classify images and we know they contain either apples, ### Exercise 4: Multi classification - Optimize -The goal of this exercise is to learn to optimize a multi-classification neural network. As learnt previously, the loss function used in binary classification is the log loss - also called in Keras `binary_crossentropy`. This function is defined for binary classification and can be extended to multi-classification. In Keras, the extended loss that supports multi-classification is `binary_crossentropy`. There's no code to run in that exercise. +The goal of this exercise is to learn to optimize a multi-classification neural network. As learnt previously, the loss function used in binary classification is the log loss - also called in Keras `binary_crossentropy`. This function is defined for binary classification and can be extended to multi-classification. In Keras, the extended loss that supports multi-classification is `categorical_crossentropy`. There's no code to run in that exercise. 1. Fill the chunk of code below in order to optimize the neural network defined in the previous exercise. Choose the adapted loss, adam as optimizer and the accuracy as metric. @@ -166,7 +164,7 @@ Preliminary: 2. Train a neural network on the train set and predict on the test set. The neural network should have 1 hidden layers. The expected **accuracy** on the test set is minimum 90%. _Hint_: increase the number of epochs - **Warning**: Do no forget to evaluate the neural network on the **SCALED** test set. + **Warning**: Do not forget to evaluate the neural network on the **SCALED** test set. ### Resources diff --git a/subjects/ai/matrix-factorization/README.md b/subjects/ai/matrix-factorization/README.md index 26550d807b..d60dc3af21 100644 --- a/subjects/ai/matrix-factorization/README.md +++ b/subjects/ai/matrix-factorization/README.md @@ -111,9 +111,9 @@ Remember, a great recommender system needs to understand both the users and the ### Resources -- [Matrix Factorization Techniques for Recommender Systems](https://datajobs.com/data-science-repo/Recommender-Systems-[Netflix].pdf) - A comprehensive overview of matrix factorization methods. +- [Matrix Factorization Techniques for Recommender Systems](https://www.diva-portal.org/smash/get/diva2:633561/FULLTEXT01.pdf) - A comprehensive overview of matrix factorization methods. - [Singular Value Decomposition and Its Applications in Recommender Systems](https://www.cs.uic.edu/~liub/KDD-cup-2007/proceedings/Regular-Paterek.pdf) - Detailed explanation of SVD. -- [Probabilistic Matrix Factorization](https://papers.nips.cc/paper/2007/file/d7322ed717dedf1eb4e6e52a37ea7bcd-Paper.pdf) - Original paper on PMF by Salakhutdinov and Mnih. +- [Probabilistic Matrix Factorization](https://www.cs.toronto.edu/~amnih/papers/bpmf.pdf) - Original paper on PMF by Salakhutdinov and Mnih. - [MovieLens Dataset](https://grouplens.org/datasets/movielens/1m/) - Official page for the MovieLens 1M dataset. - [Scipy sparse.linalg.svds Documentation](https://docs.scipy.org/doc/scipy/reference/generated/scipy.sparse.linalg.svds.html) - Reference for SVD. - [Pandas Documentation](https://pandas.pydata.org/docs/) - Guide for data manipulation with Pandas. diff --git a/subjects/ai/nlp-spacy/README.md b/subjects/ai/nlp-spacy/README.md index e32ee8135b..00cec879f7 100644 --- a/subjects/ai/nlp-spacy/README.md +++ b/subjects/ai/nlp-spacy/README.md @@ -102,8 +102,6 @@ The goal of this exercise is to learn to use `spaCy` embedding on a document. [logo]: ./w3day05ex1_plot.png "Plot" -https://medium.com/datadriveninvestor/cosine-similarity-cosine-distance-6571387f9bf8 - --- --- @@ -172,4 +170,3 @@ The data `news_amazon.txt` used is a newspaper about Amazon. - [Spacy](https://spacy.io/usage/spacy-101) - [NLP 1](https://spacy.io/api/doc) - [NLP 2](https://www.analyticsvidhya.com/blog/2021/06/nlp-application-named-entity-recognition-ner-in-python-with-spacy/) -- [NLP 3](https://medium.com/mlearning-ai/nlp-04-part-of-speech-tagging-in-spacy-dc3e239c2726) diff --git a/subjects/ai/numpy/README.md b/subjects/ai/numpy/README.md index 8b63eb709c..04cce4e5d5 100644 --- a/subjects/ai/numpy/README.md +++ b/subjects/ai/numpy/README.md @@ -296,7 +296,7 @@ The goal of this exercise is to perform fundamental data analysis on real data u The dataset chosen for this task was the [red wine dataset](./data/winequality-red.csv). You can find more info [HERE](./data/) -1. Load the data using `genfromtxt`, specifying the delimiter as ';', and optimize the numpy array size by reducing the data types. Use `np.float32` and verify that the resulting numpy array weighs **76800 bytes**. +1. Load the data using `genfromtxt`, specifying the delimiter as ';' with excluding the headers, and optimize the numpy array size by reducing the data types. Use `np.float32` and verify that the resulting numpy array weighs **76800 bytes**. 2. Display the 2nd, 7th, and 12th rows as a two-dimensional array. Exclude `np.nan` values if present. diff --git a/subjects/ai/pandas/README.md b/subjects/ai/pandas/README.md index 477f3aa9f0..44d7f6b28c 100644 --- a/subjects/ai/pandas/README.md +++ b/subjects/ai/pandas/README.md @@ -66,7 +66,6 @@ I recommend to use: The goal of this exercise is to learn to create basic Pandas objects. 1. Create a DataFrame as below this using two ways: - - From a NumPy array - From a Pandas Series @@ -168,7 +167,7 @@ For this exercise, use [this dataset](./data/iris.csv). ### Resources -- [The ultimate Pandas resource](https://bedford-computing.co.uk/learning/wp-content/uploads/2015/10/Python-for-Data-Analysis.pdf) +- [Awesome pandas](https://github.com/tommyod/awesome-pandas) - [Pandas documentation](https://pandas.pydata.org/docs/) diff --git a/subjects/ai/pipeline/README.md b/subjects/ai/pipeline/README.md index c3d9f15d11..0b63fe9f39 100644 --- a/subjects/ai/pipeline/README.md +++ b/subjects/ai/pipeline/README.md @@ -323,8 +323,6 @@ Resources: - [Resource 2](https://towardsdatascience.com/guide-to-encoding-categorical-features-using-scikit-learn-for-machine-learning-5048997a5c79) -- [Resource 3](https://machinelearningmastery.com/one-hot-encoding-for-categorical-data/) - --- --- @@ -366,7 +364,7 @@ The pipeline you will implement has to contain 3 steps: #### Step 3 -- [Dimensionality reduction](https://towardsdatascience.com/dimensionality-reduction-for-machine-learning-80a46c2ebb7e) +- [Dimensionality reduction](https://www.geeksforgeeks.org/machine-learning/dimensionality-reduction/) #### Step 4 diff --git a/subjects/ai/sp500-strategies/README.md b/subjects/ai/sp500-strategies/README.md index 71e0767ee1..04405907b7 100644 --- a/subjects/ai/sp500-strategies/README.md +++ b/subjects/ai/sp500-strategies/README.md @@ -84,7 +84,7 @@ Once you'll have run the grid search on the cross validation (choose either Bloc **The output is a DataFrame or Series with a double index ordered with the probability the stock price for asset `i` increases between d+1 and d+2.** -- (optional): [Train an RNN/LSTM](https://towardsdatascience.com/predicting-stock-price-with-lstm-13af86a74944). This is a nice way to discover and learn about recurrent neural networks. But keep in mind that there are some new neural network architectures that seem to outperform recurrent neural networks. Here is an [interesting article](https://towardsdatascience.com/the-fall-of-rnn-lstm-2d1594c74ce0) about the topic. +- (optional): [Train an RNN/LSTM](https://medium.com/@aditib259/predicting-stock-prices-using-lstms-time-series-forecasting-a-step-by-step-guide-a70ebb04bbb8). This is a nice way to discover and learn about recurrent neural networks. But keep in mind that there are some new neural network architectures that seem to outperform recurrent neural networks. Here is an [interesting article](https://medium.com/data-science/the-fall-of-rnn-lstm-2d1594c74ce0) about the topic. #### Strategy backtesting @@ -122,7 +122,6 @@ Once you'll have run the grid search on the cross validation (choose either Bloc - Weights proportional to the machine learning signals - invest x on asset `i` for on day - Long and short: For those who search long short strategy on Google, don't get wrong, this has nothing to do with pair trading. - - Binary signal: - -1: take a short position on asset `i` for 1 day - 1: take a long position on asset `i` for 1 day @@ -132,7 +131,6 @@ Once you'll have run the grid search on the cross validation (choose either Bloc - 1: take a long position on asset `i` for 1 day Notes: - - Warning! When you don't invest on all stock as in the binary signal or the ternary signal, make sure that you are still investing $1 per day! - In order to simplify the **short position** we consider that this is the opposite of a long position. Example: I take a short one AAPL stock and the price decreases by $20 on one day. I earn $20. diff --git a/subjects/ai/time-series/README.md b/subjects/ai/time-series/README.md index dcf4814c7a..ce66655f0e 100644 --- a/subjects/ai/time-series/README.md +++ b/subjects/ai/time-series/README.md @@ -158,7 +158,6 @@ We will backtest a **long only** strategy on Apple Inc. Long only means that we - On the 2010-01-02 I receive `0` before the market closes meaning that,, if I trust the signal, the close price of day d+1 will not increase. I should not buy the stock. 3. Backtest the signal created in Question 2. Here are some assumptions made to backtest this signal: - - When, at date d, the signal equals 1 we buy 1$ of stock just before the market closes and we sell the stock just before the market closes the next day. - When, at date d, the signal equals 0, we do not buy anything. - The profit is not reinvested, when invested, the amount is always 1$. @@ -184,7 +183,7 @@ We will backtest a **long only** strategy on Apple Inc. Long only means that we - [Resource 3](https://www.learndatasci.com/tutorials/python-pandas-tutorial-complete-introduction-for-beginners/) -- [Resource 4](https://towardsdatascience.com/different-ways-to-iterate-over-rows-in-a-pandas-dataframe-performance-comparison-dc0d5dcef8fe) +- [Resource 4](https://medium.com/data-science/different-ways-to-iterate-over-rows-in-a-pandas-dataframe-performance-comparison-dc0d5dcef8fe) - [Resource 5](https://www.investopedia.com/terms/b/backtesting.asp) diff --git a/subjects/ai/vision-track/README.md b/subjects/ai/vision-track/README.md index 3488b8a990..0470829e1c 100644 --- a/subjects/ai/vision-track/README.md +++ b/subjects/ai/vision-track/README.md @@ -19,7 +19,6 @@ The primary goal of **VisionTrack** is to develop practical skills in building a #### Data Loading and Preprocessing 1. **Video/Image Dataset Preparation**: - - Select or capture video streams or images featuring people. - Preprocess the data (e.g., resizing, normalization) to ensure it is ready for model input. @@ -30,7 +29,6 @@ The primary goal of **VisionTrack** is to develop practical skills in building a #### Model Implementation 1. **Person Detection with YOLO**: - - Use a **pre-trained YOLO model** (e.g., YOLOv5 or YOLOv8) tailored for person detection. - Fine-tune the model using **transfer learning** to adapt to specific dataset variations with **PyTorch** or **TensorFlow/Keras**. @@ -41,7 +39,6 @@ The primary goal of **VisionTrack** is to develop practical skills in building a #### Multi-Stream Object Tracking and Counting 1. **Multi-Stream Tracking Pipeline**: - - Extend the **supervision** library integration to support multiple video streams, enabling simultaneous tracking and analysis. - Develop logic to ensure accurate tracking and distinct object IDs for each stream. @@ -52,7 +49,6 @@ The primary goal of **VisionTrack** is to develop practical skills in building a #### Streamlit App Development 1. **App Layout**: - - Create a **Streamlit** app (`app.py`) to display real-time video feeds with overlaid detection, tracking, and counting for multiple streams. - Design an intuitive interface that allows users to: - Upload or connect multiple video feeds. @@ -60,7 +56,6 @@ The primary goal of **VisionTrack** is to develop practical skills in building a - View detection, tracking, and counting results with overlaid bounding boxes and counts. 2. **Interactive Controls**: - - Include controls for configuring detection thresholds and switching between video streams. - Allow toggling of detection, tracking, and counting features for each stream independently. @@ -71,11 +66,9 @@ The primary goal of **VisionTrack** is to develop practical skills in building a #### Performance Optimization 1. **Hardware Utilization**: - - Implement **GPU acceleration** using **CUDA** with **OpenCV** and **PyTorch** to support real-time multi-stream processing. 2. **Model Optimization**: - - Apply **model pruning** and **quantization** techniques to enhance inference speed and reduce latency, essential for multi-stream performance. 3. **Streamlit App Efficiency**: @@ -84,7 +77,6 @@ The primary goal of **VisionTrack** is to develop practical skills in building a #### Visualization and Analysis 1. **Real-Time Results**: - - Display detection, tracking, and counting results across all active video streams with clear overlays. - Present real-time metrics such as FPS and latency for each stream within the app interface. @@ -118,31 +110,12 @@ vision-track/ └── requirements.txt # List of dependencies ``` -### Timeline (2-3 weeks) - -**Week 1**: - -- **Days 1-3**: Prepare datasets, conduct EDA, and set up the initial project structure. -- **Days 4-7**: Implement and test YOLO-based person detection with transfer learning. - -**Week 2**: - -- **Days 1-3**: Integrate the **supervision** library for multi-stream tracking and counting. -- **Days 4-7**: Develop and test the **Streamlit** app for real-time, multi-stream visualization. - -**Week 3**: - -- **Days 1-4**: Optimize app performance, ensure GPU utilization, and refine user interaction for multi-stream functionality. -- **Days 5-7**: Finalize documentation, complete README, and create comprehensive usage instructions. - ### Tips 1. **Pre-Trained Model Advantage**: - - Start with a pre-trained YOLO model to save time and ensure strong baseline performance for person detection. 2. **Optimize for Multi-Stream Processing**: - - Ensure the app handles multiple video feeds efficiently by testing on different video sources and resolutions. 3. **User Experience**: @@ -151,7 +124,7 @@ vision-track/ ### Resources - [YOLOv5 Documentation](https://github.com/ultralytics/yolov5) -- [Supervision Library Documentation](https://supervisionlib.docs) +- [Supervision Library Documentation](https://github.com/roboflow/supervision) - [Streamlit Documentation](https://docs.streamlit.io/) - [PyTorch Documentation](https://pytorch.org/docs/stable/index.html) - [OpenCV Documentation](https://docs.opencv.org/) diff --git a/subjects/ai/visualizations/README.md b/subjects/ai/visualizations/README.md index 0a4309c54e..ef67e863cf 100644 --- a/subjects/ai/visualizations/README.md +++ b/subjects/ai/visualizations/README.md @@ -198,7 +198,6 @@ The plot has to contain: - 6 subplots: 2 rows, 3 columns - Keep space between plots: `hspace=0.5` and `wspace=0.5` - Each plot contains - - Text (2,3,i) centered at 0.5, 0.5. _Hint_: check the parameter `ha` of `text` - a title: Title i @@ -273,7 +272,6 @@ The plot has to contain: - [Resource 1](https://matplotlib.org/3.3.3/tutorials/index.html) - [Resource 2](https://towardsdatascience.com/matplotlib-tutorial-learn-basics-of-pythons-powerful-plotting-library-b5d1b8f67596) - - [Resource 3](https://github.com/rougier/matplotlib-tutorial) - [Resource 4](https://jakevdp.github.io/PythonDataScienceHandbook/05.13-kernel-density-estimation.html) - [Resource 5](https://plotly.com/python/box-plots/) diff --git a/subjects/banner/README.md b/subjects/banner/README.md index b27a9bf002..765b6901e1 100644 --- a/subjects/banner/README.md +++ b/subjects/banner/README.md @@ -22,7 +22,7 @@ println!("short hand: {}, long hand: {}, description: {}", d.short_hand, d.long_ An associated **type** called `Callback` will also be provided. It should represent a function pointer which is going to be used in the structure and functions below. This function will represent the callback for the flag associated to it. -A second structure named `FlagsHandler` will be given which just has one element: `flags: HashMap<(String, String), Callback>`. You'll also need to implement the following associated **functions**: +A second structure named `FlagsHandler` will be given which just has one element: `flags: HashMap`. You'll also need to implement the following associated **functions**: - `add_flag`, which adds the flag and callback function to the HashMap. - `exec_func`, which executes the function using the flag provided and returns the result. The callback should be executed with the first two arguments of the supplied `argv` argument. Return either the successful result from the callback or the error stringified. diff --git a/subjects/blood_types/README.md b/subjects/blood_types/README.md index 92ef0116a4..0c8d1061e0 100644 --- a/subjects/blood_types/README.md +++ b/subjects/blood_types/README.md @@ -20,24 +20,25 @@ Take a look at the `BloodType` struct below. It contains two enums which enable To provide a simple way to create blood types, implement the trait `FromStr` for `BloodType`. This will allow us to use the `parse` method and `from_str`, so we can do: ```rust - let a_neg: BloodType = "A-".parse(); +let a_neg: BloodType = "A-".parse(); ``` Implement the following Traits: -- `std::cmp::Ord`: to make possible to sort a vector or array of `BloodType`. -- `std::Debug`: for `BloodType`, allowing us print a vector such as `[BloodType { antigen: A, rh_factor: Positive}, BloodType{ antigen: B, rh_factor: Negative}]` as `"[ A+, B-]"` when using format strings `{:?}`. +- `std::fmt::Debug`: for `BloodType`, allowing us to print a vector such as `[BloodType { antigen: A, rh_factor: Positive }, BloodType { antigen: B, rh_factor: Negative }]` as `"[A+, B-]"` when using format strings `{:?}`. Create three methods for BloodType: -- `can_receive_from`: which returns `true` if `self` can receive blood from `other` blood type. +- `can_receive_from`: which returns whether `self` can receive blood from `other` blood type. - `donors`: which returns all the blood types that can give blood to `self`. - `recipients`: which returns all the blood types that can receive blood from `self`. ### Expected Functions and Structures ```rust -#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)] +use std::{fmt, str::FromStr}; + +#[derive(PartialEq, Eq, Hash, Clone, Copy)] pub enum Antigen { A, AB, @@ -45,47 +46,44 @@ pub enum Antigen { O, } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +#[derive(PartialEq, Eq, Hash, Clone, Copy)] enum RhFactor { Positive, Negative, } -#[derive(PartialEq, Eq, PartialOrd)] +#[derive(PartialEq, Eq, Hash, Clone, Copy)] pub struct BloodType { pub antigen: Antigen, pub rh_factor: RhFactor, } -use std::cmp::{Ord, Ordering}; - -use std::str::FromStr; - -impl FromStr for Antigen { -} - -impl FromStr for RhFactor { -} - -impl Ord for BloodType { -} - impl FromStr for BloodType { -} + type Err = (); -use std::fmt::{self, Debug}; + fn from_str(s: &str) -> Result { + todo!() + } +} -impl Debug for BloodType { +impl fmt::Debug for BloodType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!() + } } impl BloodType { - pub fn can_receive_from(&self, other: &Self) -> bool { + pub fn can_receive_from(self, other: Self) -> bool { + todo!() } - pub fn donors(&self) -> Vec { + pub fn donors(self) -> Vec { + todo!() } - pub fn recipients(&self) -> Vec { + pub fn recipients(self) -> Vec { + todo!() + } } ``` @@ -97,14 +95,15 @@ Here is a program to test your function. use blood_types::*; fn main() { - let blood_type: BloodType = "O+".parse().unwrap(); + let blood_type = "O+".parse::().unwrap(); println!("recipients of O+ {:?}", blood_type.recipients()); println!("donors of O+ {:?}", blood_type.donors()); - let another_blood_type: BloodType = "A-".parse().unwrap(); + + let another_blood_type = "A-".parse::().unwrap(); println!( "donors of O+ can receive from {:?} {:?}", - &another_blood_type, - blood_type.can_receive_from(&another_blood_type) + another_blood_type, + blood_type.can_receive_from(another_blood_type) ); } ``` diff --git a/subjects/blood_types_s/README.md b/subjects/blood_types_s/README.md index 932e82e520..67e1e6bc26 100644 --- a/subjects/blood_types_s/README.md +++ b/subjects/blood_types_s/README.md @@ -24,35 +24,38 @@ Implement three methods for `BloodType`: ### Expected Functions and Structures ```rust -#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)] +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] pub enum Antigen { - A, - AB, - B, - O, + A, + AB, + B, + O, } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] pub enum RhFactor { - Positive, - Negative, + Positive, + Negative, } -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] pub struct BloodType { - pub antigen: Antigen, - pub rh_factor: RhFactor, + pub antigen: Antigen, + pub rh_factor: RhFactor, } impl BloodType { - pub fn can_receive_from(&self, other: &Self) -> bool { - } + pub fn can_receive_from(self, other: Self) -> bool { + todo!() + } - pub fn donors(&self) -> Vec { - } + pub fn donors(self) -> Vec { + todo!() + } - pub fn recipients(&self) -> Vec { - } + pub fn recipients(self) -> Vec { + todo!() + } } ``` @@ -61,24 +64,27 @@ impl BloodType { Here is a program to test your function. ```rust -use blood_types_s::{Antigen, BloodType, RhFactor}; +use blood_types_s::*; fn main() { - let blood_type = BloodType { - antigen: Antigen::O, - rh_factor: RhFactor::Positive, - }; - println!("recipients of O+ {:?}", blood_type.recipients()); - println!("donors of O+ {:?}", blood_type.donors()); - let another_blood_type = BloodType { - antigen: Antigen::O, - rh_factor: RhFactor::Positive, - }; - println!( - "donors of O+ can receive from {:?} {:?}", - &another_blood_type, - blood_type.can_receive_from(&another_blood_type) - ); + let blood_type = BloodType { + antigen: Antigen::O, + rh_factor: RhFactor::Positive, + }; + + println!("recipients of O+ {:?}", blood_type.recipients()); + println!("donors of O+ {:?}", blood_type.donors()); + + let another_blood_type = BloodType { + antigen: Antigen::O, + rh_factor: RhFactor::Positive, + }; + + println!( + "donors of O+ can receive from {:?} {}", + another_blood_type, + blood_type.can_receive_from(another_blood_type) + ); } ``` @@ -86,8 +92,8 @@ And its output ```console $ cargo run -recipients of O+ [BloodType { antigen: AB, rh_factor: Positive }, BloodType { antigen: O, rh_factor: Positive }, BloodType { antigen: A, rh_factor: Positive }, BloodType { antigen: B, rh_factor: Positive }] -donors of O+ [BloodType { antigen: O, rh_factor: Positive }, BloodType { antigen: O, rh_factor: Negative }] -donors of O+ can receive from BloodType { antigen: O, rh_factor: Positive } true +recipients of O+ [BloodType { rh_factor: Positive, antigen: A }, BloodType { rh_factor: Positive, antigen: AB }, BloodType { rh_factor: Positive, antigen: B }, BloodType { rh_factor: Positive, antigen: O }] +donors of O+ [BloodType { rh_factor: Positive, antigen: O }, BloodType { rh_factor: Negative, antigen: O }] +donors of O+ can receive from BloodType { rh_factor: Positive, antigen: O } true $ ``` diff --git a/subjects/blood_types_s/main.rs b/subjects/blood_types_s/main.rs index 60fd9be35d..6aeb86f1c0 100644 --- a/subjects/blood_types_s/main.rs +++ b/subjects/blood_types_s/main.rs @@ -1,19 +1,22 @@ -use blood_types_s::{Antigen, BloodType, RhFactor}; +use blood_types_s::*; fn main() { let blood_type = BloodType { antigen: Antigen::O, rh_factor: RhFactor::Positive, }; + println!("recipients of O+ {:?}", blood_type.recipients()); println!("donors of O+ {:?}", blood_type.donors()); + let another_blood_type = BloodType { antigen: Antigen::O, rh_factor: RhFactor::Positive, }; + println!( - "donors of O+ can receive from {:?} {:?}", - &another_blood_type, - blood_type.can_receive_from(&another_blood_type) + "donors of O+ can receive from {:?} {}", + another_blood_type, + blood_type.can_receive_from(another_blood_type) ); } diff --git a/subjects/border_cross/README.md b/subjects/border_cross/README.md index eda6c4fdf8..46ba2ad765 100644 --- a/subjects/border_cross/README.md +++ b/subjects/border_cross/README.md @@ -4,42 +4,43 @@ At a border crossing, you want to keep a list of all the vehicles that are waiting to enter the country. You intend to keep a waiting list of the vehicles, but the vehicles can be one of two types: `Car` or `Truck`. -Create a function that receives a vector of structures that implements the `Vehicle` trait, and returns all the models. +Create a function that receives an array of references to structures that implements the `Vehicle` trait, and returns all the models in an array of same size. -With the following structure: +> Once again, ensure that all the function signatures and their respective generics and lifetimes are correct. ### Expected Functions and Structures ```rust -#[allow(dead_code)] pub struct Car<'a> { - pub plate_nbr: &'a str, - pub model: &'a str, - pub horse_power: u32, - pub year: u32, + pub plate_nbr: &'a str, + pub model: &'a str, + pub horse_power: u32, + pub year: u32, } -#[allow(dead_code)] pub struct Truck<'a> { - pub plate_nbr: &'a str, - pub model: &'a str, - pub horse_power: u32, - pub year: u32, - pub load_tons: u32, + pub plate_nbr: &'a str, + pub model: &'a str, + pub horse_power: u32, + pub year: u32, + pub load_tons: u32, } pub trait Vehicle { - fn model(&self) -> &str; - fn year(&self) -> u32; + fn model(&self) -> &str; + fn year(&self) -> u32; } impl Vehicle for Truck<'_> { + } impl Vehicle for Car<'_> { + } -fn all_models(list: Vec<&Vehicle>) -> Vec<&str> { +pub fn all_models(list: [_; N]) -> [&str; N] { + todo!() } ``` @@ -48,23 +49,27 @@ fn all_models(list: Vec<&Vehicle>) -> Vec<&str> { Here is a program to test your function. ```rust +use border_cross::*; + fn main() { - let vehicles: Vec = vec![ - &Car { - plate_nbr: "A3D5C7", - model: "Model 3", - horse_power: 325, - year: 2010, - }, - &Truck { - plate_nbr: "V3D5CT", - model: "Ranger", - horse_power: 325, - year: 2010, - load_tons: 40, - }, - ]; - println!("{:?}", all_models(vehicles)); + println!( + "{:?}", + all_models([ + &Car { + plate_nbr: "A3D5C7", + model: "Model 3", + horse_power: 325, + year: 2010, + }, + &Truck { + plate_nbr: "V3D5CT", + model: "Ranger", + horse_power: 325, + year: 2010, + load_tons: 40, + }, + ]) + ); } ``` diff --git a/subjects/box_recursion/README.md b/subjects/box_recursion/README.md index e5714caea2..41eb751b26 100644 --- a/subjects/box_recursion/README.md +++ b/subjects/box_recursion/README.md @@ -30,11 +30,11 @@ pub struct WorkEnvironment { pub grade: Link, } -pub type Link; +pub type Link = _; // Complete type alias #[derive(Debug)] pub struct Worker { - pub role: String, + pub role: Role, pub name: String, pub next: Link, } diff --git a/subjects/brackets_matching/README.md b/subjects/brackets_matching/README.md index 4a538ecc1f..36cf292907 100644 --- a/subjects/brackets_matching/README.md +++ b/subjects/brackets_matching/README.md @@ -2,9 +2,10 @@ ### Instructions -Create a **program** that takes an undefined number of command-line arguments. For each argument, if the expression is correctly bracketed, the program prints `OK` to the standard output followed by a newline (`'\n'`), otherwise it prints `Error` followed by a newline. +Create a **program** that takes an undefined number of command-line arguments. For each argument, if the expression is correctly bracketed, the program prints `OK` to the standard output, otherwise it prints `Error` followed by a newline. All characters are ignored except for the following brackets: + - parentheses `(` and `)`. - square brackets `[` and `]`. - curly braces `{` and `}`. @@ -19,7 +20,7 @@ You'll need to get the command line arguments somehow, and this will get you sta ```rust fn main() { - let args: Vec = std::env::args().collect(); + let args = std::env::args().collect::>(); //... } @@ -34,7 +35,6 @@ OK $ cargo run '([)]' | cat -e Error $ cargo run - $ cargo run '' '{[(0 + 0)(1 + 1)](3*(-1)){()}}' | cat -e OK OK diff --git a/subjects/brain_fuck/README.md b/subjects/brain_fuck/README.md index 874dc67734..cde7ac9acb 100644 --- a/subjects/brain_fuck/README.md +++ b/subjects/brain_fuck/README.md @@ -3,9 +3,9 @@ ### Instructions Write a `Brainfuck` interpreter program. -The source code will be given as first parameter. -The code will always be valid, with less than 4096 operations. -`Brainfuck` is a minimalist language. It consists of an array of bytes (in this exercise 2048 bytes) all initialized with zero, and with a pointer to its first byte. +The source code will be given as the first argument. +The code will always be valid. +`Brainfuck` is a minimalist language. It consists of an array of bytes (in this exercise as many as 2048 bytes) all initialized with zero, and with a pointer to its first byte. Every operator consists of a single character : @@ -19,16 +19,7 @@ Every operator consists of a single character : Any other character is a comment. -For receiving arguments from the command line you should use something like: - -```rust -fn main() { - let args: Vec = std::env::args().collect(); - - brain_fuck(&args[1]); -} - -``` +> Use `std::env::args()` to get the program's arguments. ### Usage diff --git a/subjects/car_rental/README.md b/subjects/car_rental/README.md index c11c3a09b5..5fdf3961ac 100644 --- a/subjects/car_rental/README.md +++ b/subjects/car_rental/README.md @@ -6,14 +6,12 @@ Create a struct named `Car` and another one named `RentalBusiness`. The scope of the exercise will be to modify and operate on the `Car` in the `RentalBusiness` even if this element is not declared as mutable, introducing the concept of interior mutability. -To accomplish that you will create some associated methods of `RentalBusiness` that will return the field `car` in many different ways. +To accomplish that, you will create some methods for `RentalBusiness` that will return the field `car` in many different ways. ### Expected Functions and Structures ```rust -use std::cell::Ref; -use std::cell::RefCell; -use std::cell::RefMut; +use std::cell::{Ref, RefCell, RefMut}; #[derive(Debug, Default, PartialEq, Eq)] pub struct Car { @@ -27,10 +25,21 @@ pub struct RentalBusiness { } impl RentalBusiness { - pub fn rent_car(&self) -> Ref {} - pub fn sell_car(&self) -> Car {} - pub fn repair_car(&self) -> RefMut {} - pub fn change_car(&self, new_car: Car) {} + pub fn rent_car(&self) -> Ref<'_, Car> { + todo!() + } + + pub fn sell_car(&self) -> Car { + todo!() + } + + pub fn repair_car(&self) -> RefMut<'_, Car> { + todo!() + } + + pub fn change_car(&self, new_car: Car) { + todo!() + } } ``` diff --git a/subjects/chaikin/README.md b/subjects/chaikin/README.md index 0b40748c56..1214242b99 100644 --- a/subjects/chaikin/README.md +++ b/subjects/chaikin/README.md @@ -2,7 +2,7 @@ ### Instructions -Implement [Chaikin's](http://graphics.cs.ucdavis.edu/education/CAGDNotes/Chaikins-Algorithm/Chaikins-Algorithm.html) algorithm as a step by step animation. +Implement [Chaikin's](https://www.cs.unc.edu/~dm/UNC/COMP258/LECTURES/Chaikins-Algorithm.pdf) algorithm as a step by step animation. You will create a canvas to enable the user to draw 1 or more points. The screen will then animate each step that is taken to obtain the final result of a drawn curve. The animation must play for 7 steps and then it must restart. @@ -13,14 +13,14 @@ You can see how the application should work [here](https://youtu.be/PbB2eKnA2QI) #### Functionality - The canvas must receive input from the mouse. The user must be able to use the left button to place control points for Chaikin's algorithm. - + - The selected points must be visible on the canvas. You will need to draw a **small** circle surrounding each point. - If the canvas has control points drawn on it, then pressing `Enter` should start the animation. It should cycle through the steps until reaching the 7th step of `Chaikin's` algorithm. The animation should then restart. - If the user presses `Enter` before any points have been drawn, then nothing should happen. It should still be possible to draw points. You may optionally choose to display a message to inform the user that they forgot to draw points. -- If the canvas only has only one control point, the program must only present that point and not cycle through the steps. +- If the canvas has only one control point, the program must only present that point and not cycle through the steps. - If the canvas has only two control points, the program must draw a straight line. diff --git a/subjects/check_user_name/README.md b/subjects/check_user_name/README.md index 85a5d4964d..a4c5d205c2 100644 --- a/subjects/check_user_name/README.md +++ b/subjects/check_user_name/README.md @@ -12,12 +12,14 @@ You will also have to create a `User` struct which has: - Fields: - `name`: `String` - - `acessLevel`: `enum` + - `access_level`: `AccessLevel` - Associated functions: - `new`: which initializes the struct. - - `send_name`: which takes only `self` as argument and returns an `Option<&str>` with `None` if the user is a `Guest` or the `name` if the `AccessLevel` has any of the other options. -- Other functions: - - `check_user_name`: which takes a `User`, calls `send_name` and returns a `tuple` with `true` and the user `name` if `send_name` returns the name or `false` and `"Error: User is guest"` if not. + - `send_name`: which takes `&self` and returns an `Option<&str>` with `None` if the user is a `Guest` or the `name` if the `AccessLevel` has any of the other options. + +Also implement a function `check_user_name` which takes a `User`, calls `send_name` and returns a `tuple` with `true` and the user `name` if `send_name` returns the name or `false` and `"ERROR: User is guest"` if not. + +> Remember to make your fields public! ### Expected Functions and Data Structures @@ -27,11 +29,18 @@ pub enum AccessLevel {} pub struct User {} impl User { - pub fn new(name: String, level: AccessLevel) -> User {} - pub fn send_name(&self) -> Option<&str> {} + pub fn new(name: String, level: AccessLevel) -> Self { + todo!() + } + + pub fn send_name(&self) -> Option<&str> { + todo!() + } } -pub fn check_user_name(user: &User) -> (bool, &str) {} +pub fn check_user_name(user: &User) -> (bool, &str) { + todo!() +} ``` ### Usage @@ -42,14 +51,14 @@ Here is a program to test your function: use check_user_name::*; fn main() { - let user0 = User::new("Didier".to_string(), AccessLevel::Admin); - println!("{:?}", check_user_name(&user0)); + let user0 = User::new("Didier".to_owned(), AccessLevel::Admin); + println!("{:?}", check_user_name(&user0)); - let user1 = User::new("Mary".to_string(), AccessLevel::Normal); - println!("{:?}", check_user_name(&user1)); + let user1 = User::new("Mary".to_owned(), AccessLevel::Normal); + println!("{:?}", check_user_name(&user1)); - let user2 = User::new("John".to_string(), AccessLevel::Guest); - println!("{:?}", check_user_name(&user2)); + let user2 = User::new("John".to_owned(), AccessLevel::Guest); + println!("{:?}", check_user_name(&user2)); } ``` diff --git a/subjects/check_user_name/main.rs b/subjects/check_user_name/main.rs index a6204cd973..e71674173f 100644 --- a/subjects/check_user_name/main.rs +++ b/subjects/check_user_name/main.rs @@ -1,12 +1,12 @@ use check_user_name::*; fn main() { - let user0 = User::new("Didier".to_string(), AccessLevel::Admin); + let user0 = User::new("Didier".to_owned(), AccessLevel::Admin); println!("{:?}", check_user_name(&user0)); - let user1 = User::new("Mary".to_string(), AccessLevel::Normal); + let user1 = User::new("Mary".to_owned(), AccessLevel::Normal); println!("{:?}", check_user_name(&user1)); - let user2 = User::new("John".to_string(), AccessLevel::Guest); + let user2 = User::new("John".to_owned(), AccessLevel::Guest); println!("{:?}", check_user_name(&user2)); } diff --git a/subjects/commits_stats/README.md b/subjects/commits_stats/README.md index 93210f860a..02331c2197 100644 --- a/subjects/commits_stats/README.md +++ b/subjects/commits_stats/README.md @@ -5,18 +5,23 @@ In this exercise, you will be provided with a json file `commits.json`([download](./attachments/commits.json)) with data corresponding to git commits in GitHub (extracted using the GitHub rest API). Your objective is to extract the relevant data and place it in a struct called `CommitData`. Create two functions: + - `commits_per_author`: which returns a hash map with the number of commits per author. The auditors will be identified by their GitHub login. - `commits_per_week`: which returns a hash map with the number of commits per week. > A week is represented by the year followed by the number of the week. For example, January 1, 2020 is in week 1 of 2020 and will be represented by a `String` with the form `"2020-W1"`. +Note: You must use the `json` crate `v0.12.4` for the functions' respective arguments. + ### Expected functions ```rust pub fn commits_per_week(data: &json::JsonValue) -> HashMap { + todo!() } pub fn commits_per_author(data: &json::JsonValue) -> HashMap { + todo!() } ``` @@ -28,7 +33,7 @@ Here is a possible test for your function: use commits_stats::{commits_per_week, commits_per_author}; fn main() { - let contents = fs::read_to_string("commits.json").unwrap(); + let contents = include_str!("commits.json"); let serialized = json::parse(&contents).unwrap(); println!("{:?}", commits_per_week(&serialized)); println!("{:?}", commits_per_author(&serialized)); @@ -46,5 +51,5 @@ $ ### Notions: -- [chrono](https://docs.rs/chrono/0.4.19/chrono) +- [chrono](https://docs.rs/chrono/0.4.41/chrono) - [json](https://docs.rs/json/0.12.4/json/index.html) diff --git a/subjects/count_factorial_steps/README.md b/subjects/count_factorial_steps/README.md index c1ba27c1be..e8cc2df68a 100644 --- a/subjects/count_factorial_steps/README.md +++ b/subjects/count_factorial_steps/README.md @@ -8,25 +8,30 @@ If the argument is not a factorial, or it is equal 0 or 1, then the function sho ```rust pub fn count_factorial_steps(factorial: u64) -> u64 { + todo!() } ``` As a reminder, the factorial of a number is the product of all the integers from 1 to that number. -Example: the factorial of 6 (written 6!) is 1 \* 2 \* 3 \* 4 \* 5 \* 6 = 720. +Example: the factorial of 6 (written 6!) is 1 \* 2 \* 3 \* 4 \* 5 \* 6 = 720. As such, the factorial steps of 720 are 6. ### Usage Here is a possible program to test your function: ```rust -use count_factorial_steps::count_factorial_steps; +use count_factorial_steps::*; fn main() { - println!("The factorial steps of 720 = {}", count_factorial_steps(720)); + println!( + "The factorial steps of 720 = {}", + count_factorial_steps(720) + ); println!("The factorial steps of 13 = {}", count_factorial_steps(13)); println!("The factorial steps of 6 = {}", count_factorial_steps(6)); } + ``` And its output: diff --git a/subjects/count_factorial_steps/main.rs b/subjects/count_factorial_steps/main.rs index 32d18fcd75..25bfa2b2c9 100644 --- a/subjects/count_factorial_steps/main.rs +++ b/subjects/count_factorial_steps/main.rs @@ -1,4 +1,4 @@ -use count_factorial_steps::count_factorial_steps; +use count_factorial_steps::*; fn main() { println!( diff --git a/subjects/counting_words/README.md b/subjects/counting_words/README.md index cf504660b8..f753f994e4 100644 --- a/subjects/counting_words/README.md +++ b/subjects/counting_words/README.md @@ -2,34 +2,35 @@ ### Instructions -Create a function named `counting_words`, that receives a `&str`. It should return each word and the number of times it appears on the string. +Create a function named `counting_words`, that receives a `&str`. It should return each word in the string and the number of times it appears on the string. -Each of the following will count as **1** word: +Each of the following will count as **one** single word: - A number like "0" or "1234". - A word or letter like "a" or "they". -- Two words joined by a single apostrophe like "it's" or "they're"). +- Two words joined by a single apostrophe like "it's" or "they're". The function must respect the following rules: - The count is case insensitive, so that "HELLO", "Hello", and "hello" are 3 uses of the same word. - All forms of punctuation are to be ignored, except for the apostrophe if used like the example above. -- The words can be separated by any form of whitespace (ie "\t", "\n", " "). +- The words can be separated by any form of ASCII whitespace (e.g. "\t", "\n", " "). +- On the resulting HashMap, every word occurrence should be in lowercase. ### Expected Function ```rust fn counting_words(words: &str) -> HashMap { + todo!() } ``` ### Usage -Here is a possible program to test your function : +Here is a possible program to test your function: ```rust -use counting_words::counting_words; -use std::collections::HashMap; +use counting_words::*; fn main() { println!("{:?}", counting_words("Hello, world!")); @@ -43,8 +44,8 @@ And its output: ```console $ cargo run -{"hello": 1, "world": 1} -{"and": 2, "human": 1, "universe": 2, "the": 2, "i\'m": 1, "about": 1, "einstein": 1, "are": 1, "infinite": 1, "sure": 1, "albert": 1, "two": 1, "things": 1, "not": 1, "stupidity": 1} -{"batman": 3, "stop": 2} +{"world": 1, "hello": 1} +{"are": 1, "about": 1, "stupidity": 1, "human": 1, "infinite": 1, "i'm": 1, "things": 1, "einstein": 1, "albert": 1, "sure": 1, "the": 2, "not": 1, "universe": 2, "and": 2, "two": 1} +{"stop": 2, "batman": 3} $ ``` diff --git a/subjects/counting_words/main.rs b/subjects/counting_words/main.rs index eced2a4c38..8893dbf5a4 100644 --- a/subjects/counting_words/main.rs +++ b/subjects/counting_words/main.rs @@ -1,5 +1,4 @@ -use counting_words::counting_words; -use std::collections::HashMap; +use counting_words::*; fn main() { println!("{:?}", counting_words("Hello, world!")); diff --git a/subjects/delete_prefix/README.md b/subjects/delete_prefix/README.md index 1878c0193d..9041a5b585 100644 --- a/subjects/delete_prefix/README.md +++ b/subjects/delete_prefix/README.md @@ -8,6 +8,7 @@ Define the function `delete_prefix` which returns the string slice `s` with the ```rust pub fn delete_prefix(prefix: &str, s: &str) -> Option<&str> { + todo!() } ``` @@ -16,11 +17,11 @@ pub fn delete_prefix(prefix: &str, s: &str) -> Option<&str> { Here is a program to test your function. ```rust -use delete_prefix::delete_prefix; +use delete_prefix::*; fn main() { - println!("{:?}", delete_prefix("ab", "abcdefghijklmnop")); - println!("{:?}", delete_prefix("x", "abcdefghijklmnop")); + println!("{:?}", delete_prefix("ab", "abcdefghijklmnop")); + println!("{:?}", delete_prefix("x", "abcdefghijklmnop")); } ``` diff --git a/subjects/display_table/README.md b/subjects/display_table/README.md index ec768a50f3..5fd48aab44 100644 --- a/subjects/display_table/README.md +++ b/subjects/display_table/README.md @@ -4,32 +4,35 @@ Define the `Table` struct below, and implement the associated functions `new` and `add_row`. You can see how they should work from the usage. -Implement the `std::fmt::Display` trait for the `Table` structure so that the table is printed like in the usage. The length of each column must adjust to the longest element of the column, and the element must be centered in the "cell" when possible. If the element cannot be centred exactly, it must be positioned slightly to the left. +Implement the `std::fmt::Display` trait for the `Table` structure so that the table is printed like in the usage. The length of each column must adjust to the longest element of the column, and the element must be centered in the "cell" when possible. If the element cannot be exactly centered, it must be offset one byte to the left of the center, as can be seen in the example output. If the table is empty `println!` must not print anything. +> Our tests will always assume that, when calling `add_row`, the row has the same correct size as the headers. + ### Expected functions and Structures ```rust #[derive(Clone, Debug, PartialEq)] pub struct Table { - pub headers: Vec, - pub body: Vec>, + pub headers: Vec, + pub body: Vec>, } impl fmt::Display for Table { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - + todo!() } } impl Table { - pub fn new() -> Table { - - } - pub fn add_row(&mut self, row: &[String]) { + pub fn new() -> Table { + todo!() + } - } + pub fn add_row(&mut self, row: &[String]) { + todo!() + } } ``` @@ -69,7 +72,6 @@ fn main() { ]); println!("{}", table); } - ``` And its output: diff --git a/subjects/division_and_remainder/README.md b/subjects/division_and_remainder/README.md index d74a7049ee..c801567bb3 100644 --- a/subjects/division_and_remainder/README.md +++ b/subjects/division_and_remainder/README.md @@ -37,8 +37,8 @@ $ ### Notions -- [The Tuple Type](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html?highlight=accessing%20a%20tuple#compound-types) +- [The Tuple Type](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html#the-tuple-type) - [Tuples](https://doc.rust-lang.org/rust-by-example/primitives/tuples.html) -- [Tuple Structs without Named Fields](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html?highlight=tuple#using-tuple-structs-without-named-fields-to-create-different-types) +- [Tuple Structs without Named Fields](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types) diff --git a/subjects/drawing/README.md b/subjects/drawing/README.md index 5d38af29fb..b8cf5e5e7b 100644 --- a/subjects/drawing/README.md +++ b/subjects/drawing/README.md @@ -30,11 +30,14 @@ In order to compile and run `main.rs`, you'll need to define some structures. Yo You'll also need to create the associated function `random` for `Line`, `Point` and `Circle`. You should derive their signatures from the usage. +Each shape must be drawn in a different color. + > Don't forget to add the dependencies in your Cargo.toml. ### Bonus You may optionally implement the following shapes, including the structures and traits needed to draw them: + - `Pentagon` - `Cube` @@ -54,13 +57,13 @@ fn main() { gs::Point::random(image.width, image.height).draw(&mut image); - let rectangle = gs::Rectangle::new(&gs::Point::new(150, 150), &gs::Point::new(50, 50)); + let rectangle = gs::Rectangle::new(&gs::Point::new(150, 300), &gs::Point::new(50, 60)); rectangle.draw(&mut image); - let triangle = gs::Triangle::new ( - &gs::Point::new(500, 500), - &gs::Point::new(250, 700), - &gs::Point::new(700, 800), + let triangle = gs::Triangle::new( + &gs::Point::new(500, 500), + &gs::Point::new(250, 700), + &gs::Point::new(700, 800), ); triangle.draw(&mut image); diff --git a/subjects/drawing/audit/README.md b/subjects/drawing/audit/README.md index f79bb178a6..d62b87a52a 100644 --- a/subjects/drawing/audit/README.md +++ b/subjects/drawing/audit/README.md @@ -10,7 +10,7 @@ ##### Open the module `geometrical_shapes`. -###### Can you confirm that the traits `Displayable` and `Drawable` where created? +###### Can you confirm that the traits `Displayable` and `Drawable` were created? ##### Try to open the `image.png`. diff --git a/subjects/dress_code/README.md b/subjects/dress_code/README.md index 520c55b08e..ff10256eec 100644 --- a/subjects/dress_code/README.md +++ b/subjects/dress_code/README.md @@ -5,7 +5,7 @@ Create a function called `choose_outfit` that receives the following input: - A `formality_level` as an `Option`. -- An `invitation_message` as a `Result<&str>`. +- An `invitation_message` as a `Result<&str, &str>`. The function will return a struct `Outfit` which contains: @@ -22,7 +22,7 @@ pub struct Outfit { For the `jacket`: -- The jacket should be `Flowers` when the `formality_level` is unset. +- The jacket should be `Flowers` when the `formality_level` is `None`. - The jacket should be `White` when the `formality_level` is more than 0. - Otherwise, it should be `Black`. @@ -31,15 +31,16 @@ For the `hat`: - If the `invitation_message` is `Ok()` it should be `Fedora`. - Otherwise, it should be `Snapback`. -In the specific case where `formality_level` is `None` and `invitation_message` -is not `Ok()` then the `jacket` should be `Flowers` and the `hat` should be `Baseball`. +In the specific case where `formality_level` is `None` and `invitation_message` is not `Ok()` then the `jacket` should be `Flowers` and the `hat` should be `Baseball`. Remember that all the `enum` and `struct` used must be `pub`. ### Expected functions ```rust -pub fn choose_outfit(formality_level: Option, invitation_message: Result<&str, &str>) -> Outfit {} +pub fn choose_outfit(formality_level: Option, invitation_message: Result<&str, &str>) -> Outfit { + todo!() +} ``` ### Usage @@ -50,7 +51,10 @@ Here is a program to test your function. use dress_code::*; fn main() { - println!("My outfit will be: {:?}", choose_outfit(Some(0), Ok("Dear friend, ..."))); + println!( + "My outfit will be: {:?}", + choose_outfit(Some(0), Ok("Dear friend, ...")) + ); } ``` diff --git a/subjects/drop_the_blog/README.md b/subjects/drop_the_blog/README.md index 900b4415d7..8d28ebd6a2 100644 --- a/subjects/drop_the_blog/README.md +++ b/subjects/drop_the_blog/README.md @@ -5,20 +5,17 @@ Define the following structures: - `Blog`: containing: - - `drops` that will save the number of dropped articles. - `states` that will save the state of multiple articles. If the article is not dropped, the state will be `false`, otherwise it will be `true`. - `Article`: containing: - - `id` as `usize`. - `body` as `String`. - - `parent` a link to the structure `Blog`. (Tip: this should be a reference). + - `parent` as a link to the structure `Blog`. (Tip: this should be a reference). You'll need to also add the following associated functions to the structures: - `Blog`: - - `new` that creates an empty blog. - `new_article` that receives a `String` for the body and returns a tuple with the `id` and a new `Article`. - `is_dropped` that receives an `id` and returns a `bool` that indicates the state of the article. @@ -26,39 +23,57 @@ You'll need to also add the following associated functions to the structures: - `add_drop` which is **called by the `Drop` trait**. It will receive an `id` that will be used to change the state of the article. If the state of that article is `true` then it will panic with the message `"X is already dropped"`, where `X` represents the `id`). Otherwise it should change the state to `true` and increment the `drops` field by 1. - `Article`: - - `new` that initializes a new article. - `discard` that drops the article. -> You must implement the `Drop` trait for the `Article` structure. In this trait you must call the function `add_drop` so that the state of the article changes. +> You must implement `Drop` for `Article`. In this trait you must call the function `add_drop` so that the state of the article changes. ### Expected Functions ```rust use std::cell::{RefCell, Cell}; -#[derive(Debug, Default, Clone, Eq, PartialEq)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct Blog { pub drops: Cell, pub states: RefCell> } impl Blog { - pub fn new() -> Blog {} - pub fn new_article(&self, body: String) -> (usize, Article) {} - pub fn new_id(&self) -> usize {} - pub fn is_dropped(&self, id: usize) -> bool {} - pub fn add_drop(&self, id: usize) {} + pub fn new() -> Self { + todo!() + } + + pub fn new_article(&self, body: String) -> (usize, Article<'_>) { + todo!() + } + + pub fn new_id(&self) -> usize { + todo!() + } + + pub fn is_dropped(&self, id: usize) -> bool { + todo!() + } + + pub fn add_drop(&self, id: usize) { + todo!() + } } #[derive(Debug, Clone, Eq, PartialEq)] pub struct Article<'a> { - // expected public fields + } impl<'a> Article<'a> { - pub fn new(id: usize, body: String, blog: &'a Blog) -> Article {} - pub fn discard(self) {} + pub fn new(id: usize, body: String, parent: &'a Blog) -> Self { + todo!() + } + + pub fn discard(self) { + todo!() + } } ``` @@ -88,8 +103,15 @@ fn main() { drop(article2_clone); - println!("{:?}", - (blog.is_dropped(id2), id2, &blog.drops, Rc::strong_count(&article2))); + println!( + "{:?}", + ( + blog.is_dropped(id2), + id2, + &blog.drops, + Rc::strong_count(&article2) + ) + ); } ``` diff --git a/subjects/easy_traits/README.md b/subjects/easy_traits/README.md index 544a313717..5275a9e2e9 100644 --- a/subjects/easy_traits/README.md +++ b/subjects/easy_traits/README.md @@ -2,32 +2,39 @@ ### Instructions -Your task is to implement the trait `AppendStr` for the type `StringValue`. +Your task is to implement the trait `AppendStrExt` for the type `String`. -The trait `AppendStr` has the following functions: +The trait `AppendStrExt` has the following functions: -- `append_str`: that appends the string to the `value`. -- `append_number`: that appends the number to the `value`. -- `remove_punctuation_marks`: that removes punctuation from the `value` (`.`, `,`, `?` and `!`). +- `append_str`: that appends `str_to_append` to `self` and returns it. +- `append_number`: that appends `nb_to_append` to `self` and returns it. +- `remove_punctuation_marks`: that removes all punctuation from `self`. +> **Note: For the sake of this exercise, we only consider `.`, `,`, `?` and `!` as punctuation.** ### Expected Function ```rust -#[derive(Clone)] -pub struct StringValue { - pub value: String, -} - -pub trait AppendStr { - fn append_str(&mut self, str_to_append: String) -> Self; +pub trait AppendStrExt { + fn append_str(&mut self, str_to_append: &str) -> &mut Self; - fn append_number(&mut self, nb_to_append: f64) -> Self; + fn append_number(&mut self, nb_to_append: f64) -> &mut Self; - fn remove_punctuation_marks(&mut self) -> Self; + fn remove_punctuation_marks(&mut self) -> &mut Self; } -impl AppendStr for StringValue { +impl AppendStrExt for String { + fn append_str(&mut self, str_to_append: &str) -> &mut Self { + todo!() + } + + fn append_number(&mut self, nb_to_append: f64) -> &mut Self { + todo!() + } + + fn remove_punctuation_marks(&mut self) -> &mut Self { + todo!() + } } ``` @@ -39,17 +46,15 @@ Here is a program to test your function. use easy_traits::*; fn main() { - let mut str_aux = StringValue { - value: String::from("hello"), - }; + let mut s = "hello".to_owned(); - println!("Before append: {}", str_aux.value); + println!("Before append: {}", s); - str_aux.append_str(String::from(" there!")); - println!("After append: {}", str_aux.value); + s.append_str(" there!"); + println!("After append: {}", s); - str_aux.remove_punctuation_marks(); - println!("After removing punctuation: {}", str_aux.value); + s.remove_punctuation_marks(); + println!("After removing punctuation: {}", s); } ``` diff --git a/subjects/events/README.md b/subjects/events/README.md index 1f8bba493b..855131fd0a 100644 --- a/subjects/events/README.md +++ b/subjects/events/README.md @@ -7,77 +7,75 @@ You have to design a notification system for a platform. Depending on the type of event, your event handler will control the size, color and position of the notification. Create a method named `notify` which returns a `Notification` with the following characteristics for each of: -- `Remainder(text)`: + +- `Remainder(&str)`: - `size`: `50` - `color`: `(50, 50, 50)` - `position`: `Bottom` - - `content`: the `text` associated to the enum variant -- `Registration(chrono::Duration)`: + - `content`: the `&str` associated to the enum variant +- `Registration(std::time::Duration)`: - `size`: `30` - `color`: `(255, 2, 22)` - `position`: `Top` - `content`: `"You have {duration} left before the registration ends"` -- `Appointment(text)`: +- `Appointment(&str)`: - `size`: `100` - `color`: `(200, 200, 3)` - `position`: `Center` - - `content`: `text associated to the value` + - `content`: the `&str` associated to the enum variant - `Holiday`: - `size`: `25` - `color`: `(0, 255, 0)` - `position`: `Top` - `content`: `"Enjoy your holiday"` -`duration` must be displayed in the form of `{hours}H:{minutes}M:{seconds}S`. The time will represent the remaining time before the event starts. For example, if there are 13 hours, 38 minutes and 14 seconds left, then the content will be `"You have 13H:38M:14S left before the registration ends"` - -Implement the `std::fmt::Display` trait so the text of the notifications are printed in the right color in the command line. +`duration` must be displayed in the form of `{hours}H:{minutes}M:{seconds}S`. The time will represent the remaining time before the event starts. For example, if there are 13 hours, 38 minutes and 14 seconds left, then the content will be `"You have 13H:38M:14S left before the registration ends"`. +Implement the `std::fmt::Display` trait for `Notification` so that notifications are printed in the correct color and formatted according to the examples given on the Usage section. ### Dependencies -chrono = "0.4" - -colored = "2.0.0" +colored = "3.0.0" ### Expected Functions and Data Structures ```rust -use chrono::Duration; use colored::*; +use std::{fmt, time::Duration}; -#[derive(Debug, Eq, PartialEq)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum Position { - Top, - Bottom, - Center, + Top, + Bottom, + Center, } -#[derive(Debug, Eq, PartialEq)] - pub struct Notification { - pub size: u32, - pub color: (u8, u8, u8), - pub position: Position, - pub content: String, +#[derive(Debug, PartialEq, Clone)] +pub struct Notification { + pub size: u32, + pub color: (u8, u8, u8), + pub position: Position, + pub content: String, } -#[derive(Debug)] +#[derive(Clone, Copy)] pub enum Event<'a> { - Remainder(&'a str), - Registration(Duration), - Appointment(&'a str), - Holiday, + Remainder(&'a str), + Registration(Duration), + Appointment(&'a str), + Holiday, } -use std::fmt; - impl fmt::Display for Notification { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!() + } } -use Event::*; - -impl Event { - pub fn notify(&self) -> Notification { - } +impl Event<'_> { + pub fn notify(self) -> Notification { + todo!() + } } ``` @@ -86,18 +84,17 @@ impl Event { Here is a program to test your function. ```rust -use events::Event::*; -use chrono::Duration; +use events::*; +use std::time::Duration; fn main() { - let remainder = Remainder("Go to the doctor"); - println!("{}", remainder.notify()); - let registration = Registration(Duration::seconds(49094)); - println!("{}", registration.notify()); - let appointment = Appointment("Go to the doctor"); - println!("{}", appointment.notify()); - let holiday = Holiday; - println!("{}", holiday.notify()); + println!("{}", Event::Remainder("Go to the doctor").notify()); + println!( + "{}", + Event::Registration(Duration::from_secs(49094)).notify() + ); + println!("{}", Event::Appointment("Go to the doctor").notify()); + println!("{}", Event::Holiday.notify()); } ``` @@ -105,14 +102,13 @@ And its output ```console $ cargo run -(Bottom, 50, Go to the doctor) -(Top, 30, You have 13H:38M:14S left before the registration ends) -(Center, 100, Go to the doctor) -(Top, 25, Enjoy your holiday) +(Bottom, 50, Go to the doctor) # the message on the last field of the tuple should be printed in a dark gray color (50, 50, 50) +(Top, 30, You have 13H:38M:14S left before the registration ends) # the message on the last field of the tuple should be printed in a red color (255, 2, 22) +(Center, 100, Go to the doctor) # the message on the last field of the tuple should be printed in a yellow color (200, 200, 3) +(Top, 25, Enjoy your holiday) # the message on the last field of the tuple should be printed in a green color (0, 255, 0) $ ``` ### Notions -- [colored crate](https://docs.rs/colored/2.0.0/colored/) -- [chrono crate](https://crates.io/crates/chrono) +- [colored crate](https://docs.rs/colored/3.0.0/colored/) diff --git a/subjects/filter_table/README.md b/subjects/filter_table/README.md index 3f6fe6ec66..b9bd7addd5 100644 --- a/subjects/filter_table/README.md +++ b/subjects/filter_table/README.md @@ -5,34 +5,34 @@ - Define the associated functions for the `Table` struct: - `new`: which creates a new empty table. - `add_rows`: which adds a new row to the table from a slice of strings. - - `filter_cols`: which receives a closure and returns a table with all the columns that yielded true when applying that closure. The closure will receive a `&str` and return a `bool` value. - - `filter_rows`: which receives a closure and returns a table with all the rows that yielded true when applied to the elements of the selected column. The closure will receive a `&str` and return a `bool` value. + - `filter_cols`: which receives a closure and returns a table with all the columns that yielded true when applying that closure. The closure will receive a `&str` and return a `bool` value. `T` is a placeholder for the type of the closure. Change it to the correct type. + - `filter_rows`: which receives a closure and returns a table with all the rows that yielded true when applied to the elements of the selected column. The closure will receive a `&str` and return a `bool` value. `T` is a placeholder for the type of the closure. Change it to the correct type. ### Expected functions and Structures ```rust #[derive(Clone, Debug, PartialEq)] pub struct Table { - pub headers: Vec, - pub body: Vec>, + pub headers: Vec, + pub body: Vec>, } impl Table { - pub fn new() -> Table { + pub fn new() -> Table { + todo!() + } - } + pub fn add_row(&mut self, row: &[String]) { + todo!() + } - pub fn add_row(&mut self, row: &[String]) { + pub fn filter_col(&self, filter: T) -> Option { + todo!() + } - } - - pub fn filter_col(&self, filter: T) -> Option { - - } - - pub fn filter_row(&self, col_name: &str, filter: T) -> Option { - - } + pub fn filter_row(&self, col_name: &str, filter: T) -> Option { + todo!() + } } ``` @@ -65,11 +65,12 @@ fn main() { "Philips".to_string(), "123456789".to_string(), ]); - let filter_names = |col: &str| col == "Name"; - println!("{:?}", table.filter_col(filter_names)); - let filter_philips = |lastname: &str| lastname == "Philips"; - println!("{:?}", table.filter_row("Last Name", filter_philips)); + println!("{:?}", table.filter_col(|col| col == "Name")); + println!( + "{:?}", + table.filter_row("Last Name", |lastname| lastname == "Philips") + ); } ``` diff --git a/subjects/filter_table/main.rs b/subjects/filter_table/main.rs index 05ea747845..0f28804780 100644 --- a/subjects/filter_table/main.rs +++ b/subjects/filter_table/main.rs @@ -22,9 +22,10 @@ fn main() { "Philips".to_string(), "123456789".to_string(), ]); - let filter_names = |col: &str| col == "Name"; - println!("{:?}", table.filter_col(filter_names)); - let filter_philips = |lastname: &str| lastname == "Philips"; - println!("{:?}", table.filter_row("Last Name", filter_philips)); + println!("{:?}", table.filter_col(|col| col == "Name")); + println!( + "{:?}", + table.filter_row("Last Name", |lastname| lastname == "Philips") + ); } diff --git a/subjects/flat_tree/README.md b/subjects/flat_tree/README.md index 0051e9ae9b..b61ae6470e 100644 --- a/subjects/flat_tree/README.md +++ b/subjects/flat_tree/README.md @@ -8,7 +8,7 @@ Create the `flatten_tree` **function** which receives a `std::collections::BTree ```rust pub fn flatten_tree>(tree: &BTreeSet) -> Vec { - + todo!() } ``` @@ -21,21 +21,12 @@ use flat_tree::*; use std::collections::BTreeSet; fn main() { - let mut tree = BTreeSet::new(); - tree.insert(34); - tree.insert(0); - tree.insert(9); - tree.insert(30); + let tree = BTreeSet::from([34, 0, 9, 30]); println!("{:?}", flatten_tree(&tree)); - let mut tree = BTreeSet::new(); - tree.insert("Slow"); - tree.insert("kill"); - tree.insert("will"); - tree.insert("Horses"); + let tree = BTreeSet::from(["Slow", "kill", "will", "Horses"]); println!("{:?}", flatten_tree(&tree)); } - ``` And its output: diff --git a/subjects/flat_tree/main.rs b/subjects/flat_tree/main.rs index f216ce9044..12604a0624 100644 --- a/subjects/flat_tree/main.rs +++ b/subjects/flat_tree/main.rs @@ -2,17 +2,9 @@ use flat_tree::*; use std::collections::BTreeSet; fn main() { - let mut tree = BTreeSet::new(); - tree.insert(34); - tree.insert(0); - tree.insert(9); - tree.insert(30); + let tree = BTreeSet::from([34, 0, 9, 30]); println!("{:?}", flatten_tree(&tree)); - let mut tree = BTreeSet::new(); - tree.insert("Slow"); - tree.insert("kill"); - tree.insert("will"); - tree.insert("Horses"); + let tree = BTreeSet::from(["Slow", "kill", "will", "Horses"]); println!("{:?}", flatten_tree(&tree)); } diff --git a/subjects/format_me/README.md b/subjects/format_me/README.md index 680695dc9b..c6d14c1807 100644 --- a/subjects/format_me/README.md +++ b/subjects/format_me/README.md @@ -7,31 +7,39 @@ In this exercise you will implement the trait `Display` for the structure `Park` Here are the public fields and possible variants for the two types: - `Park`: - - `name` as `String` + - `name` as `Option` - `park_type` as `ParkType` - - `address` as `String` - - `cap` as `String` - - `state` as `String` + - `address` as `Option` + - `cap` as `Option` + - `state` as `Option` - `ParkType`: - `Garden` - `Forest` - `Playground` +On implementing the `Display` trait for `Park`, you should display the park's fields using the following format: `{park_type} - {name}, {address}, {cap} - {state}`. If any of the fields `name`, `address`, `cap` or `state` are missing, display `No name`, `No address`, `No cap`, or `No state` respectively instead. + +On implementing the `Display` trait for `ParkType`, you should display the park type as a string, in all lowercase. + ### Expected Functions and Structures ```rust use std::fmt; pub struct Park {} - + pub enum ParkType {} impl fmt::Display for Park { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {} + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!() + } } impl fmt::Display for ParkType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {} + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!() + } } ``` @@ -46,21 +54,21 @@ fn main() { println!( "{}", Park { - name: "Les Tuileries".to_string(), + name: Some("Les Tuileries".to_owned()), park_type: ParkType::Garden, - address: "Pl. de la Concorde".to_string(), - cap: "75001".to_string(), - state: "France".to_string() + address: Some("Pl. de la Concorde".to_owned()), + cap: Some("75001".to_owned()), + state: Some("France".to_owned()) } ); println!( "{}", Park { - name: "".to_string(), + name: None, park_type: ParkType::Playground, - address: "".to_string(), - cap: "".to_string(), - state: "".to_string() + address: None, + cap: None, + state: None } ); } diff --git a/subjects/format_me/main.rs b/subjects/format_me/main.rs index 4890d7e506..72d65f7d99 100644 --- a/subjects/format_me/main.rs +++ b/subjects/format_me/main.rs @@ -4,21 +4,21 @@ fn main() { println!( "{}", Park { - name: "Les Tuileries".to_string(), + name: Some("Les Tuileries".to_owned()), park_type: ParkType::Garden, - address: "Pl. de la Concorde".to_string(), - cap: "75001".to_string(), - state: "France".to_string() + address: Some("Pl. de la Concorde".to_owned()), + cap: Some("75001".to_owned()), + state: Some("France".to_owned()) } ); println!( "{}", Park { - name: "".to_string(), + name: None, park_type: ParkType::Playground, - address: "".to_string(), - cap: "".to_string(), - state: "".to_string() + address: None, + cap: None, + state: None } ); } diff --git a/subjects/generics/README.md b/subjects/generics/README.md index c7d5f2033c..3a90ac6531 100644 --- a/subjects/generics/README.md +++ b/subjects/generics/README.md @@ -2,14 +2,13 @@ ### Instructions -Create a **function** named `identity` which calculates the identity of a value (receives any data type and returns the same value). - - +Create a **function** named `identity` which receives an argument of any type and returns it. ### Expected Function (signature to be completed) ```rust pub fn identity(v: _) -> _ { + todo!() } ``` diff --git a/subjects/generics_list/README.md b/subjects/generics_list/README.md index 5079e58a67..f8299c6345 100644 --- a/subjects/generics_list/README.md +++ b/subjects/generics_list/README.md @@ -1,8 +1,8 @@ -## generics_list +## generics_list ### Instructions -Create a linked list of generic values with the following methods. +Create a generic linked list with the following methods: - `new`: returns a new empty list. - `push`: adds an element to the beginning of the list. @@ -23,17 +23,21 @@ pub struct Node { pub next: Option>>, } -impl List { - pub fn new() -> List { +impl List { + pub fn new() -> Self { + todo!() } - pub fn push(&mut self, value: T) { + pub fn push(&mut self, value: _) { // fill in `value`'s type! + todo!() } pub fn pop(&mut self) { + todo!() } pub fn len(&self) -> usize { + todo!() } } ``` diff --git a/subjects/get_document_id/README.md b/subjects/get_document_id/README.md index 5484dc55b6..7785e46025 100644 --- a/subjects/get_document_id/README.md +++ b/subjects/get_document_id/README.md @@ -9,7 +9,7 @@ Create the following structures which will help you get the `document_id` of the - `OfficeThree`: `next_office` as type `Result`. - `OfficeFour`: `document_id` as type `Result`. -`ErrorOffice` is an `enum` with `OfficeClosed(u32)`, `OfficeNotFound(u32)` or `OfficeFull(u32)`. +`ErrorOffice` is an `enum` with `OfficeClose(u32)`, `OfficeNotFound(u32)` or `OfficeFull(u32)`. The `u32` is the `id` of the office generating the error. @@ -48,7 +48,9 @@ pub struct OfficeFour { } impl OfficeOne { - pub fn get_document_id(&self) -> Result {} + pub fn get_document_id(&self) -> Result { + todo!() + } } ``` @@ -69,6 +71,7 @@ fn main() { }), }), }; + let office_closed = { OfficeOne { next_office: Ok(OfficeTwo { @@ -81,6 +84,7 @@ fn main() { Ok(id) => println!("Found a document with id {}", id), Err(err) => println!("Error: {:?}", err), }; + match office_closed.get_document_id() { Ok(id) => println!("Found a document with id {}", id), Err(err) => println!("Error: {:?}", err), diff --git a/subjects/get_document_id/main.rs b/subjects/get_document_id/main.rs index 689833adf1..de9e6b6d4a 100644 --- a/subjects/get_document_id/main.rs +++ b/subjects/get_document_id/main.rs @@ -10,6 +10,7 @@ fn main() { }), }), }; + let office_closed = { OfficeOne { next_office: Ok(OfficeTwo { @@ -22,6 +23,7 @@ fn main() { Ok(id) => println!("Found a document with id {}", id), Err(err) => println!("Error: {:?}", err), }; + match office_closed.get_document_id() { Ok(id) => println!("Found a document with id {}", id), Err(err) => println!("Error: {:?}", err), diff --git a/subjects/insertion_sort/README.md b/subjects/insertion_sort/README.md index 4addc817e0..d581fa3f56 100644 --- a/subjects/insertion_sort/README.md +++ b/subjects/insertion_sort/README.md @@ -12,18 +12,19 @@ The insertion-sort algorithm sorts an array of size `n` in ascending order. 3. If `slice[key]` is smaller than `slice[key-1]`, then `slice[key]` is compared to `slice[key-2]` and so on. -4. All of the elements with values greater than `slice[key]` will need to be shifted over, to fit the value at `slice[key]` into its new position. +4. All of the elements with values greater than `slice[key]` are shifted right to fit `slice[key]` into its new position. A step-by-step example of insertion-sort: ![image.png](Insertion-Sort-demo.png) -**Figure 1** - Step by step execution of the algorithm insertion sort +**Figure 1** - Step-by-step execution of the algorithm insertion sort ### Expected Function ```rust pub fn insertion_sort(slice: &mut [i32], steps: usize) { + todo!() } ``` @@ -32,7 +33,7 @@ pub fn insertion_sort(slice: &mut [i32], steps: usize) { Here is a possible program to test your function, ```rust -use insertion_sort::insertion_sort; +use insertion_sort::*; fn main() { let mut target = [5, 3, 7, 2, 1, 6, 8, 4]; @@ -41,10 +42,9 @@ fn main() { println!("{:?}", target); let mut target = [5, 3, 7, 2, 1, 6, 8, 4]; - let len = target.len(); - // executes len - 1 iterations of the algorithm - // i.e. sorts the slice - insertion_sort(&mut target, len - 1); + // executes len - 1 iterations of the algorithm (sorts the slice) + let len = target.len() - 1; + insertion_sort(&mut target, len); println!("{:?}", target); } ``` diff --git a/subjects/insertion_sort/main.rs b/subjects/insertion_sort/main.rs index 2992ca9afd..cdd55c7d06 100644 --- a/subjects/insertion_sort/main.rs +++ b/subjects/insertion_sort/main.rs @@ -1,4 +1,4 @@ -use insertion_sort::insertion_sort; +use insertion_sort::*; fn main() { let mut target = [5, 3, 7, 2, 1, 6, 8, 4]; @@ -7,9 +7,8 @@ fn main() { println!("{:?}", target); let mut target = [5, 3, 7, 2, 1, 6, 8, 4]; - let len = target.len(); - // executes len - 1 iterations of the algorithm - // i.e. sorts the slice - insertion_sort(&mut target, len - 1); + // executes len - 1 iterations of the algorithm (sorts the slice) + let len = target.len() - 1; + insertion_sort(&mut target, len); println!("{:?}", target); } diff --git a/subjects/inv_pyramid/README.md b/subjects/inv_pyramid/README.md index 58f619a291..dc79a9ba01 100644 --- a/subjects/inv_pyramid/README.md +++ b/subjects/inv_pyramid/README.md @@ -2,12 +2,12 @@ ### Instructions -Create a function named `inv_pyramid` that takes a `string` as an `integer` and returns a vector of `string`s. -This function should create a pyramid structure. Each element of the vector must be a combination of spaces and the string given +Create a function named `inv_pyramid` that takes a string and an integer as input and returns a vector of strings. +This function should create a pyramid structure. Each element of the vector must be the given string after indentation represented as spaces. ### Example -i = 5 +For i = 5, ```console [ @@ -26,7 +26,9 @@ i = 5 ### Expected Functions ```rust -pub fn inv_pyramid(v: String, i: u32) -> Vec {} +pub fn inv_pyramid(v: String, i: usize) -> Vec { + todo!() +} ``` ### Usage @@ -37,23 +39,10 @@ Here is a program to test your function use inv_pyramid::*; fn main() { - let a = inv_pyramid(String::from("#"), 1); - let b = inv_pyramid(String::from("a"), 2); - let c = inv_pyramid(String::from(">"), 5); - let d = inv_pyramid(String::from("&"), 8); - - for v in a.iter() { - println!("{:?}", v); - } - for v in b.iter() { - println!("{:?}", v); - } - for v in c.iter() { - println!("{:?}", v); - } - for v in d.iter() { - println!("{:?}", v); - } + println!("{:#?}", inv_pyramid(String::from("#"), 1)); + println!("{:#?}", inv_pyramid(String::from("a"), 2)); + println!("{:#?}", inv_pyramid(String::from(">"), 5)); + println!("{:#?}", inv_pyramid(String::from("&"), 8)); } ``` @@ -61,33 +50,41 @@ And its output ```console $ cargo run -" #" -" a" -" aa" -" a" -" >" -" >>" -" >>>" -" >>>>" -" >>>>>" -" >>>>" -" >>>" -" >>" -" >" -" &" -" &&" -" &&&" -" &&&&" -" &&&&&" -" &&&&&&" -" &&&&&&&" -" &&&&&&&&" -" &&&&&&&" -" &&&&&&" -" &&&&&" -" &&&&" -" &&&" -" &&" -" &" +[ + " #", +] +[ + " a", + " aa", + " a", +] +[ + " >", + " >>", + " >>>", + " >>>>", + " >>>>>", + " >>>>", + " >>>", + " >>", + " >", +] +[ + " &", + " &&", + " &&&", + " &&&&", + " &&&&&", + " &&&&&&", + " &&&&&&&", + " &&&&&&&&", + " &&&&&&&", + " &&&&&&", + " &&&&&", + " &&&&", + " &&&", + " &&", + " &", +] $ ``` diff --git a/subjects/inv_pyramid/main.rs b/subjects/inv_pyramid/main.rs index 621cd7af6a..32a1c8979d 100644 --- a/subjects/inv_pyramid/main.rs +++ b/subjects/inv_pyramid/main.rs @@ -1,21 +1,8 @@ use inv_pyramid::*; fn main() { - let a = inv_pyramid(String::from("#"), 1); - let b = inv_pyramid(String::from("a"), 2); - let c = inv_pyramid(String::from(">"), 5); - let d = inv_pyramid(String::from("&"), 8); - - for v in a.iter() { - println!("{:?}", v); - } - for v in b.iter() { - println!("{:?}", v); - } - for v in c.iter() { - println!("{:?}", v); - } - for v in d.iter() { - println!("{:?}", v); - } + println!("{:#?}", inv_pyramid(String::from("#"), 1)); + println!("{:#?}", inv_pyramid(String::from("a"), 2)); + println!("{:#?}", inv_pyramid(String::from(">"), 5)); + println!("{:#?}", inv_pyramid(String::from("&"), 8)); } diff --git a/subjects/java/checkpoints/age-finder/README.md b/subjects/java/checkpoints/age-finder/README.md index 44284688db..876473e498 100644 --- a/subjects/java/checkpoints/age-finder/README.md +++ b/subjects/java/checkpoints/age-finder/README.md @@ -48,6 +48,8 @@ public class ExerciseRunner { ### Expected Output +> **Note:** The displayed ages depend on when the subject was created. Your solution should calculate and show the current age. + ```shell $ date Tue Jul 9 03:58:06 PM UTC 2024 diff --git a/subjects/java/checkpoints/breakdown-url/README.md b/subjects/java/checkpoints/breakdown-url/README.md index fb27aa47b4..4d4223770d 100644 --- a/subjects/java/checkpoints/breakdown-url/README.md +++ b/subjects/java/checkpoints/breakdown-url/README.md @@ -2,11 +2,15 @@ ### Instructions -Create a class `BreakdownURL` that provides a method to parse and validate URLs using regex.The method should extract and return the following URL components: `protocol`, `domain`, `port`, `path` and `query` -Assume the URL is always correct. -The method should extract and return URL components the parameters. The URL is always correct. +Create a class `BreakdownURL` with a method that uses a regular expression to parse a URL and return its components. -> Give back in the map just the existing component. +**Requirements** + +- Extract the following components when present: `protocol`, `domain`, `port`, `path`, `query`. +- Assume the input URL is valid (well-formed). +- Return only the components that actually exist in the given URL (omit absent ones). + +> πŸ’‘ Have you ever seen a URL without Path ??? ### Expected Class diff --git a/subjects/java/checkpoints/builder-blueprint/README.md b/subjects/java/checkpoints/builder-blueprint/README.md index 515b53b6d5..b462ad2c34 100644 --- a/subjects/java/checkpoints/builder-blueprint/README.md +++ b/subjects/java/checkpoints/builder-blueprint/README.md @@ -39,7 +39,6 @@ public ... RegexBuilder { // ConcreteRegexBuilder class public class ConcreteRegexBuilder { - private Regex regex = new Regex(); List component; ... diff --git a/subjects/java/checkpoints/circular-linked-list/LinkedList.java b/subjects/java/checkpoints/circular-linked-list/LinkedList.java deleted file mode 100644 index cb4c5885c9..0000000000 --- a/subjects/java/checkpoints/circular-linked-list/LinkedList.java +++ /dev/null @@ -1,6 +0,0 @@ -public interface LinkedList { - int at(int index); - void add(int value); - void remove(int index); - int size(); -} \ No newline at end of file diff --git a/subjects/java/checkpoints/config-protector/README.md b/subjects/java/checkpoints/config-protector/README.md index b51cd0dce5..b4e7b0c854 100644 --- a/subjects/java/checkpoints/config-protector/README.md +++ b/subjects/java/checkpoints/config-protector/README.md @@ -2,9 +2,11 @@ ### Instructions -Create a class `ConfigProtector` that provides a method to hide sensitive data in a configuration file using `Regex`. The method should replace sensitive values with asterisks. The configuration file will be provided as a `String`, and the keys for the sensitive data will be given in a `List`. +Create a class named `ConfigProtector` that provides functionality to mask sensitive data in a configuration file using regular expressions (`Regex`). This class should expose a method that replaces sensitive values with asterisks. -The config file format will always be as follows: +The configuration file will be supplied as a `String`, while the sensitive keys will be provided as a `List`. + +The format of the configuration file will always follow this structure: ``` username=admin diff --git a/subjects/java/checkpoints/date-formatter/README.md b/subjects/java/checkpoints/date-formatter/README.md index 01aaacad86..01f5aa728d 100644 --- a/subjects/java/checkpoints/date-formatter/README.md +++ b/subjects/java/checkpoints/date-formatter/README.md @@ -68,3 +68,22 @@ $ java -cp build ExerciseRunner 31 December 2022 $ ``` + +### Tip β€” How to Extract Day, Month, and Year from a Date + +```java +// Get the current time in seconds since the epoch (UTC) +long currentDateInSeconds = System.currentTimeMillis() / 1000L; + +// Create a Date from the UTC timestamp (convert seconds to milliseconds) +Date dateObj = new Date(currentDateInSeconds * 1000); + +// Create a Calendar in the UTC time zone and set the date +Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); +calendar.setTime(dateObj); + +// Extract the date components +int day = calendar.get(Calendar.DAY_OF_MONTH); +String month = getMonth(calendar.get(Calendar.MONTH)); +int year = calendar.get(Calendar.YEAR); +``` diff --git a/subjects/java/checkpoints/day-of-week/ExerciseRunner.java b/subjects/java/checkpoints/day-of-week/ExerciseRunner.java index cd50245c49..d79e083510 100644 --- a/subjects/java/checkpoints/day-of-week/ExerciseRunner.java +++ b/subjects/java/checkpoints/day-of-week/ExerciseRunner.java @@ -1,6 +1,6 @@ public class ExerciseRunner { public static void main(String[] args) { - DayOfWeekFinder finder = new DayOfWeek(); + DayOfWeekFinder finder = new DayOfWeekFinder(); // Test case 1 String startDate1 = "2023-06-22"; diff --git a/subjects/java/checkpoints/day-of-week/README.md b/subjects/java/checkpoints/day-of-week/README.md index 843ee81169..96d7bd5bef 100644 --- a/subjects/java/checkpoints/day-of-week/README.md +++ b/subjects/java/checkpoints/day-of-week/README.md @@ -2,7 +2,7 @@ ### Instructions -Create a class `DayOfWeekFinder` that provides a method to find the date of the next specified day of the week from a given date. The date will be provided in the format `yyyy-MM-dd`, and the day of the week will be provided as a string (e.g., "Monday", "Tuesday"). +Create a class `DayOfWeekFinder` that provides a method to find the date of the next specified day of the week from a given date. The date will be provided in the format `yyyy-MM-dd`, and the day of the week will be provided as a string ("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"). You should return 'Error' in case of any error. diff --git a/subjects/java/checkpoints/distinct-substring-length/README.md b/subjects/java/checkpoints/distinct-substring-length/README.md index 52726603e3..92d8c92881 100644 --- a/subjects/java/checkpoints/distinct-substring-length/README.md +++ b/subjects/java/checkpoints/distinct-substring-length/README.md @@ -2,9 +2,9 @@ ### Instructions -Create a class `DistinctSubstringLength` that provides a method to find the length of the longest substring without repeating characters in a given string. +Create a class named `DistinctSubstringLength` that provides a method to determine the length of the longest substring in a given string that contains no repeating characters. -The distinction between characters should be case-sensitive. +Character comparison must be case-sensitive. ### Expected Class diff --git a/subjects/java/checkpoints/double-linked-list/LinkedList.java b/subjects/java/checkpoints/double-linked-list/LinkedList.java deleted file mode 100644 index cb4c5885c9..0000000000 --- a/subjects/java/checkpoints/double-linked-list/LinkedList.java +++ /dev/null @@ -1,6 +0,0 @@ -public interface LinkedList { - int at(int index); - void add(int value); - void remove(int index); - int size(); -} \ No newline at end of file diff --git a/subjects/java/checkpoints/factory-blueprint/ExerciseRunner.java b/subjects/java/checkpoints/factory-blueprint/ExerciseRunner.java index 2457a2f4c0..f34f4d1304 100644 --- a/subjects/java/checkpoints/factory-blueprint/ExerciseRunner.java +++ b/subjects/java/checkpoints/factory-blueprint/ExerciseRunner.java @@ -9,7 +9,7 @@ public static void main(String[] args) { System.out.println("Invalid product type"); } - ConcreteProductA productB = factory.createProduct("B"); + ConcreteProductB productB = factory.createProduct("B"); if (productB != null) { productB.showDetails(); } else { @@ -18,7 +18,7 @@ public static void main(String[] args) { Object invalidProduct = factory.createProduct("C"); if (invalidProduct != null) { - invalidProduct.showDetails(); + System.out.println("Invalid product type should return null"); } else { System.out.println("Invalid product type"); } diff --git a/subjects/java/checkpoints/factory-blueprint/README.md b/subjects/java/checkpoints/factory-blueprint/README.md index 0f2a8ebf53..fbdd70e948 100644 --- a/subjects/java/checkpoints/factory-blueprint/README.md +++ b/subjects/java/checkpoints/factory-blueprint/README.md @@ -24,7 +24,7 @@ public class ConcreteProductB { // Factory class public class Factory { - public Product createProduct(String type) { + public ???? createProduct(String type) { } } @@ -46,7 +46,7 @@ public class ExerciseRunner { System.out.println("Invalid product type"); } - ConcreteProductA productB = factory.createProduct("B"); + ConcreteProductB productB = factory.createProduct("B"); if (productB != null) { productB.showDetails(); } else { @@ -55,7 +55,7 @@ public class ExerciseRunner { Object invalidProduct = factory.createProduct("C"); if (invalidProduct != null) { - invalidProduct.showDetails(); + System.out.println("Invalid product type should return null"); } else { System.out.println("Invalid product type"); } diff --git a/subjects/java/checkpoints/is-anagram/README.md b/subjects/java/checkpoints/is-anagram/README.md index 317b4f3890..77062d4065 100644 --- a/subjects/java/checkpoints/is-anagram/README.md +++ b/subjects/java/checkpoints/is-anagram/README.md @@ -1,4 +1,4 @@ -## Is Anagram +## Check Anagram ### Instructions diff --git a/subjects/java/checkpoints/monthly-period/ExerciseRunner.java b/subjects/java/checkpoints/monthly-period/ExerciseRunner.java index 4ee5dcf7e2..7f25828e6f 100644 --- a/subjects/java/checkpoints/monthly-period/ExerciseRunner.java +++ b/subjects/java/checkpoints/monthly-period/ExerciseRunner.java @@ -11,7 +11,7 @@ public static void main(String[] args) { System.out.println("Period: " + MonthlyPeriod.calculatePeriod(startDate2, endDate2)); String startDate3 = "2015-05-20"; - String endDate3 = "2015-10-19"; + String endDate3 = "2015-10-20"; System.out.println("Period: " + MonthlyPeriod.calculatePeriod(startDate3, endDate3)); String startDate4 = "2018-12-25"; diff --git a/subjects/java/checkpoints/monthly-period/README.md b/subjects/java/checkpoints/monthly-period/README.md index 0294bd5ca2..cdfde47ea1 100644 --- a/subjects/java/checkpoints/monthly-period/README.md +++ b/subjects/java/checkpoints/monthly-period/README.md @@ -40,7 +40,7 @@ public class ExerciseRunner { System.out.println("Period: " + MonthlyPeriod.calculatePeriod(startDate2, endDate2)); String startDate3 = "2015-05-20"; - String endDate3 = "2015-10-19"; + String endDate3 = "2015-10-20"; System.out.println("Period: " + MonthlyPeriod.calculatePeriod(startDate3, endDate3)); String startDate4 = "2018-12-25"; diff --git a/subjects/java/checkpoints/single-linked-list/LinkedList.java b/subjects/java/checkpoints/single-linked-list/LinkedList.java deleted file mode 100644 index cb4c5885c9..0000000000 --- a/subjects/java/checkpoints/single-linked-list/LinkedList.java +++ /dev/null @@ -1,6 +0,0 @@ -public interface LinkedList { - int at(int index); - void add(int value); - void remove(int index); - int size(); -} \ No newline at end of file diff --git a/subjects/java/checkpoints/singleton-blueprint/ExerciseRunner.java b/subjects/java/checkpoints/singleton-blueprint/ExerciseRunner.java index fe273d612c..f058cccfab 100644 --- a/subjects/java/checkpoints/singleton-blueprint/ExerciseRunner.java +++ b/subjects/java/checkpoints/singleton-blueprint/ExerciseRunner.java @@ -1,5 +1,5 @@ public class ExerciseRunner { public static void main(String[] args) { - System.out.println(Singleton.get???().ShowMessage()); + System.out.println(Singleton.get???().showMessage()); } } \ No newline at end of file diff --git a/subjects/java/checkpoints/singleton-blueprint/README.md b/subjects/java/checkpoints/singleton-blueprint/README.md index 8800e95eba..65493ad331 100644 --- a/subjects/java/checkpoints/singleton-blueprint/README.md +++ b/subjects/java/checkpoints/singleton-blueprint/README.md @@ -10,13 +10,13 @@ You are given an incomplete `Singleton` class. Complete the class to demonstrate public class Singleton { public Singleton instance; - private Singleton() { + ??? Singleton() { } - public Singleton get???() { + public ??? Singleton get???() { } - public String ShowMessage() { + public String showMessage() { return "Hello, I am a singleton!" } } @@ -29,7 +29,7 @@ Here is a possible `ExerciseRunner.java` to test your class: ```java public class ExerciseRunner { public static void main(String[] args) { - System.out.println(Singleton.get???().ShowMessage()); + System.out.println(Singleton.get???().showMessage()); } } ``` diff --git a/subjects/java/checkpoints/time-tracker/README.md b/subjects/java/checkpoints/time-tracker/README.md index 381afd0750..53bb1ce375 100644 --- a/subjects/java/checkpoints/time-tracker/README.md +++ b/subjects/java/checkpoints/time-tracker/README.md @@ -71,3 +71,16 @@ Full Day Project Total Logged Time: 24 h Error Project Total Logged Time: -1 $ ``` + +### Tip β€” How To Use SimpleDateFormat + +```java +// Creation of the date parser +SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + +// parse and get the date +Date date = DATE_FORMAT.parse(startTime); + +// getTime in milisecond +Long timeInMilisecond = date.getTime(); +``` diff --git a/subjects/java/checkpoints/top-frequents/ExerciseRunner.java b/subjects/java/checkpoints/top-frequents/ExerciseRunner.java index 2790d2eefa..682cb02779 100644 --- a/subjects/java/checkpoints/top-frequents/ExerciseRunner.java +++ b/subjects/java/checkpoints/top-frequents/ExerciseRunner.java @@ -13,7 +13,7 @@ public static void main(String[] args) { System.out.println("Top " + k2 + " frequent elements: " + topFrequents.findTopKFrequent(nums2, k2)); // Test case 3 - int[] nums3 = {4, 1, -1, 2, -1, 2, 3}; + int[] nums3 = {4, 1, -1, 2, -1, 2, 3, 3}; int k3 = 2; System.out.println("Top " + k3 + " frequent elements: " + topFrequents.findTopKFrequent(nums3, k3)); } diff --git a/subjects/java/checkpoints/top-frequents/README.md b/subjects/java/checkpoints/top-frequents/README.md index 51248b8e63..39952086a2 100644 --- a/subjects/java/checkpoints/top-frequents/README.md +++ b/subjects/java/checkpoints/top-frequents/README.md @@ -2,7 +2,9 @@ ### Instructions -Given a non-empty array of integers, return the k most frequent elements. Use a hash map and a heap for efficient lookup and retrieval. The returned array should be ordered by appearance frequency first, and if there is a tie in frequency, the element with the smallest index in the original array will appear first. +Given a non-empty array of integers, return the `k` most frequent elements. Use a hash map together with a heap to ensure efficient lookup and retrieval. + +The resulting array should be ordered primarily by frequency (most frequent first). In case of a frequency tie, the element that appears earliest in the original array should come first. ### Expected Class @@ -36,7 +38,7 @@ public class ExerciseRunner { System.out.println("Top " + k2 + " frequent elements: " + topFrequents.findTopKFrequent(nums2, k2)); // Test case 3 - int[] nums3 = {4, 1, -1, 2, -1, 2, 3}; + int[] nums3 = {4, 1, -1, 2, -1, 2, 3, 3}; int k3 = 2; System.out.println("Top " + k3 + " frequent elements: " + topFrequents.findTopKFrequent(nums3, k3)); diff --git a/subjects/lalgebra_scalar/README.md b/subjects/lalgebra_scalar/README.md index d717bbe4d4..e1672644a5 100644 --- a/subjects/lalgebra_scalar/README.md +++ b/subjects/lalgebra_scalar/README.md @@ -15,6 +15,7 @@ After finishing completing the declaration of the trait, implement the `Scalar` ```rust pub trait Scalar: _ { type Item; + fn zero() -> Self::Item; fn one() -> Self::Item; } @@ -49,4 +50,4 @@ $ ### Notions - [Module std::ops](https://doc.rust-lang.org/std/ops/index.html) -[Module std::marker::Sized](https://doc.rust-lang.org/std/marker/trait.Sized.html) + [Module std::marker::Sized](https://doc.rust-lang.org/std/marker/trait.Sized.html) diff --git a/subjects/lalgebra_vector/README.md b/subjects/lalgebra_vector/README.md index 52ac6809ec..19804e513a 100644 --- a/subjects/lalgebra_vector/README.md +++ b/subjects/lalgebra_vector/README.md @@ -6,23 +6,22 @@ A vector in linear algebra is defined as "anything that can be added, and that c Define the associated function `dot`, that calculates the dot product between two vectors. If the vectors are of different lengths, return `None`. -Note: `Vector` must implement `Debug`, `Clone`, `Eq` and `PartialEq`. +Note: `Vector` must implement at least `Debug` and `PartialEq`. ### Expected Functions and Structure ```rust -pub struct Vector(pub Vec); - use std::ops::Add; -impl Add for Vector { -} +#[derive(Debug, PartialEq)] +pub struct Vector(pub Vec); -impl Vector { - pub fn new() -> Self { - } +impl Add<_> for Vector<_> { +} - pub fn dot(&self, other: &Self) -> Option { +impl Vector<_> { + pub fn dot(self, rhs: Self) -> Option { + todo!() } } ``` @@ -35,10 +34,8 @@ Here is a program to test your function. use lalgebra_vector::*; fn main() { - let vector_1: Vector = Vector(vec![1, 3, -5]); - let vector_2: Vector = Vector(vec![4, -2, -1]); - println!("{:?}", vector_1.dot(&vector_2)); - println!("{:?}", vector_1 + vector_2); + println!("{:?}", Vector(vec![1, 3, -5]).dot(Vector(vec![4, -2, -1]))); + println!("{:?}", Vector(vec![1, 3, -5]) + Vector(vec![4, -2, -1])); } ``` diff --git a/subjects/lifetimes/README.md b/subjects/lifetimes/README.md index 161bda7161..e883b22cc8 100644 --- a/subjects/lifetimes/README.md +++ b/subjects/lifetimes/README.md @@ -7,15 +7,16 @@ Complete the `Person` struct with the fields and associated function described b ### Expected Functions and Data Structures (Both need to be completed) ```rust -#[derive(Debug)] -pub struct Person{ - pub name: &str, - pub age: u8, +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Person { + pub name: &str, + pub age: u32, } impl Person { - pub fn new(name: &str) -> Person { - } + pub fn new(name: &str) -> Self { + todo!() + } } ``` @@ -27,9 +28,9 @@ Here is a program to test your function. use lifetimes::*; fn main() { - let person = Person::new("Leo"); + let person = Person::new("Leo"); - println!("Person = {:?}", person); + println!("Person = {:?}", person); } ``` diff --git a/subjects/lucas_number/README.md b/subjects/lucas_number/README.md index 781b27ea6e..2eb8571841 100644 --- a/subjects/lucas_number/README.md +++ b/subjects/lucas_number/README.md @@ -5,7 +5,9 @@ Complete the body of the **function** `lucas_number`. ```rust -pub fn lucas_number(n: u32) -> u32 {} +pub fn lucas_number(n: u32) -> u32 { + todo!() +} ``` This function receives a number `n` and returns the `n`th number in the Lucas Numbers where the `n`th number is the sum of the previous two numbers in the series. @@ -17,13 +19,29 @@ The Lucas Numbers start like this: 2, 1, 3, 4, 7, 11, 18, 29, 47, 76, 123, etc.. Here is a possible test for your function: ```rust -use lucas_number::lucas_number; +use lucas_number::*; fn main() { - println!("The element in the position {} in Lucas Numbres is {}", 2, lucas_number(2)); - println!("The element in the position {} in Lucas Numbres is {}", 5, lucas_number(5)); - println!("The element in the position {} in Lucas Numbres is {}", 10, lucas_number(10)); - println!("The element in the position {} in Lucas Numbres is {}", 13, lucas_number(13)); + println!( + "The element in the position {} in Lucas Numbers is {}", + 2, + lucas_number(2) + ); + println!( + "The element in the position {} in Lucas Numbers is {}", + 5, + lucas_number(5) + ); + println!( + "The element in the position {} in Lucas Numbers is {}", + 10, + lucas_number(10) + ); + println!( + "The element in the position {} in Lucas Numbers is {}", + 13, + lucas_number(13) + ); } ``` diff --git a/subjects/lucas_number/main.rs b/subjects/lucas_number/main.rs index ecc5c0ff10..cd8f442e28 100644 --- a/subjects/lucas_number/main.rs +++ b/subjects/lucas_number/main.rs @@ -1,23 +1,23 @@ -use lucas_number::lucas_number; +use lucas_number::*; fn main() { println!( - "The element in the position {} in Lucas Numbres is {}", + "The element in the position {} in Lucas Numbers is {}", 2, lucas_number(2) ); println!( - "The element in the position {} in Lucas Numbres is {}", + "The element in the position {} in Lucas Numbers is {}", 5, lucas_number(5) ); println!( - "The element in the position {} in Lucas Numbres is {}", + "The element in the position {} in Lucas Numbers is {}", 10, lucas_number(10) ); println!( - "The element in the position {} in Lucas Numbres is {}", + "The element in the position {} in Lucas Numbers is {}", 13, lucas_number(13) ); diff --git a/subjects/lunch_queue/README.md b/subjects/lunch_queue/README.md index ed3bbd6057..347fbd206e 100644 --- a/subjects/lunch_queue/README.md +++ b/subjects/lunch_queue/README.md @@ -2,47 +2,54 @@ ### Instructions -You will need to create an _API_, so that a program can organize a queue of people. +You will need to create an API, so that a program can organize a queue of people. The program requires the following functions. Add them as associated functions to the `Queue` structure: - `new`: which will initialize the `Queue`. - `add`: which adds a person to the queue. - `invert_queue`: which reverses the queue. -- `rm`: which removes the person who finished ordering their food. The removal should respect the FIFO method (first in first out). It should return the person's details. -- `search`: which returns the details for a given person's `name`. +- `rm`: which removes the person who finished ordering their food. The removal should respect the FIFO method (first in first out). It should return the person's details (as `(name, discount)`). +- `search`: which returns the details for a given person's `name` (as `(name, discount)`). You must also create a type named `Link`. This will be the connection of the structures `Queue` and `Person`. This will be a recursion type, and must point to `None` if there is no `Person` to point to. ### Expected Function and Structures ```rust +#[derive(Debug, Clone)] pub struct Queue { pub node: Link, } pub type Link = +#[derive(Debug, Clone)] pub struct Person { - pub discount: i32, pub name: String, + pub discount: i32, + pub next_person: Link, } impl Queue { pub fn new() -> Queue { - + todo!() } - pub fn add(&mut self, name: String, discount: i32) { + pub fn add(&mut self, name: String, discount: i32) { + todo!() } - pub fn invert_queue(&mut self) { + pub fn invert_queue(&mut self) { + todo!() } - pub fn rm(&mut self) -> Option<(String, i32)> { + pub fn rm(&mut self) -> Option<(String, i32)> { + todo!() } - pub fn search(&self, name: &str) -> Option<(String, i32)> { + pub fn search(&self, name: &str) -> Option<(&String, &i32)> { + todo!() } } ``` diff --git a/subjects/macro_map/README.md b/subjects/macro_map/README.md index aa395f81e9..42fa581f6e 100644 --- a/subjects/macro_map/README.md +++ b/subjects/macro_map/README.md @@ -2,9 +2,11 @@ ### Instructions -Create a macro rule called `hash_map` to initialize and declare a `HashMap` at the same time, very similar to what `vec!` macro does for `Vector`. +Create a macro rule called `hash_map!` to initialize and optionally populate `std::collections::HashMap`, similarly to what `vec!` does for `Vec`. -> Your macro should accept both leading and non leading commas syntax to be more flexible in terms of coding style and reflect the language general style. +> Your macro should work with or without a leading comma as do the language's list standard macros work. + +> Your macro should also be able to work without the need to explicitly import `std::collections::HashMap` outside of its definition. ### Expected Macro @@ -22,19 +24,20 @@ use macro_map::hash_map; use std::collections::HashMap; fn main() { - let empty: HashMap = hash_map!(); - let new = hash_map!('a' => 22, 'b' => 1, 'c' => 10); - let nested = hash_map!( - "first" => hash_map!( - "Rob" => 32.2, - "Gen" => 44.1, - "Chris" => 10., - ), - "second" => hash_map!() - ); + let empty: HashMap = hash_map![]; println!("{:?}", empty); - println!("{:?}", new); - println!("{:?}", nested); + println!("{:?}", hash_map!['a' => 22, 'b' => 1, 'c' => 10]); + println!( + "{:?}", + hash_map![ + "first" => hash_map![ + "Rob" => 32.2, + "Gen" => 44.1, + "Chris" => 10., + ], + "second" => hash_map![] + ] + ); } ``` @@ -47,4 +50,3 @@ $ cargo run {"first": {"Rob": 32.2, "Gen": 44.1, "Chris": 10.0}, "second": {}} $ ``` - diff --git a/subjects/matrix/README.md b/subjects/matrix/README.md index afc8300667..23f18a2dcd 100644 --- a/subjects/matrix/README.md +++ b/subjects/matrix/README.md @@ -2,29 +2,33 @@ ### Instructions -Define a data structure to represent a matrix of any size and implement some basic operations. +Define a data structure to represent a matrix of any size **known at compile-time**. -We will consider a matrix as a rectangular arrangements of scalars. You can represent this as a 2 dimensional vector`. You will use the definition of scalars from the [lalgebra_scalar](../lalgebra_scalar/README.md) exercise. +We will consider a matrix as a rectangular arrangement of scalars. It can be represented as a 2 dimensional array. You will use the definition of `Scalar` from the [lalgebra-scalar](../lalgebra_scalar/README.md) exercise. Implement the following associated functions: -- `new`: which returns a matrix of size `1 x 1`. -- `identity`: which returns the identity matrix of size n. -- `zero`: which returns a matrix of size `row` x `col` with all the positions filled by zeros. - + +- `zero`: which returns a matrix of size `W` x `H` with all the positions filled by `T::zero()`. +- `identity`: which returns the identity matrix of size `S`. + +> Remember that arrays must have a size known at compile-time. The expected structure below gives some hints but you _will_ have to make some modifications to the types for the exercise to be correct. + ### Expected Functions and Structure ```rust -pub struct Matrix(pub Vec>); +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub struct Matrix(pub [[T; W]; H]); -impl > Matrix { - pub fn new() -> Matrix { - } - - pub fn zero(row: usize, col: usize) -> Matrix { - } +impl Matrix { + pub fn zero() -> Self { + todo!() + } +} - pub fn identity(n: usize) -> Matrix { - } +impl Matrix { + pub fn identity() -> Self { + todo!() + } } ``` @@ -36,10 +40,10 @@ Here is a program to test your function. use matrix::*; fn main() { - let m: Matrix = Matrix(vec![vec![0, 0, 0, 0], vec![0, 0, 0, 0], vec![0, 0, 0, 0]]); - println!("{:?}", m); - println!("{:?}", Matrix::::identity(4)); - println!("{:?}", Matrix::::zero(3, 4)); + let m = Matrix([[0; 4]; 3]); + println!("{:?}", m); + println!("{:?}", Matrix::<4, 4, u32>::identity()); + println!("{:?}", Matrix::<3, 4, f64>::zero()); } ``` @@ -49,10 +53,11 @@ And its output: $ cargo run Matrix([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]) Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) -Matrix([[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]) +Matrix([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]) $ ``` ### Notions - [Traits](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html) +- [Constant generics](https://rust-lang.github.io/rfcs/2000-const-generics.html) diff --git a/subjects/matrix_determinant/README.md b/subjects/matrix_determinant/README.md index 76b6806937..37b0a96f36 100644 --- a/subjects/matrix_determinant/README.md +++ b/subjects/matrix_determinant/README.md @@ -25,9 +25,9 @@ To calculate a 3x3 matrix determinant you have to take 'a' and multiply it by th ### Expected Function -```rs +```rust pub fn matrix_determinant(matrix: [[isize; 3]; 3]) -> isize { - + todo!() } ``` @@ -35,7 +35,7 @@ pub fn matrix_determinant(matrix: [[isize; 3]; 3]) -> isize { Here is a program to test your function: -```rs +```rust use matrix_determinant::*; fn main() { diff --git a/subjects/matrix_display/README.md b/subjects/matrix_display/README.md index a5757d46be..73944e52ad 100644 --- a/subjects/matrix_display/README.md +++ b/subjects/matrix_display/README.md @@ -11,24 +11,27 @@ You will also need to implement the `std::fmt::Display` trait, so that it prints ### Expected Functions and Struct ```rust +use std::fmt; + +#[derive(Debug, Clone)] pub struct Matrix(pub Vec>); impl Matrix { pub fn new(slice: &[&[i32]]) -> Self { - + todo!() } } -use std::fmt; - impl fmt::Display for Matrix { - + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!() + } } ``` ### Usage -Here is a possible program to test your function +Here is a possible program to test your function: ```rust use matrix_display::*; @@ -37,10 +40,9 @@ fn main() { let matrix = Matrix::new(&[&[1, 2, 3], &[4, 5, 6], &[7, 8, 9]]); println!("{}", matrix); } - ``` -And it's output: +And its output: ```console $ cargo run diff --git a/subjects/matrix_multiplication/README.md b/subjects/matrix_multiplication/README.md index 8f9f63cc3a..26e9487f7b 100644 --- a/subjects/matrix_multiplication/README.md +++ b/subjects/matrix_multiplication/README.md @@ -4,10 +4,11 @@ - Define a `struct` named `Matrix` as a tuple of two tuples. The nested tuple will contain two `i32`. -- Create a **function** named `multiply` that receives a `Matrix` and an `i32` and returns the `Matrix` with each number multiplied by the second argument. +- Create a **function** named `multiply` that receives a `Matrix` and an `i32` and returns the `Matrix` with each number multiplied by the second argument. ```rust pub fn multiply(m: Matrix, multiplier: i32) -> Matrix { + todo!() } ``` @@ -33,8 +34,8 @@ And its output: ```console $ cargo run -Original matrix Matrix ((1, 3), (4, 5)) -Matrix after multiply ((3, 9), (12, 15)) +Original matrix Matrix((1, 3), (4, 5)) +Matrix after multiply Matrix((3, 9), (12, 15)) $ ``` diff --git a/subjects/matrix_ops/README.md b/subjects/matrix_ops/README.md index dd1e6969c8..c598141510 100644 --- a/subjects/matrix_ops/README.md +++ b/subjects/matrix_ops/README.md @@ -2,20 +2,35 @@ ### Instructions -In this exercise, you will define some basic matrix operations, Implement traits for `Add` and `Sub` +In this exercise, you will implement some matrix operations: `Add`, `Sub` and `Mul`. -Remember that two matrices can only be added or subtracted if they have the same dimensions. Therefore, you must handle the possibility of failure by returning an `Option`. +You will be reusing your `Matrix` and `Scalar` structures defined in the [matrix](../matrix/README.md) and [lalgebra-scalar](../lalgebra_scalar/README.md) exercises. -You will be reusing your `Matrix` and `Scalar` structures defined in the [matrix](../matrix/README.md) and [lalgebra_scalar](../lalgebra_scalar/README.md) exercises. +Additionally, as it isn't possible to implement foreign traits on foreign types, we will write a `Wrapper` struct that will simply wrap our `Matrix` struct and implement these traits on `Wrapper` instead. -### Expected Function +> Remember that two matrices can only be added or subtracted if they have the same dimensions. Since we're dealing with arrays with sizes known at compile-time and compile-time generics, we don't need to check for dimensions at runtime. This is part of the magic of Rust's compile time generics! + +As with the previous exercise, make sure the generics have the correct constraints. + +### Expected Functions and Structure ```rust -impl Add for Matrix { +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub struct Wrapper(pub Matrix); + +impl From<[[T; W]; H]> for Wrapper { + +} + +impl Add for Wrapper { } -impl Sub for Matrix { +impl Sub for Wrapper { + +} + +impl Mul for Wrapper { } ``` @@ -25,25 +40,32 @@ impl Sub for Matrix { Here is a program to test your function ```rust -// Importing Matrix by defining it as a dependency in Cargo.toml use matrix_ops::*; fn main() { - let matrix = Matrix(vec![vec![8, 1], vec![9, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1], vec![1, 1]]); - println!("{:?}", matrix + matrix_2); + let matrix = Wrapper::from([[8, 1], [9, 1]]); + let matrix_2 = Wrapper::from([[1, 1], [1, 1]]); + println!("{:?}", matrix + matrix_2); + + let matrix = Wrapper::from([[1, 3], [2, 5]]); + let matrix_2 = Wrapper::from([[3, 1], [1, 1]]); + println!("{:?}", matrix - matrix_2); + + let matrix = Wrapper::from([[1, 2], [3, 4]]); + let matrix_2 = Wrapper::from([[2, 0], [1, 2]]); + println!("{:?}", matrix * matrix_2); - let matrix = Matrix(vec![vec![1, 3], vec![2, 5]]); - let matrix_2 = Matrix(vec![vec![3, 1], vec![1, 1]]); - println!("{:?}", matrix - matrix_2); + // The examples below should give a compile-time error. + // Because we have correct const generics and arrays with a fixed, known size + // we can't operate either with matrices of different sizes or with invalid matrices (for instance with rows of different sizes). - let matrix = Matrix(vec![vec![1, 1], vec![1, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - println!("{:?}", matrix - matrix_2); + // let matrix = Wrapper::from([[1, 1], [1, 1]]); + // let matrix_2 = Wrapper::from([[1, 1, 3], [1, 1]]); + // println!("{:?}", matrix - matrix_2); - let matrix = Matrix(vec![vec![1, 3], vec![9, 1]]); - let matrix_2 = Matrix(vec![vec![1, 1, 3], vec![1, 1]]); - println!("{:?}", matrix + matrix_2); + // let matrix = Wrapper::from([[1, 3], [9, 1]]); + // let matrix_2 = Wrapper::from([[1, 1, 3], [1, 1, 4]]); + // println!("{:?}", matrix + matrix_2); } ``` @@ -51,9 +73,8 @@ And its output ```console $ cargo run -Some(Matrix([[9, 2], [10, 2]])) -Some(Matrix([[-2, 2], [1, 4]])) -None -None +Wrapper(Matrix([[9, 2], [10, 2]])) +Wrapper(Matrix([[-2, 2], [1, 4]])) +Wrapper(Matrix([[4, 4], [10, 8]])) $ ``` diff --git a/subjects/modify_letter/README.md b/subjects/modify_letter/README.md index 6b4e506fbb..4fc5e3621b 100644 --- a/subjects/modify_letter/README.md +++ b/subjects/modify_letter/README.md @@ -8,16 +8,21 @@ Create a **function** `remove_letter_insensitive` that returns a string without Create a **function** `swap_letter_case` that returns a string swapping the case for the chosen letter. +> Our tests will only use ASCII characters. + ### Expected Functions ```rust pub fn remove_letter_sensitive(s: &str, letter: char) -> String { + todo!() } pub fn remove_letter_insensitive(s: &str, letter: char) -> String { + todo!() } pub fn swap_letter_case(s: &str, letter: char) -> String { + todo!() } ``` @@ -28,10 +33,12 @@ Here is a program to test your functions. ```rust use modify_letter::*; - fn main() { println!("{}", remove_letter_sensitive("Jojhn jis sljeepjjing", 'j')); - println!("{}", remove_letter_insensitive("JaimA ais swiaAmmingA", 'A')); + println!( + "{}", + remove_letter_insensitive("JaimA ais swiaAmmingA", 'A') + ); println!("{}", swap_letter_case("byE bye", 'e')); } ``` diff --git a/subjects/modify_letter/main.rs b/subjects/modify_letter/main.rs index aaaf128665..98aff8e04a 100644 --- a/subjects/modify_letter/main.rs +++ b/subjects/modify_letter/main.rs @@ -2,6 +2,9 @@ use modify_letter::*; fn main() { println!("{}", remove_letter_sensitive("Jojhn jis sljeepjjing", 'j')); - println!("{}", remove_letter_insensitive("JaimA ais swiaAmmingA", 'A')); + println!( + "{}", + remove_letter_insensitive("JaimA ais swiaAmmingA", 'A') + ); println!("{}", swap_letter_case("byE bye", 'e')); } diff --git a/subjects/moving_targets/README.md b/subjects/moving_targets/README.md index 92aad0c646..f92583cf5d 100644 --- a/subjects/moving_targets/README.md +++ b/subjects/moving_targets/README.md @@ -9,14 +9,20 @@ You will handle recursive types and ownership and implement the following **asso - `new`: which will initialize the `Field` with `head` set to `None`. - `push`: which receives a `Target` and add it as a `Node` at the head of the list. - `pop`: which returns the last added `Target` wrapped in an `Option` and removes it from the list. -- `peek`: which returns the last added `Target` as a reference wrapped in an `Option` but do not removes it from the list. -- `peek_mut`: which returns the last added `Target` as a mutable reference wrapped in an `Option` and also do not removes it from the list. +- `peek`: which returns the last added `Target` as a reference wrapped in an `Option` but does not remove it from the list. +- `peek_mut`: which returns the last added `Target` as a mutable reference wrapped in an `Option` and also does not remove it from the list. You must also implement a type named `Link`. This will be the connection between the `Field` and `Target` structures. This will be a recursion type, and it must point to `None` if there is no `Target` to point to. ### Expected Functions and structures ```rust +#[derive(Debug, PartialEq, Eq)] +pub struct Target { + pub size: u32, + pub xp: u32, +} + pub struct Field { head: Link, } @@ -28,17 +34,26 @@ struct Node { next: Link, } -#[derive(Debug, PartialEq, Eq)] -pub struct Target { - pub size: u32, - pub xp: u32, -} impl Field { - pub fn new() -> Self {} - pub fn push(&mut self, target: Target) {} - pub fn pop(&mut self) -> Option {} - pub fn peek(&self) -> Option<&Target> {} - pub fn peek_mut(&mut self) -> Option<&mut Target> {} + pub fn new() -> Self { + todo!() + } + + pub fn push(&mut self, target: Target) { + todo!() + } + + pub fn pop(&mut self) -> Option { + todo!() + } + + pub fn peek(&self) -> Option<&Target> { + todo!() + } + + pub fn peek_mut(&mut self) -> Option<&mut Target> { + todo!() + } } ``` diff --git a/subjects/negative_spelling/README.md b/subjects/negative_spelling/README.md index 2a5fc0af8e..48f52cf0f2 100644 --- a/subjects/negative_spelling/README.md +++ b/subjects/negative_spelling/README.md @@ -18,7 +18,7 @@ Here are some examples of what your function should return: ```rust pub fn negative_spell(n: i64) -> String { - + todo!() } ``` diff --git a/subjects/nextprime/README.md b/subjects/nextprime/README.md index d80c8bba1a..2df0068b0d 100644 --- a/subjects/nextprime/README.md +++ b/subjects/nextprime/README.md @@ -6,20 +6,19 @@ Create a **function** which returns the first prime number which is greater than The function must be optimized, so as to avoid time-outs. -> A prime number is a natural number greater than 1 that is a not a product of two smaller natural numbers. -> 4 is not a prime number (so it's called a composite number) because it can be represented as 2 \* 2. 5 is a prime number as it can only be represented by 5 \* 1 or 1 \* 5. +> We consider that only positive numbers can be prime numbers. ### Expected function ```rust -pub fn next_prime(nbr: u64) -> u64 { - +pub fn next_prime(nbr: usize) -> usize { + todo!() } ``` ### Usage -Here is a possible program to test your function : +Here is a possible program to test your function: ```rust use nextprime::*; @@ -28,7 +27,6 @@ fn main() { println!("The next prime after 4 is: {}", next_prime(4)); println!("The next prime after 11 is: {}", next_prime(11)); } - ``` And its output : diff --git a/subjects/office_worker/README.md b/subjects/office_worker/README.md index 461735e30e..5b62e18b11 100644 --- a/subjects/office_worker/README.md +++ b/subjects/office_worker/README.md @@ -2,7 +2,7 @@ ### Instructions -Create a structure `OfficeWorker` having the following public fields: +Create a structure `OfficeWorker` with the following public fields: - `name` as `String`. - `age` as `u32`. @@ -10,15 +10,15 @@ Create a structure `OfficeWorker` having the following public fields: Create an enum `WorkerRole` which can be `Admin`, `User` or `Guest`. -Implement for both the trait `From<&str>`. For `OfficeWorker` the string will have the format `"name,age,role"`, for `WorkerRole` the format of the string will be the `"role"` name in lower case. +Implement the trait `From<&str>` for both `OfficeWorker` and `WorkerRole`. +For `OfficeWorker` the string will have the format `{name},{age},{role}`. +For `WorkerRole` the format of the string will be `{role}` in lowercase. > Invalid inputs won't be tested. ### Expected Functions and Data Structures ```rust -use crate::OfficeWorker::*; - #[derive(Debug, PartialEq, Eq)] pub struct OfficeWorker { } @@ -28,9 +28,15 @@ pub enum WorkerRole { } impl From<&str> for OfficeWorker { + fn from(s: &str) -> Self { + todo!() + } } impl From<&str> for WorkerRole { + fn from(s: &str) -> Self { + todo!() + } } ``` @@ -42,10 +48,11 @@ Here is a program to test your function. use office_worker::*; fn main() { - println!("New worker: {:?}", - OfficeWorker::from("Manuel,23,admin")); - println!("New worker: {:?}", - OfficeWorker::from("Jean Jacques,44,guest")); + println!("New worker: {:?}", OfficeWorker::from("Manuel,23,admin")); + println!( + "New worker: {:?}", + OfficeWorker::from("Jean Jacques,44,guest") + ); } ``` diff --git a/subjects/order_books/README.md b/subjects/order_books/README.md index 720edba113..97131dbfaf 100644 --- a/subjects/order_books/README.md +++ b/subjects/order_books/README.md @@ -12,9 +12,9 @@ Build a module named `library` which contains two sub-modules: - `books`: which contains: - `Book`: a structure with: - `title`: `String` - - `year`: `u64` as its year of publication + - `year`: `u32` as its year of publication -A function `order_books` should be created (outside of the previous modules which receives a `Writer`, and orders the set of books alphabetically. +A function `order_books` should be created outside of the previous modules which receives a `Writer`, and orders the set of books alphabetically (case insensitive!). ### Expected Functions and Structs @@ -34,7 +34,7 @@ pub struct Book { ```rs pub fn order_books(writer: &mut Writer) { - + todo!() } ``` @@ -43,28 +43,30 @@ pub fn order_books(writer: &mut Writer) { Here is a program to test your function and structs: ```rs -pub use library::writers::Writer; -pub use library::books::Book; +pub use order_books::{ + library::{books::Book, writers::Writer}, + order_books, +}; fn main() { let mut writer_a = Writer { - first_name: "William".to_string(), - last_name: "Shakespeare".to_string(), + first_name: "William".to_owned(), + last_name: "Shakespeare".to_owned(), books: vec![ Book { - title: "Hamlet".to_string(), + title: "Hamlet".to_owned(), year: 1600, }, Book { - title: "Othelo".to_string(), + title: "Othelo".to_owned(), year: 1603, }, Book { - title: "Romeo and Juliet".to_string(), + title: "Romeo and Juliet".to_owned(), year: 1593, }, Book { - title: "MacBeth".to_string(), + title: "MacBeth".to_owned(), year: 1605, }, ], diff --git a/subjects/order_books/main.rs b/subjects/order_books/main.rs index bb5a02f831..ba4af1c9b3 100644 --- a/subjects/order_books/main.rs +++ b/subjects/order_books/main.rs @@ -1,25 +1,27 @@ -pub use library::books::Book; -pub use library::writers::Writer; +pub use order_books::{ + library::{books::Book, writers::Writer}, + order_books, +}; fn main() { let mut writer_a = Writer { - first_name: "William".to_string(), - last_name: "Shakespeare".to_string(), + first_name: "William".to_owned(), + last_name: "Shakespeare".to_owned(), books: vec![ Book { - title: "Hamlet".to_string(), + title: "Hamlet".to_owned(), year: 1600, }, Book { - title: "Othelo".to_string(), + title: "Othelo".to_owned(), year: 1603, }, Book { - title: "Romeo and Juliet".to_string(), + title: "Romeo and Juliet".to_owned(), year: 1593, }, Book { - title: "MacBeth".to_string(), + title: "MacBeth".to_owned(), year: 1605, }, ], diff --git a/subjects/organize_garage/README.md b/subjects/organize_garage/README.md index 1e159df733..f1bf5d0156 100644 --- a/subjects/organize_garage/README.md +++ b/subjects/organize_garage/README.md @@ -1,16 +1,18 @@ -## organize_garage +## organize_garage ### Instructions -Create a structure `Garage` with generic values. It will have the following public fields: +Create a structure `Garage` with generic values. It must derive at least `Debug`, `PartialEq`, and `Eq`, and will have the following public fields: + - `left` as `Option`. - `right` as `Option`. It will implement the following public methods: + - `move_to_right`: Moves the values from left to right. - `move_to_left`: Moves the values from right to left. -> The generic type will need to have `Add` and `Copy` traits implemented. It will also need to derive `Debug`. +> The generic type will need to have `Add` and `Copy` traits implemented. ### Usage diff --git a/subjects/own_and_return/README.md b/subjects/own_and_return/README.md index 1d06e69eb4..b9cc0be213 100644 --- a/subjects/own_and_return/README.md +++ b/subjects/own_and_return/README.md @@ -17,9 +17,11 @@ pub struct Film { } pub fn read_film_name(/* to be implemented */) -> String { + todo!() } pub fn take_film_name(/* to be implemented */) -> String { + todo!() } ``` @@ -32,16 +34,19 @@ Here is a possible program to test your function: use own_and_return::*; fn main() { - let my_film = Film { name: "Terminator".to_string() }; - println!("{}", take_film_name(/* to be implemented */)); - // the order of the print statements is intentional, if your implementation is correct, - // you should have a compile error because my_film was consumed + let my_film = Film { + name: "Terminator".to_owned(), + }; + + // println!("{}", take_film_name(/* to be implemented */)); + println!("{}", read_film_name(/* to be implemented */)); - println!("{}", take_film_name(/*to be implemented*/)) - // you can test this function by commenting out the first print statement, - // you should see the expected output without errors in this case -} + println!("{}", take_film_name(/* to be implemented */)); + // the order of the print statements is intentional. + // you can test this exercise properly by uncommenting out the first print statement, + // you should get a compilation error then if your implementation is correct. +} ``` And its output: diff --git a/subjects/own_and_return/main.rs b/subjects/own_and_return/main.rs index 144f124987..60b39463d3 100644 --- a/subjects/own_and_return/main.rs +++ b/subjects/own_and_return/main.rs @@ -2,13 +2,15 @@ use own_and_return::*; fn main() { let my_film = Film { - name: "Terminator".to_string(), + name: "Terminator".to_owned(), }; - println!("{}", take_film_name(/* to be implemented */)); - // the order of the print statements is intentional, if your implementation is correct, - // you should have a compile error because my_film was consumed + + // println!("{}", take_film_name(/* to be implemented */)); + println!("{}", read_film_name(/* to be implemented */)); - println!("{}", take_film_name(/*to be implemented*/)) - // you can test this function by commenting out the first print statement, - // you should see the expected output without errors in this case + println!("{}", take_film_name(/* to be implemented */)); + + // the order of the print statements is intentional. + // you can test this exercise properly by uncommenting out the first print statement, + // you should get a compilation error then if your implementation is correct. } diff --git a/subjects/partial_sums/README.md b/subjects/partial_sums/README.md index 33eb74e4c9..98a8b832cf 100644 --- a/subjects/partial_sums/README.md +++ b/subjects/partial_sums/README.md @@ -2,7 +2,7 @@ ### Instructions -Create a function named `parts_sums`, that receives a reference of an array of `u64`, and returns a vector with the partial sums of the received array. +Create a function named `parts_sums`, that receives a slice of `u64`, and returns a vector with the partial sums of the received array. This is how partial sums work: @@ -37,10 +37,11 @@ This is how partial sums work: parts_sums(&[1, 2, 3, 4, 5]) // == [15, 10, 6, 3 ,1, 0] ``` -### Expected Result +### Expected Functions ```rs -pub fn parts_sums(arr: &[u64]) -> Vec{ +pub fn parts_sums(arr: &[u64]) -> Vec { + todo!() } ``` @@ -53,7 +54,7 @@ use partial_sums::*; fn main() { println!( - "Partial sums of [5, 18, 3, 23] is : {:?}", + "Partial sums of [5, 18, 3, 23] is: {:?}", parts_sums(&[5, 18, 3, 23]) ); } @@ -63,6 +64,6 @@ And its output: ```sh $ cargo run -Partial sums of [5, 18, 3, 23] is : [49, 26, 23, 5, 0] +Partial sums of [5, 18, 3, 23] is: [49, 26, 23, 5, 0] $ ``` diff --git a/subjects/partial_sums/main.rs b/subjects/partial_sums/main.rs index 545488b4a3..d2a6835121 100644 --- a/subjects/partial_sums/main.rs +++ b/subjects/partial_sums/main.rs @@ -2,7 +2,7 @@ use partial_sums::*; fn main() { println!( - "Partial sums of [5, 18, 3, 23] is : {:?}", + "Partial sums of [5, 18, 3, 23] is: {:?}", parts_sums(&[5, 18, 3, 23]) ); } diff --git a/subjects/previousprime/main.rs b/subjects/previousprime/main.rs new file mode 100644 index 0000000000..8629b6fc6a --- /dev/null +++ b/subjects/previousprime/main.rs @@ -0,0 +1,5 @@ +use previousprime::*; + +fn main() { + println!("The previous prime number before 34 is: {}", prev_prime(34)); +} diff --git a/subjects/prime_checker/README.md b/subjects/prime_checker/README.md index 8a71fe9e40..d7f933cd2b 100644 --- a/subjects/prime_checker/README.md +++ b/subjects/prime_checker/README.md @@ -2,14 +2,11 @@ ### Instructions -Create a **function** `prime_checker` that takes an `u32` and check if it is a prime number. +Create a **function** `prime_checker` that takes an `usize` and check if it is a prime number. -The result will be `None` if the argument is less or equal one, otherwise it will return a `Result`. -If the `u32` is prime, the function will return an`Ok(u32)`. For any other case it will return an `enum` `PrimeErr`. -The `enum` `PrimeErr` will be `Even` if the number is a multiple of two or `Divider(u32)` where the `u32` is the smallest divider of the number. - -> A prime number is a natural number greater than 1 that is a not a product of two smaller natural numbers. -> 4 is not a prime number (so it's called a composite number) because it can be represented as 2 \* 2. 5 is a prime number as it can only be represented by 5 \* 1 or 1 \* 5. +The result will be `None` if the argument is less than or equal to one, otherwise it will return a `Result`. +If the `usize` is prime, the function will return an `Ok(usize)`. For any other case it will return an `Err(PrimeErr)`. +The `enum` `PrimeErr` will be `Even` if the number is a multiple of two, or `Divider(usize)` where the `usize` is the smallest divider of the number. > Your solution should be optimized to a certain degree. @@ -19,10 +16,12 @@ The `enum` `PrimeErr` will be `Even` if the number is a multiple of two or `Divi #[derive(PartialEq, Eq, Debug)] pub enum PrimeErr { Even, - Divider(u32), + Divider(usize), } -pub fn prime_checker(nb: u32) -> /* Implement return type here */ {} +pub fn prime_checker(nb: usize) -> /* Implement return type here */ { + todo!() +} ``` ### Usage diff --git a/subjects/printifnot/README.md b/subjects/printifnot/README.md index 7bb7ba6c55..62fb0befbb 100644 --- a/subjects/printifnot/README.md +++ b/subjects/printifnot/README.md @@ -2,9 +2,11 @@ ### Instructions -Write a function that takes a `string` as an argument and returns the letter `G` if the argument length is less than 3, otherwise returns `Invalid Input` followed by a newline `\n`. +Write a function that takes a string and returns: -- If it's an empty string return `G` followed by a newline `\n`. +- `"G\n"` if the string's length is less than 3 (including empty string). + +- `"Invalid Input\n"` otherwise. ### Expected function diff --git a/subjects/profanity_filter/README.md b/subjects/profanity_filter/README.md index 95e7559f91..dbca09a1a7 100644 --- a/subjects/profanity_filter/README.md +++ b/subjects/profanity_filter/README.md @@ -1,12 +1,12 @@ -## profanity filter +## profanity-filter ### Instructions Generally it is more desirable to catch the failure of some parts of a program instead of panicking. -For this exercise you will have to create a message blocker, where you must block the word `"stupid"`. +For this exercise you will have to create a message blocker. -You will need to create a **function** named `check_ms` which accepts a string and returns a `Result`. It should return an error with the message `"ERROR: illegal"` if the message is either empty or contains the word stupid. Otherwise, it should return the content of the message. +You will need to create a **function** named `check_ms` which accepts a string and returns a `Result`. It should return an error with the message `"ERROR: illegal"` if the message is either empty or contains the word `stupid`. Otherwise, it should return the content of the message. ##### Expected Function @@ -21,10 +21,12 @@ pub fn check_ms(message: &str) -> Result<&str, &str> { Here is a program to test your function ```rust +use profanity_filter::*; + fn main() { ["hello there", "", "you are stupid", "stupid"] .into_iter() - .for_each(|m| println!("{:?}", profanity_filter::check_ms(m))); + .for_each(|m| println!("{:?}", check_ms(m))); } ``` diff --git a/subjects/profanity_filter/main.rs b/subjects/profanity_filter/main.rs index 02607b9a35..bbe16b540e 100644 --- a/subjects/profanity_filter/main.rs +++ b/subjects/profanity_filter/main.rs @@ -1,15 +1,7 @@ use profanity_filter::*; fn main() { - let m0 = Message::new("hello there".to_string(), "toby".to_string()); - println!("{:?}", check_ms(&m0)); - - let m1 = Message::new("".to_string(), "toby".to_string()); - println!("{:?}", check_ms(&m1)); - - let m2 = Message::new("you are stupid".to_string(), "toby".to_string()); - println!("{:?}", check_ms(&m2)); - - let m3 = Message::new("stupid".to_string(), "toby".to_string()); - println!("{:?}", check_ms(&m3)); + ["hello there", "", "you are stupid", "stupid"] + .into_iter() + .for_each(|m| println!("{:?}", check_ms(m))); } diff --git a/subjects/queens/README.md b/subjects/queens/README.md index 3af78077d6..7db7593558 100644 --- a/subjects/queens/README.md +++ b/subjects/queens/README.md @@ -8,7 +8,7 @@ The purpose of this exercise is to find out if two queens can attack each other. The position of a chess piece on a chessboard will be represented by the struct `ChessPosition`. You must implement the associated function `new` which will return the position if it is valid, otherwise it will return `None`. -> Remember, chessboards have 8 files and 8 ranks (each from 0 to 7). +> Remember, chessboards have 8 files and 8 ranks (0 to 7). You will create the `Queen` struct with the associate function `can_attack`, which will return `true` if the queens can attack each other or not. You also need to implement the function `new` which creates a new `Queen` with a `ChessPosition`. @@ -30,37 +30,37 @@ _ _ _ _ _ _ _ _ ### Expected Function and Structures ```rust -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub struct ChessPosition { - pub rank: i32, - pub file: i32, -} - -#[derive(Debug)] -pub struct Queen { - pub position: ChessPosition, + pub rank: usize, + pub file: usize, } impl ChessPosition { - pub fn new(rank: i32, file: i32) -> Option { - + pub fn new(rank: usize, file: usize) -> Option { + todo!() } } +#[derive(Debug, Clone, Copy)] +pub struct Queen { + pub position: ChessPosition, +} + impl Queen { pub fn new(position: ChessPosition) -> Self { - + todo!() } - pub fn can_attack(&self, other: &Queen) -> bool { - + pub fn can_attack(self, other: Self) -> bool { + todo!() } } ``` ### Usage -Here is a possible program to test your function : +Here is a possible program to test your function: ```rust use queens::*; @@ -70,26 +70,25 @@ fn main() { let black_queen = Queen::new(ChessPosition::new(0, 4).unwrap()); println!( - "Is it possible for the queens to attack each other? => {}", - white_queen.can_attack(&black_queen) + "Is it possible for the queens to attack each other? {}", + white_queen.can_attack(black_queen) ); let white_queen = Queen::new(ChessPosition::new(1, 2).unwrap()); let black_queen = Queen::new(ChessPosition::new(0, 4).unwrap()); println!( - "Is it possible for the queens to attack each other? => {}", - white_queen.can_attack(&black_queen) + "Is it possible for the queens to attack each other? {}", + white_queen.can_attack(black_queen) ); } - ``` And its output: ```console $ cargo run -Is it possible for the queens to attack each other? => true -Is it possible for the queens to attack each other? => false +Is it possible for the queens to attack each other? true +Is it possible for the queens to attack each other? false $ ``` diff --git a/subjects/queens/main.rs b/subjects/queens/main.rs index 17acf05889..ea00527b86 100644 --- a/subjects/queens/main.rs +++ b/subjects/queens/main.rs @@ -5,15 +5,15 @@ fn main() { let black_queen = Queen::new(ChessPosition::new(0, 4).unwrap()); println!( - "Is it possible for the queens to attack each other? => {}", - white_queen.can_attack(&black_queen) + "Is it possible for the queens to attack each other? {}", + white_queen.can_attack(black_queen) ); let white_queen = Queen::new(ChessPosition::new(1, 2).unwrap()); let black_queen = Queen::new(ChessPosition::new(0, 4).unwrap()); println!( - "Is it possible for the queens to attack each other? => {}", - white_queen.can_attack(&black_queen) + "Is it possible for the queens to attack each other? {}", + white_queen.can_attack(black_queen) ); } diff --git a/subjects/reverse_it/README.md b/subjects/reverse_it/README.md index 4d59fed44f..4f4e203a29 100644 --- a/subjects/reverse_it/README.md +++ b/subjects/reverse_it/README.md @@ -8,15 +8,16 @@ Create a function named `reverse_it`, that takes a number. It should return a st ```rust pub fn reverse_it(v: i32) -> String { + todo!() } ``` ### Usage -Here is a program to test your function, +Here is a program to test your function: ```rust -use reverse_it::reverse_it; +use reverse_it::*; fn main() { println!("{}", reverse_it(123)); diff --git a/subjects/reverse_it/main.rs b/subjects/reverse_it/main.rs index e6af2f1ff3..75d0e6e26c 100644 --- a/subjects/reverse_it/main.rs +++ b/subjects/reverse_it/main.rs @@ -1,4 +1,4 @@ -use reverse_it::reverse_it; +use reverse_it::*; fn main() { println!("{}", reverse_it(123)); diff --git a/subjects/roman_numbers/README.md b/subjects/roman_numbers/README.md index f473efcbc2..4f9e6f1ddf 100644 --- a/subjects/roman_numbers/README.md +++ b/subjects/roman_numbers/README.md @@ -28,10 +28,10 @@ pub enum RomanDigit { #[derive(Clone, Debug, PartialEq, Eq)] pub struct RomanNumber(pub Vec); -impl From for RomanDigit { -} - impl From for RomanNumber { + fn from(value: u32) -> Self { + todo!() + } } ``` diff --git a/subjects/rot21/README.md b/subjects/rot21/README.md index e5620ef6c1..e99f419c57 100644 --- a/subjects/rot21/README.md +++ b/subjects/rot21/README.md @@ -6,13 +6,13 @@ The purpose of this exercise is to create a `rot21` function that works like the This function will receive a `string` and will rotate each letter of that `string` 21 times to the right. -The function should only rotate letters. Punctuation, symbols and numbers should remain the unchanged. +The function should only rotate **ASCII letters**. Everything should remain the unchanged. ### Expected functions ```rust pub fn rot21(input: &str) -> String { - + todo!() } ``` @@ -21,16 +21,15 @@ pub fn rot21(input: &str) -> String { Here is a program to test your function. ```rust -use rot21::rot21; +use rot21::*; fn main() { println!("The letter \"a\" becomes: {}", rot21("a")); println!("The letter \"m\" becomes: {}", rot21("m")); println!("The word \"MISS\" becomes: {}", rot21("MISS")); - println!("Your cypher wil be: {}", rot21("Testing numbers 1 2 3")); - println!("Your cypher wil be: {}", rot21("rot21 works!")); + println!("Your cypher will be: {}", rot21("Testing numbers 1 2 3")); + println!("Your cypher will be: {}", rot21("rot21 works!")); } - ``` And its output: @@ -40,7 +39,7 @@ $ cargo run The letter "a" becomes: v The letter "m" becomes: h The word "MISS" becomes: HDNN -Your cypher wil be: Oznodib iphwzmn 1 2 3 -Your cypher wil be: mjo21 rjmfn! +Your cypher will be: Oznodib iphwzmn 1 2 3 +Your cypher will be: mjo21 rjmfn! $ ``` diff --git a/subjects/rot21/main.rs b/subjects/rot21/main.rs index fc32129ac0..7308419aa1 100644 --- a/subjects/rot21/main.rs +++ b/subjects/rot21/main.rs @@ -4,6 +4,6 @@ fn main() { println!("The letter \"a\" becomes: {}", rot21("a")); println!("The letter \"m\" becomes: {}", rot21("m")); println!("The word \"MISS\" becomes: {}", rot21("MISS")); - println!("Your cypher wil be: {}", rot21("Testing numbers 1 2 3")); - println!("Your cypher wil be: {}", rot21("rot21 works!")); + println!("Your cypher will be: {}", rot21("Testing numbers 1 2 3")); + println!("Your cypher will be: {}", rot21("rot21 works!")); } diff --git a/subjects/rpn/README.md b/subjects/rpn/README.md index d73cade956..0f4f5bd7a2 100644 --- a/subjects/rpn/README.md +++ b/subjects/rpn/README.md @@ -2,14 +2,15 @@ ### Instructions -Write a **program** which takes a `string` containing an equation written in `Reverse Polish Notation` (RPN). It should evaluate the equation, and print the result on the standard output followed by a newline (`'\n'`). +Write a **program** which takes a `&str` containing an equation written in `Reverse Polish Notation` (RPN). It should evaluate the expression, and print the result on the standard output followed by a newline. -- If the `string` is not valid, or if there is not exactly one argument, `Error` must be printed on the standard output followed by a newline. -- If the `string` has extra spaces it is still considered valid. +- If the expression is not valid, or if there is not exactly one argument, `Error` must be printed on the standard output followed by a newline. + +> Extra spaces on the expression should be ignored. `Reverse Polish Notation` is a mathematical notation in which every operator follows all of its operands. In RPN, every operator encountered evaluates the previous 2 operands, and the result of this operation then becomes the first of the two operands for the subsequent operator. Operands and operators must be spaced by at least one space. -The following operators must be implemented : `+`, `-`, `*`, `/`, and `%`. +The following operators must be implemented : `+`, `-`, `*`, `/`, and `%` (modulo). All the given operands must fit in a `i64`. @@ -39,16 +40,7 @@ Or: 2 ``` -For receiving arguments from the command line you should use something like: - -```rust - fn main() { - let args: Vec = std::env::args().collect(); - - rpn(&args[1]); - } - -``` +> Use `std::env::args()` to get the program's arguments. ### Usage @@ -59,6 +51,10 @@ $ cargo run "1 2 3 4 +" Error $ cargo run "" Error +$ cargo run +Error +$ cargo run "2" "4" +Error $ cargo run " 1 3 * 2 -" 1 $ cargo run " 1 3 * ksd 2 -" diff --git a/subjects/scytale_decoder/README.md b/subjects/scytale_decoder/README.md index 3591fc7ca2..ae2771bbb6 100644 --- a/subjects/scytale_decoder/README.md +++ b/subjects/scytale_decoder/README.md @@ -1,18 +1,16 @@ -## scytale_cipher +## scytale_decoder ### Instructions -Create a **function** which decode a scytale cipher (also known as spartan cipher). +Create a **function** which **decodes** a scytale cipher (also known as spartan cipher). -In practice, it is represented by a strip wrapped around a cylinder. The message is written across the loops of the strip (not along the strip). The message becomes _coded_ if the radius of the cylinder changes, or the strip is removed from the cylinder. - -Your function will receive a `String` representing the ciphered message, and a `u32` representing the number of letters by turn of the strip around the cylinder. +Your function will receive a `String` representing the ciphered message, and a `usize` representing the number of letters per turn of the strip around the cylinder. > If the ciphered message is empty or the letters per turn are 0 the function will return `None`. ### Example -**letters_per_turn 2:** `"scytale Code"` -> `"sec yCtoadle"` +**letters_per_turn 2:** `"sec yCtoadle"` -> `"scytale Code"` ```console -------------------------------- @@ -21,7 +19,7 @@ Your function will receive a `String` representing the ciphered message, and a ` -------------------------------- ``` -**letters_per_turn 4:** `"scytale Code"` -> `"steoca dylCe"` +**letters_per_turn 4:** `"steoca dylCe"` -> `"scytale Code"` ```console ------------------------------------------ @@ -35,23 +33,28 @@ Your function will receive a `String` representing the ciphered message, and a ` ### Expected Functions ```rust -pub fn scytale_decoder(s: String, letters_per_turn: u32) -> Option { +pub fn scytale_decoder(s: String, letters_per_turn: usize) -> Option { + todo!() } ``` ### Usage -Here is a program to test your function +Here is a program to test your function: ```rust use scytale_decoder::*; fn main() { - println!("\"sec yCtoadle\" size=2 -> {:?}", - scytale_decoder("sec yCtoadle".to_string(), 2)); - - println!("\"steoca dylCe\" size=4 -> {:?}", - scytale_decoder("steoca dylCe".to_string(), 4)); + println!( + "\"sec yCtoadle\" size=2 -> {:?}", + scytale_decoder("sec yCtoadle".to_owned(), 2) + ); + + println!( + "\"steoca dylCe\" size=4 -> {:?}", + scytale_decoder("steoca dylCe".to_owned(), 4) + ); } ``` diff --git a/subjects/scytale_decoder/main.rs b/subjects/scytale_decoder/main.rs index 67461332b5..c1718aa7c6 100644 --- a/subjects/scytale_decoder/main.rs +++ b/subjects/scytale_decoder/main.rs @@ -3,11 +3,11 @@ use scytale_decoder::*; fn main() { println!( "\"sec yCtoadle\" size=2 -> {:?}", - scytale_decoder("sec yCtoadle".to_string(), 2) + scytale_decoder("sec yCtoadle".to_owned(), 2) ); println!( "\"steoca dylCe\" size=4 -> {:?}", - scytale_decoder("steoca dylCe".to_string(), 4) + scytale_decoder("steoca dylCe".to_owned(), 4) ); } diff --git a/subjects/smallest/README.md b/subjects/smallest/README.md index 504bfa9293..afb286eca9 100644 --- a/subjects/smallest/README.md +++ b/subjects/smallest/README.md @@ -10,6 +10,7 @@ If the `HashMap` is empty, return the maximum `i32`. ```rust pub fn smallest(h: HashMap<&str, i32>) -> i32 { + todo!() } ``` @@ -18,19 +19,23 @@ pub fn smallest(h: HashMap<&str, i32>) -> i32 { Here is a program to test your function. ```rust -use std::collections::HashMap; use smallest::smallest; +use std::collections::HashMap; fn main() { - - let mut hash = HashMap::new(); - hash.insert("Cat", 122); - hash.insert("Dog", 333); - hash.insert("Elephant", 334); - hash.insert("Gorilla", 14); - - println!("The smallest of the elements in the HashMap is {}", smallest(hash)); + let hash = HashMap::from([ + ("Cat", 122), + ("Dog", 333), + ("Elephant", 334), + ("Gorilla", 14), + ]); + + println!( + "The smallest of the elements in the HashMap is {}", + smallest(hash) + ); } + ``` And its output diff --git a/subjects/smallest/main.rs b/subjects/smallest/main.rs index 1f2f166df5..660648b103 100644 --- a/subjects/smallest/main.rs +++ b/subjects/smallest/main.rs @@ -2,11 +2,12 @@ use smallest::smallest; use std::collections::HashMap; fn main() { - let mut hash = HashMap::new(); - hash.insert("Cat", 122); - hash.insert("Dog", 333); - hash.insert("Elephant", 334); - hash.insert("Gorilla", 14); + let hash = HashMap::from([ + ("Cat", 122), + ("Dog", 333), + ("Elephant", 334), + ("Gorilla", 14), + ]); println!( "The smallest of the elements in the HashMap is {}", diff --git a/subjects/traits/README.md b/subjects/traits/README.md index 90c28d5292..b6f2c925a1 100644 --- a/subjects/traits/README.md +++ b/subjects/traits/README.md @@ -11,22 +11,24 @@ There are two types of food for now: Define the `Food` trait for `Fruit` and `Meat`. The required method `gives` returns the amount of strength that the food provides. -Implement the `std::fmt::Display` trait for the `Player` structure, so that when `{}` corresponds to a `Player` insider a `println!` macro, it will print 3 lines: +Implement the `std::fmt::Display` trait for the `Player` structure, so that when `Player` is printed, it will print information according to this example: -- First: the name of the player. -- Second: strength, score and the money. -- Third: The player's list of weapons. +- player_name +- Strength: 4, Score: 10, Money: 400 +- Weapons: ["toy knife", "tough glove"] ### Expected Functions and Structures ```rust +use std::fmt; + #[derive(Debug)] -pub struct Player { - pub name: String, +pub struct Player<'a> { + pub name: &'a str, pub strength: f64, - pub score: i32, - pub money: i32, - pub weapons: Vec, + pub score: u32, + pub money: u32, + pub weapons: Vec<&'a str>, } pub struct Fruit { @@ -38,20 +40,32 @@ pub struct Meat { pub fat_content: f64, } -impl Player { - fn eat(&mut self, food: T) { +impl Player<'_> { + pub fn eat(&mut self, food: impl Food) { self.strength += food.gives(); } } +impl fmt::Display for Player<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + todo!() + } +} + pub trait Food { fn gives(&self) -> f64; } impl Food for Fruit { + fn gives(&self) -> f64 { + todo!() + } } impl Food for Meat { + fn gives(&self) -> f64 { + todo!() + } } ``` @@ -74,15 +88,18 @@ fn main() { }; let mut player1 = Player { - name: String::from("player1"), + name: "player1", strength: 1.0, score: 0, money: 0, - weapons: vec![String::from("knife")], + weapons: vec!["knife"], }; + println!("Before eating {:?}", player1); + player1.eat(apple); println!("After eating an apple\n{}", player1); + player1.eat(steak); println!("After eating a steak\n{}", player1); } diff --git a/subjects/tuples_refs/README.md b/subjects/tuples_refs/README.md index 5a9881477d..4df42b6183 100644 --- a/subjects/tuples_refs/README.md +++ b/subjects/tuples_refs/README.md @@ -46,12 +46,12 @@ $ - [Defining a struct](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html) -- [The Tuple Type](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html?highlight=accessing%20a%20tuple#compound-types) +- [The Tuple Type](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html#the-tuple-type) - [Tuples](https://doc.rust-lang.org/rust-by-example/primitives/tuples.html) -- [Tuple Structs without Named Fields](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html?highlight=tuple#using-tuple-structs-without-named-fields-to-create-different-types) +- [Tuple Structs without Named Fields](https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types) -- [Adding Useful Functionality with Derived Traits](https://doc.rust-lang.org/stable/book/ch05-02-example-structs.html?highlight=debug%20deriv#adding-useful-functionality-with-derived-traits) +- [Adding Useful Functionality with Derived Traits](https://doc.rust-lang.org/stable/book/ch05-02-example-structs.html?#adding-useful-functionality-with-derived-traits) - [Chapter 7](https://doc.rust-lang.org/stable/book/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html) diff --git a/subjects/vector_operations/README.md b/subjects/vector_operations/README.md index 3e4c5a2164..d29314d6f1 100644 --- a/subjects/vector_operations/README.md +++ b/subjects/vector_operations/README.md @@ -6,11 +6,13 @@ Define the structure `ThreeDVector`, that represents a 3 dimensional vector. In physics, these vectors are represented as `ai`, `bj` and `ck`. `a`, `b` and `c` are real numbers. `i`, `j` and `k` represent the direction in the Cartesian plane, along the axises `x`, `y` and `z` respectively. Therefore, we use the fields `i`, `j` and `k` in the structure. -Take a look how the operations `Addition` and `Subtraction` work for a 3 dimensional vector, and implement them by creating the `std::ops::Add` and `std::ops::Sub` traits. +Take a look how the operations `Addition` and `Subtraction` work for a 3 dimensional vector, and implement them by using the `std::ops::Add` and `std::ops::Sub` traits. ### Expected Functions and Structures ```rust +use std::ops::{Add, Sub}; + #[derive(Debug, Copy, Clone, PartialEq)] pub struct ThreeDVector { pub i: T, @@ -18,12 +20,10 @@ pub struct ThreeDVector { pub k: T, } -use std::ops::{Add, Sub}; - -impl Add for ThreeDVector { +impl Add for ThreeDVector { } -impl Sub for ThreeDVector { +impl Sub for ThreeDVector { } ```