Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn lucians-luscious-lasagna into a Concept Exercise + fix low-power-embedded-game #156

Merged
merged 6 commits into from
Sep 4, 2024
Merged
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
28 changes: 14 additions & 14 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,22 @@
"name": "Low-power Embedded Game",
"uuid": "f3b7ce44-1667-42b4-b792-401d36aee2f1",
"concepts": [
"tuples",
"traits",
"generics"
"tuples"
],
"prerequisites": [
"traits"
],
"prerequisites": [],
"status": "wip"
},
{
"slug": "lucians-luscious-lasagna",
"name": "Lucian's Luscious Lasagna",
"uuid": "8302f8de-14d7-45dd-9a65-812bc1ed5464",
"concepts": [
"functions"
],
"prerequisites": [],
"status": "beta"
}
],
"practice": [
Expand Down Expand Up @@ -144,16 +154,6 @@
"prerequisites": [],
"difficulty": 2
},
{
"slug": "lucians-luscious-lasagna",
"name": "Lucian's Luscious Lasagna",
"uuid": "8302f8de-14d7-45dd-9a65-812bc1ed5464",
"practices": [
"functions"
],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "pangram",
"name": "Pangram",
Expand Down
49 changes: 2 additions & 47 deletions exercises/concept/low-power-embedded-game/.docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ Tuples are a lightweight way to group a fixed set of arbitrary types of data tog
a particular name; naming a data structure turns it into a `struct`. A tuple's fields don't have names;
they are accessed by means of destructuring or by position.

## Syntax

### Creation
## Creation

Tuples are always created with a tuple expression:

Expand All @@ -21,7 +19,7 @@ let two_element = (123, "elements can be of differing types");

Tuples can have an arbitrary number of elements.

### Access by destructuring
## Access by destructuring

It is possible to access the elements of a tuple by destructuring. This just means assigning variable
names to the individual elements of the tuple, consuming it.
Expand All @@ -30,46 +28,3 @@ names to the individual elements of the tuple, consuming it.
let (elem1, _elem2) = two_element;
assert_eq!(elem1, 123);
```

### Access by position

It is also possible to access the elements of a tuple by numeric positional index. Indexing, as always,
begins at 0.

```rust
let notation = single_element.0;
assert_eq!(notation, "note the comma");
```

## Tuple Structs

You will also be asked to work with tuple structs. Like normal structs, these are named types; unlike
normal structs, they have anonymous fields. Their syntax is very similar to normal tuple syntax. It is
legal to use both destructuring and positional access.

```rust
struct TupleStruct(u8, i32);
let my_tuple_struct = TupleStruct(123, -321);
let neg = my_tuple_struct.1;
let TupleStruct(byte, _) = my_tuple_struct;
assert_eq!(neg, -321);
assert_eq!(byte, 123);
```

### Field Visibility

All fields of anonymous tuples are always public. However, fields of tuple structs have individual
visibility which defaults to private, just like fields of standard structs. You can make the fields
public with the `pub` modifier, just as in a standard struct.

```rust
// fails due to private fields
mod tuple { pub struct TupleStruct(u8, i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }
```

```rust
// succeeds: fields are public
mod tuple { pub struct TupleStruct(pub u8, pub i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }
```
10 changes: 2 additions & 8 deletions exercises/concept/low-power-embedded-game/.meta/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,18 @@

## Goal

Introduce the student to tuples and how to work with them. Understand that traits can be automatically generated from an implementation.
Introduce the student to tuples and how to work with them.

## Learning objectives

- know how to create tuples and tuple structs
- know how to create tuples
- know how to destructure tuples into new variables, e.g. `let (x, y) = a_point;`;
- see that traits can be automatically generated by the compiler if the `impl` is annotated with the `#[generate_trait]` attribute.

## Out of scope

- enum variants with tuple structs

## Concepts

- tuples
- destructuring
- traits

## Prerequisites

Expand All @@ -29,4 +24,3 @@ Introduce the student to tuples and how to work with them. Understand that trait
### Hints

- <https://book.cairo-lang.org/ch02-02-data-types.html?highlight=tuples#the-tuple-type>
- <https://book.cairo-lang.org/ch05-03-method-syntax.html?highlight=generate_tra#the-generate_trait-attribute>
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub impl PositionImpl of PositionTrait {
}
}

// The below trait enables calling `abs` on an i16 variable
// to get the absolute value
#[generate_trait]
impl AbsImpl of AbsTrait {
fn abs(self: @i16) -> u16 {
Expand Down
14 changes: 14 additions & 0 deletions exercises/concept/low-power-embedded-game/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,17 @@ pub impl PositionImpl of PositionTrait {
panic!("implement `manhattan`")
}
}

// The below trait enables calling `abs` on an i16 variable
// to get the absolute value
#[generate_trait]
impl AbsImpl of AbsTrait {
fn abs(self: @i16) -> u16 {
let val = if *self < 0 {
-*self
} else {
*self
};
val.try_into().unwrap()
}
}
39 changes: 39 additions & 0 deletions exercises/concept/lucians-luscious-lasagna/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Hints

## General

- An [integer value][integers] can be defined as one or more consecutive digits.
- If you see a `panic` error when running the tests, this is because you have not implemented one of the functions (it should say which one) or you have left the boilerplate in place. You need to remove the `panic!(...)` line from the supplied code and replace it with a real implementation.

## 1. Define the expected oven time in minutes

- You need to define a [function][functions] without any parameters.
- You need to [return][return] the expected oven time in minutes from the function.

## 2. Calculate the remaining oven time in minutes

- You need to define a [function][functions] with a single parameter.
- The function's parameter is an [integer][integers].
- You have to [explicitly return an integer][return] from a function.
- You can [call][functions] one of the other functions you've defined previously.
- You can use the [mathematical operator for subtraction][operators] to subtract values.

## 3. Calculate the preparation time in minutes

- You need to define a [function][functions] with a single parameter.
- The function's parameter is an [integer][integers].
- You have to [explicitly return an integer][return] from a function.
- You can use the [mathematical operator for multiplication][operators] to multiply values.

## 4. Calculate the elapsed working time in minutes

- You need to define a [function][functions] with two parameters.
- The function's parameter is an [integer][integers].
- You have to [explicitly return an integer][return] from a function.
- You can [call][functions] one of the other functions you've defined previously.
- You can use the [mathematical operator for addition][operators] to add values.

[functions]: https://book.cairo-lang.org/ch02-03-functions.html
[return]: https://book.cairo-lang.org/ch02-03-functions.html#functions-with-return-values
[operators]: https://book.cairo-lang.org/appendix-02-operators-and-symbols.html
[integers]: https://book.cairo-lang.org/ch02-02-data-types.html#integer-types
82 changes: 82 additions & 0 deletions exercises/concept/lucians-luscious-lasagna/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Introduction

A function in Cairo allows you to group code into a reusable unit, making your programs more modular and easier to understand. Functions in Cairo consist of the `fn` keyword, followed by the function name, a list of parameters in parentheses, and a code block that defines what the function does.

## Function Parameters

In Cairo, all function parameters must be explicitly typed. Unlike some languages, Cairo does not infer types, and there are no default parameter values, so all parameters are required.

```rust
// Function with no parameters
fn print_hello() {
// Function body
}

// Function with two parameters
fn print_greeting_name(greeting: ByteArray, name: ByteArray) {
// Function body
}
```

## Parameters vs. Arguments

It's important to distinguish between `parameters` and `arguments`:

- **Parameters** are the variable names used in the function definition, such as `greeting` and `name` in the function `print_greeting_name`.
- **Arguments** are the actual values passed to the function when it is called.

```rust
// Calling the function with arguments
print_greeting_name(123, 456)
```

## Statements and Expressions

Function bodies are made up of a series of statements optionally ending in an expression.

- Statements are instructions that perform some action and do not return a value.
- Expressions evaluate to a resultant value.

Creating a variable and assigning a value to it with the `let` keyword is a statement.

```rust
let y = 6;
```

But the `6` in the above statement is an expression that evaluates to the value `6`.

Calling a function is an expression since it always evaluates to a value: the function's explicit return value, if specified, or the 'unit' type `()` otherwise.

## Return Values

Cairo functions can return values to the code that calls them. Return values are listed after the parameters, separated by an arrow `->`. In Cairo, the return value of the function is synonymous with the value of the final expression in the block of the body of a function. You can return early from a function by using the `return` keyword and specifying a value.

```rust
// Function returning the last (and only) expression
fn hello(name: ByteArray) -> ByteArray {
"Hello " + name
}

// Function returning using the `return` keyword
fn double_if_even(value: u32) -> u32 {
if value % 2 == 0 {
return value * 2;
}
return value;
}
```

## Invoking Functions

To call a function in Cairo, you simply use the function name followed by arguments in parentheses.

```rust
// Calling a function with no parameters
print_hello()

// Calling a function with one parameter
let greeting = hello("John")

// Calling a function with multiple parameters
print_greeting_name("Howdy", "Joel")
```
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
"test": [
"tests/lucians_luscious_lasagna.cairo"
],
"example": [
".meta/example.cairo"
"exemplar": [
".meta/exemplar.cairo"
],
"invalidator": [
"Scarb.toml"
]
},
"forked_from": [
"rust/lucians-luscious-lasagna"
],
"icon": "lasagna",
"blurb": "Learn about the basics of Cairo by following a lasagna recipe."
}
23 changes: 23 additions & 0 deletions exercises/concept/lucians-luscious-lasagna/.meta/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Design

## Learning objectives

- How to define a function
- How to invoke a function
- How to pass parameters to a function
- How to return a value from a function
- How to receive returned values from a function

## Out of scope

- Data types

## Concepts

The Concepts this exercise unlocks are:

- `functions`

## Prerequisites

There are no prerequisites.
37 changes: 0 additions & 37 deletions exercises/practice/lucians-luscious-lasagna/.docs/hints.md

This file was deleted.

Loading
Loading