Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/classroom/autograding.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"tests": [
{
"name": "test_rustlings",
"setup": "",
"run": "make test",
"input": "",
"output": "",
"comparison": "included",
"timeout": 10,
"points": 100
}
]
}
24 changes: 24 additions & 0 deletions .github/workflows/classroom.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: GitHub Classroom Workflow

on: [push]

permissions:
checks: write
actions: read
contents: read

jobs:
build:
name: Autograding
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
components: rustfmt, clippy
- name: Install rustlings
run: |
cargo install --force --path .
rustlings --help
- uses: education/autograding@v1
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions exercises/advanced_errors/advanced_errs1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
// Make this code compile! Execute `rustlings hint advanced_errs1` for
// hints :)

// I AM NOT DONE

use std::num::ParseIntError;
use std::str::FromStr;

Expand All @@ -24,6 +22,15 @@ impl From<CreationError> for ParsePosNonzeroError {
fn from(e: CreationError) -> Self {
// TODO: complete this implementation so that the `?` operator will
// work for `CreationError`
ParsePosNonzeroError::Creation(e)
}
}

impl From<ParseIntError> for ParsePosNonzeroError {
fn from(e: ParseIntError) -> Self {
// TODO: complete this implementation so that the `?` operator will
// work for `CreationError`
ParsePosNonzeroError::ParseInt(e)
}
}

Expand Down
17 changes: 14 additions & 3 deletions exercises/advanced_errors/advanced_errs2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,8 @@
// 4. Complete the partial implementation of `Display` for
// `ParseClimateError`.

// I AM NOT DONE

use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::fmt::{self, write, Display, Formatter};
use std::num::{ParseFloatError, ParseIntError};
use std::str::FromStr;

Expand Down Expand Up @@ -47,6 +45,7 @@ impl From<ParseIntError> for ParseClimateError {
impl From<ParseFloatError> for ParseClimateError {
fn from(e: ParseFloatError) -> Self {
// TODO: Complete this function
Self::ParseFloat(e)
}
}

Expand All @@ -62,7 +61,10 @@ impl Display for ParseClimateError {
// Imports the variants to make the following code more compact.
use ParseClimateError::*;
match self {
Empty => write!(f, "empty input"),
NoCity => write!(f, "no city name"),
BadLen => write!(f, "incorrect number of fields"),
ParseInt(e) => write!(f, "error parsing year: {}", e),
ParseFloat(e) => write!(f, "error parsing temperature: {}", e),
}
}
Expand All @@ -88,17 +90,26 @@ impl FromStr for Climate {
// TODO: Complete this function by making it handle the missing error
// cases.
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.len() == 0 {
return Err(ParseClimateError::Empty);
}
let v: Vec<_> = s.split(',').collect();
let (city, year, temp) = match &v[..] {
[city, year, temp] => (city.to_string(), year, temp),
_ => return Err(ParseClimateError::BadLen),
};
if city.len() == 0 {
return Err(ParseClimateError::NoCity);
}

let year: u32 = year.parse()?;
let temp: f32 = temp.parse()?;
Ok(Climate { city, year, temp })
}
}

impl Error for ParseClimateError {}

// Don't change anything below this line (other than to enable ignored
// tests).

Expand Down
4 changes: 1 addition & 3 deletions exercises/clippy/clippy1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@
// check clippy's suggestions from the output to solve the exercise.
// Execute `rustlings hint clippy1` for hints :)

// I AM NOT DONE

use std::f32;

fn main() {
let pi = 3.14f32;
let pi = std::f32::consts::PI;
let radius = 5.00f32;

let area = pi * f32::powi(radius, 2);
Expand Down
4 changes: 1 addition & 3 deletions exercises/clippy/clippy2.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// clippy2.rs
// Make me compile! Execute `rustlings hint clippy2` for hints :)

// I AM NOT DONE

fn main() {
let mut res = 42;
let option = Some(12);
for x in option {
if let Some(x) = option {
res += x;
}
println!("{}", res);
Expand Down
6 changes: 3 additions & 3 deletions exercises/collections/hashmap1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
// Execute the command `rustlings hint hashmap1` if you need
// hints.

// I AM NOT DONE

use std::collections::HashMap;

fn fruit_basket() -> HashMap<String, u32> {
let mut basket = // TODO: declare your hash map here.
let mut basket = HashMap::new();// TODO: declare your hash map here.

// Two bananas are already given for you :)
basket.insert(String::from("banana"), 2);
basket.insert(String::from("banana1"), 2);
basket.insert(String::from("banana2"), 2);

// TODO: Put more fruits in your basket here.

Expand Down
4 changes: 2 additions & 2 deletions exercises/collections/hashmap2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
// Execute the command `rustlings hint hashmap2` if you need
// hints.

// I AM NOT DONE

use std::collections::HashMap;

#[derive(Hash, PartialEq, Eq)]
Expand All @@ -38,6 +36,8 @@ fn fruit_basket(basket: &mut HashMap<Fruit, u32>) {
// TODO: Put new fruits if not already present. Note that you
// are not allowed to put any type of fruit that's already
// present!
basket.entry(fruit).or_insert(2);

}
}

Expand Down
4 changes: 1 addition & 3 deletions exercises/collections/vec1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@
// Make me compile and pass the test!
// Execute the command `rustlings hint vec1` if you need hints.

// I AM NOT DONE

fn array_and_vec() -> ([i32; 4], Vec<i32>) {
let a = [10, 20, 30, 40]; // a plain array
let v = // TODO: declare your vector here with the macro for vectors
let v = vec![10,20,30,40]; // TODO: declare your vector here with the macro for vectors

(a, v)
}
Expand Down
3 changes: 1 addition & 2 deletions exercises/collections/vec2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
// Execute the command `rustlings hint vec2` if you need
// hints.

// I AM NOT DONE

fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
for i in v.iter_mut() {
// TODO: Fill this up so that each element in the Vec `v` is
// multiplied by 2.
*i = (*i) * 2;
}

// At this point, `v` should be equal to [4, 8, 12, 16, 20].
Expand Down
6 changes: 2 additions & 4 deletions exercises/conversions/as_ref_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
// Read more about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html
// and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively.

// I AM NOT DONE

// Obtain the number of bytes (not characters) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn byte_counter<T>(arg: T) -> usize {
fn byte_counter<T:AsRef<str>> (arg: T) -> usize {
arg.as_ref().as_bytes().len()
}

// Obtain the number of characters (not bytes) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn char_counter<T>(arg: T) -> usize {
fn char_counter<T:AsRef<str>> (arg: T) -> usize {
arg.as_ref().chars().count()
}

Expand Down
24 changes: 22 additions & 2 deletions exercises/conversions/from_into.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::default;

// The From trait is used for value-to-value conversions.
// If From is implemented correctly for a type, the Into trait should work conversely.
// You can read more about it at https://doc.rust-lang.org/std/convert/trait.From.html
Expand Down Expand Up @@ -33,10 +35,28 @@ impl Default for Person {
// If while parsing the age, something goes wrong, then return the default of Person
// Otherwise, then return an instantiated Person object with the results

// I AM NOT DONE

impl From<&str> for Person {
fn from(s: &str) -> Person {
if s.len()==0 {
return Person::default();
}
let mut split = s.split(',');
if let Some(x) = split.next(){
if let Some(y) = split.next(){
if x.len()!=0{
let y = y.parse::<i32>();
if let Ok(y) = y {
if split.next() == None{
return Person{
name:x.to_string(),
age:y as usize,
}
}
}
}
}
}
Person::default()
}
}

Expand Down
24 changes: 22 additions & 2 deletions exercises/conversions/from_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ enum ParsePersonError {
ParseInt(ParseIntError),
}

// I AM NOT DONE

// Steps:
// 1. If the length of the provided string is 0, an error should be returned
// 2. Split the given string on the commas present in it
Expand All @@ -41,6 +39,28 @@ enum ParsePersonError {
impl FromStr for Person {
type Err = ParsePersonError;
fn from_str(s: &str) -> Result<Person, Self::Err> {
if s.len() == 0 {
return Err(ParsePersonError::Empty);
}
let mut split = s.split(',');
let s: Vec<_> = split.collect();
if s.len() != 2 {
return Err(ParsePersonError::BadLen);
}
let Name = s[0];
let Age = s[1].parse::<usize>();
if Name.len() == 0 {
return Err(ParsePersonError::NoName);
}
match Age {
Ok(age) => Ok(Person {
name: Name.to_string(),
age: age,
}),
Err(err) => {
Err(ParsePersonError::ParseInt(err))
}
}
}
}

Expand Down
25 changes: 22 additions & 3 deletions exercises/conversions/try_from_into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
// Basically, this is the same as From. The main difference is that this should return a Result type
// instead of the target type itself.
// You can read more about it at https://doc.rust-lang.org/std/convert/trait.TryFrom.html
use std::convert::{TryFrom, TryInto};
use std::{
cmp::min,
cmp::max,
convert::{TryFrom, TryInto},
};

#[derive(Debug, PartialEq)]
struct Color {
Expand All @@ -21,8 +25,6 @@ enum IntoColorError {
IntConversion,
}

// I AM NOT DONE

// Your task is to complete this implementation
// and return an Ok result of inner type Color.
// You need to create an implementation for a tuple of three integers,
Expand All @@ -36,20 +38,37 @@ enum IntoColorError {
impl TryFrom<(i16, i16, i16)> for Color {
type Error = IntoColorError;
fn try_from(tuple: (i16, i16, i16)) -> Result<Self, Self::Error> {
let (red, green, blue) = tuple;
if min(red, min(green, blue)) < 0 {
return Err(IntoColorError::IntConversion);
}
if max(red, max(green, blue)) > u8::MAX as i16 {
return Err(IntoColorError::IntConversion);
}
Ok(Color {
red: tuple.0 as u8,
green: tuple.1 as u8,
blue: tuple.2 as u8,
})
}
}

// Array implementation
impl TryFrom<[i16; 3]> for Color {
type Error = IntoColorError;
fn try_from(arr: [i16; 3]) -> Result<Self, Self::Error> {
Self::try_from((arr[0],arr[1],arr[2]))
}
}

// Slice implementation
impl TryFrom<&[i16]> for Color {
type Error = IntoColorError;
fn try_from(slice: &[i16]) -> Result<Self, Self::Error> {
if(slice.len()!=3){
return Err(IntoColorError::BadLen);
}
Self::try_from((slice[0],slice[1],slice[2]))
}
}

Expand Down
4 changes: 1 addition & 3 deletions exercises/conversions/using_as.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
// The goal is to make sure that the division does not fail to compile
// and returns the proper type.

// I AM NOT DONE

fn average(values: &[f64]) -> f64 {
let total = values.iter().sum::<f64>();
total / values.len()
total / values.len() as f64
}

fn main() {
Expand Down
Loading