From cb0f0040ad61f7db44a9f91ee435d0a3140d5c3f Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 21:50:50 +0100 Subject: [PATCH 01/17] add introduction.md --- .../.docs/introduction.md | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/exercises/concept/chrono-realms-time-tree/.docs/introduction.md b/exercises/concept/chrono-realms-time-tree/.docs/introduction.md index e69de29b..7ba0dbca 100644 --- a/exercises/concept/chrono-realms-time-tree/.docs/introduction.md +++ b/exercises/concept/chrono-realms-time-tree/.docs/introduction.md @@ -0,0 +1,89 @@ +# Introduction + +Smart pointers in Cairo are a powerful tool that provide safe and efficient management of memory. + +A smart pointer is a data structure that acts like a regular pointer, but with added safety features to avoid common memory management issues like dereferencing null pointers or accessing uninitialized memory. + +## What is a Smart Pointer? + +In general, a pointer is a variable that stores a memory address, typically pointing to a value stored at that location. + +However, raw pointers can be dangerous: if the pointer doesn't point to valid memory or is incorrectly dereferenced, it can lead to crashes or unpredictable behavior. + +Smart pointers solve this issue by enforcing strict rules on memory management, ensuring that memory is accessed in a safe and controlled manner. + +Cairo, like many modern languages such as Rust, uses smart pointers to prevent unsafe memory access. + +A smart pointer in Cairo not only stores a memory address but also tracks ownership and ensures memory safety. + +## Types of Smart Pointers in Cairo + +Cairo provides several types of smart pointers, including `Box` and `Nullable`, each serving a different purpose. + +Let's take a closer look at how these types work and when you might use them. + +### `Box` + +The `Box` type is the principal smart pointer in Cairo. + +It allows you to store data in a special memory segment called the "boxed segment." A `Box` is a pointer that points to this segment, and when you create a box, you allocate space for the data in this segment. + +Boxes are ideal in situations where: + +- You need to store a value of a type whose size cannot be determined at compile time. +- You have a large amount of data and want to transfer ownership without copying it. + +By using a box, you can store large data structures more efficiently. + +When passing a `Box` to a function, only the pointer is passed, avoiding the need to copy the entire data, which improves performance, especially with large structures. + +### `Nullable` + +The `Nullable` type is another important smart pointer in Cairo. + +It can either point to a valid value of type `T` or be `null` if there is no value. + +This type is useful in cases where you need to store values that may not always exist, such as in a dictionary that can contain optional elements. + +In Cairo, `Nullable` is typically used in dictionaries to handle cases where no default value can be applied. + +It allows you to store values conditionally, making it easier to handle the absence of data safely. + +## Memory Safety with Smart Pointers + +One of the primary advantages of using smart pointers is that they help ensure memory safety. + +By managing ownership and access rules, Cairo prevents common issues such as dereferencing null or dangling pointers. + +Smart pointers track when data is no longer needed and can automatically deallocate memory when it goes out of scope, reducing the risk of memory leaks. + +### Example: Using a `Box` for Recursive Types + +A common challenge in many programming languages is handling recursive types. + +Recursive types refer to types that contain references to themselves. + +Without proper memory management, defining a recursive type can lead to issues such as infinite recursion. + +In Cairo, `Box` makes it possible to define recursive types safely. + +For instance, you can use `Box` to implement a binary tree, where each node contains a reference to another node. + +By storing references in boxes, Cairo ensures that memory usage is finite, and the compiler can determine the required memory size for the structure. + +```rust +use core::box::{BoxTrait}; + +#[derive(Copy, Drop)] +enum BinaryTree { + Leaf: u32, + Node: (u32, Box, Box), +} + +fn main() { + let leaf1 = BinaryTree::Leaf(1); + let leaf2 = BinaryTree::Leaf(2); + let node = BinaryTree::Node((3, BoxTrait::new(leaf1), BoxTrait::new(leaf2))); + println!("{:?}", node); +} +``` From cf6e4c04d94b81091371cb28a0508c5f80865b31 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 21:54:45 +0100 Subject: [PATCH 02/17] update descr in control-flow links --- concepts/control-flow/links.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concepts/control-flow/links.json b/concepts/control-flow/links.json index 2cc370a3..efe514a5 100644 --- a/concepts/control-flow/links.json +++ b/concepts/control-flow/links.json @@ -1,6 +1,6 @@ [ { "url": "https://book.cairo-lang.org/ch02-05-control-flow.html", - "description": "Control flow concept in cairo book" + "description": "Control Flow Concept in The Cairo Book" } ] From c112c262bab36dbadace57b095ab166412aa5838 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 21:59:29 +0100 Subject: [PATCH 03/17] add missing comma in control-flow blurb --- concepts/control-flow/.meta/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concepts/control-flow/.meta/config.json b/concepts/control-flow/.meta/config.json index 17756acf..6058fa32 100644 --- a/concepts/control-flow/.meta/config.json +++ b/concepts/control-flow/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Control flow in Cairo uses `if` expressions to conditionally execute code and loops to run code repeatedly.", + "blurb": "Control flow in Cairo uses `if` expressions to conditionally execute code, and loops to run code repeatedly.", "authors": ["Falilah"], "contributors": ["0xNeshi"] } From 342a68affcc4d8f94f003e67e32eb971985fa128 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 22:01:11 +0100 Subject: [PATCH 04/17] Add smart pointers concept --- concepts/smart-pointers/.meta/config.json | 4 +- concepts/smart-pointers/about.md | 126 ++++++++++++++++++++++ concepts/smart-pointers/introduction.md | 6 ++ concepts/smart-pointers/links.json | 12 ++- 4 files changed, 145 insertions(+), 3 deletions(-) diff --git a/concepts/smart-pointers/.meta/config.json b/concepts/smart-pointers/.meta/config.json index 35b1d32b..0dfbb489 100644 --- a/concepts/smart-pointers/.meta/config.json +++ b/concepts/smart-pointers/.meta/config.json @@ -1,7 +1,7 @@ { - "blurb": "", + "blurb": "Smart pointers in Cairo are special data structures that manage memory safely by ensuring that memory is accessed in a controlled way.", "authors": [ - "" + "0xNeshi" ], "contributors": [] } diff --git a/concepts/smart-pointers/about.md b/concepts/smart-pointers/about.md index bf8e8d62..435e99c6 100644 --- a/concepts/smart-pointers/about.md +++ b/concepts/smart-pointers/about.md @@ -1 +1,127 @@ # Smart Pointers + +Smart pointers in Cairo are a powerful tool that provide safe and efficient management of memory. + +A smart pointer is a data structure that acts like a regular pointer, but with added safety features to avoid common memory management issues like dereferencing null pointers or accessing uninitialized memory. + +## What is a Smart Pointer? + +In general, a pointer is a variable that stores a memory address, typically pointing to a value stored at that location. + +However, raw pointers can be dangerous: if the pointer doesn't point to valid memory or is incorrectly dereferenced, it can lead to crashes or unpredictable behavior. + +Smart pointers solve this issue by enforcing strict rules on memory management, ensuring that memory is accessed in a safe and controlled manner. + +Cairo, like many modern languages such as Rust, uses smart pointers to prevent unsafe memory access. + +A smart pointer in Cairo not only stores a memory address but also tracks ownership and ensures memory safety. + +## Types of Smart Pointers in Cairo + +Cairo provides several types of smart pointers, including `Box` and `Nullable`, each serving a different purpose. + +Let's take a closer look at how these types work and when you might use them. + +### `Box` + +The `Box` type is the principal smart pointer in Cairo. + +It allows you to store data in a special memory segment called the "boxed segment." A `Box` is a pointer that points to this segment, and when you create a box, you allocate space for the data in this segment. + +Boxes are ideal in situations where: + +- You need to store a value of a type whose size cannot be determined at compile time. +- You have a large amount of data and want to transfer ownership without copying it. + +By using a box, you can store large data structures more efficiently. + +When passing a `Box` to a function, only the pointer is passed, avoiding the need to copy the entire data, which improves performance, especially with large structures. + +### `Nullable` + +The `Nullable` type is another important smart pointer in Cairo. + +It can either point to a valid value of type `T` or be `null` if there is no value. + +This type is useful in cases where you need to store values that may not always exist, such as in a dictionary that can contain optional elements. + +In Cairo, `Nullable` is typically used in dictionaries to handle cases where no default value can be applied. + +It allows you to store values conditionally, making it easier to handle the absence of data safely. + +## Memory Safety with Smart Pointers + +One of the primary advantages of using smart pointers is that they help ensure memory safety. + +By managing ownership and access rules, Cairo prevents common issues such as dereferencing null or dangling pointers. + +Smart pointers track when data is no longer needed and can automatically deallocate memory when it goes out of scope, reducing the risk of memory leaks. + +### Example: Using a `Box` for Recursive Types + +A common challenge in many programming languages is handling recursive types. + +Recursive types refer to types that contain references to themselves. + +Without proper memory management, defining a recursive type can lead to issues such as infinite recursion. + +In Cairo, `Box` makes it possible to define recursive types safely. + +For instance, you can use `Box` to implement a binary tree, where each node contains a reference to another node. + +By storing references in boxes, Cairo ensures that memory usage is finite, and the compiler can determine the required memory size for the structure. + +```rust +use core::box::{BoxTrait}; + +#[derive(Copy, Drop)] +enum BinaryTree { + Leaf: u32, + Node: (u32, Box, Box), +} + +fn main() { + let leaf1 = BinaryTree::Leaf(1); + let leaf2 = BinaryTree::Leaf(2); + let node = BinaryTree::Node((3, BoxTrait::new(leaf1), BoxTrait::new(leaf2))); + println!("{:?}", node); +} +``` + +### Performance Benefits of Smart Pointers + +Smart pointers also improve the performance of your programs. + +When you use `Box`, only the pointer to the data is passed around, instead of copying the entire data structure. + +This is especially useful when dealing with large datasets, as it significantly reduces the overhead of memory operations. + +In the following example, the data is passed by reference using a `Box` to avoid the cost of copying the entire structure: + +```rust +#[derive(Drop)] +struct Cart { + paid: bool, + items: u256, + buyer: ByteArray, +} + +fn pass_data(cart: Cart) { + println!("{} is shopping today and bought {} items", cart.buyer, cart.items); +} + +fn pass_pointer(cart: Box) { + let cart = cart.unbox(); + println!("{} is shopping today and bought {} items", cart.buyer, cart.items); +} + +fn main() { + let new_cart = Cart { paid: true, items: 1, buyer: "John" }; + pass_data(new_cart); + + let new_box = BoxTrait::new(Cart { paid: false, items: 3, buyer: "Jane" }); + pass_pointer(new_box); +} +``` + +In this example, `pass_pointer` takes a `Box` instead of a `Cart`, reducing the amount of memory copied during the function call. diff --git a/concepts/smart-pointers/introduction.md b/concepts/smart-pointers/introduction.md index e10b99d0..77bfcbde 100644 --- a/concepts/smart-pointers/introduction.md +++ b/concepts/smart-pointers/introduction.md @@ -1 +1,7 @@ # Introduction + +Smart pointers in Cairo are special data structures that manage memory safely by ensuring that memory is accessed in a controlled way. + +They act like regular pointers but include additional features like ownership rules and metadata to prevent common errors, such as dereferencing uninitialized memory. + +This makes them essential for working with complex data structures and improving program safety and performance. diff --git a/concepts/smart-pointers/links.json b/concepts/smart-pointers/links.json index fe51488c..fa9411a8 100644 --- a/concepts/smart-pointers/links.json +++ b/concepts/smart-pointers/links.json @@ -1 +1,11 @@ -[] +[ + { + "url": "https://book.cairo-lang.org/ch11-02-smart-pointers.html", + "description": "Smart Pointers in The Cairo Book" + }, + { + "url": "https://book.cairo-lang.org/ch03-02-dictionaries.html#dictionaries-of-types-not-supported-natively", + "description": "Nullable Use Case with Dictionaries" + } +] + \ No newline at end of file From 892947e7557c31ab6d8ed8dc718e4da696ec71e0 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 22:05:40 +0100 Subject: [PATCH 05/17] rewrite introduction.md --- .../.docs/introduction.md | 82 +++++-------------- 1 file changed, 22 insertions(+), 60 deletions(-) diff --git a/exercises/concept/chrono-realms-time-tree/.docs/introduction.md b/exercises/concept/chrono-realms-time-tree/.docs/introduction.md index 7ba0dbca..1c1ac3a7 100644 --- a/exercises/concept/chrono-realms-time-tree/.docs/introduction.md +++ b/exercises/concept/chrono-realms-time-tree/.docs/introduction.md @@ -1,75 +1,25 @@ # Introduction -Smart pointers in Cairo are a powerful tool that provide safe and efficient management of memory. - -A smart pointer is a data structure that acts like a regular pointer, but with added safety features to avoid common memory management issues like dereferencing null pointers or accessing uninitialized memory. +Smart pointers in Cairo are advanced data structures that ensure safe and efficient memory management by adding safety features to regular pointers, preventing common issues like dereferencing null pointers or accessing uninitialized memory. ## What is a Smart Pointer? -In general, a pointer is a variable that stores a memory address, typically pointing to a value stored at that location. - -However, raw pointers can be dangerous: if the pointer doesn't point to valid memory or is incorrectly dereferenced, it can lead to crashes or unpredictable behavior. - -Smart pointers solve this issue by enforcing strict rules on memory management, ensuring that memory is accessed in a safe and controlled manner. - -Cairo, like many modern languages such as Rust, uses smart pointers to prevent unsafe memory access. - -A smart pointer in Cairo not only stores a memory address but also tracks ownership and ensures memory safety. - -## Types of Smart Pointers in Cairo - -Cairo provides several types of smart pointers, including `Box` and `Nullable`, each serving a different purpose. - -Let's take a closer look at how these types work and when you might use them. - -### `Box` - -The `Box` type is the principal smart pointer in Cairo. - -It allows you to store data in a special memory segment called the "boxed segment." A `Box` is a pointer that points to this segment, and when you create a box, you allocate space for the data in this segment. - -Boxes are ideal in situations where: - -- You need to store a value of a type whose size cannot be determined at compile time. -- You have a large amount of data and want to transfer ownership without copying it. - -By using a box, you can store large data structures more efficiently. - -When passing a `Box` to a function, only the pointer is passed, avoiding the need to copy the entire data, which improves performance, especially with large structures. - -### `Nullable` +A smart pointer behaves like a regular pointer but tracks ownership and ensures safe memory access, preventing issues like null or dangling pointer dereferencing. -The `Nullable` type is another important smart pointer in Cairo. +## Types of Smart Pointers -It can either point to a valid value of type `T` or be `null` if there is no value. +Cairo provides several smart pointer types, such as `Box` and `Nullable`: -This type is useful in cases where you need to store values that may not always exist, such as in a dictionary that can contain optional elements. +- **`Box`**: Stores data in a special memory segment, ideal for large or dynamically-sized data. It allows transferring ownership without copying the data. +- **`Nullable`**: Points to either a valid value of type `T` or `null`, useful for handling optional values. -In Cairo, `Nullable` is typically used in dictionaries to handle cases where no default value can be applied. +## Memory Safety -It allows you to store values conditionally, making it easier to handle the absence of data safely. +Smart pointers help prevent unsafe memory access, ensuring memory is automatically deallocated when no longer needed, thus reducing the risk of memory leaks. -## Memory Safety with Smart Pointers +### Example: Using `Box` for Recursive Types -One of the primary advantages of using smart pointers is that they help ensure memory safety. - -By managing ownership and access rules, Cairo prevents common issues such as dereferencing null or dangling pointers. - -Smart pointers track when data is no longer needed and can automatically deallocate memory when it goes out of scope, reducing the risk of memory leaks. - -### Example: Using a `Box` for Recursive Types - -A common challenge in many programming languages is handling recursive types. - -Recursive types refer to types that contain references to themselves. - -Without proper memory management, defining a recursive type can lead to issues such as infinite recursion. - -In Cairo, `Box` makes it possible to define recursive types safely. - -For instance, you can use `Box` to implement a binary tree, where each node contains a reference to another node. - -By storing references in boxes, Cairo ensures that memory usage is finite, and the compiler can determine the required memory size for the structure. +Smart pointers like `Box` allow for safe handling of recursive types, such as in a binary tree, by allocating memory efficiently and avoiding infinite recursion. ```rust use core::box::{BoxTrait}; @@ -87,3 +37,15 @@ fn main() { println!("{:?}", node); } ``` + +## Performance Benefits + +Smart pointers improve performance by passing references to data instead of copying large structures, reducing memory overhead. + +```rust +// `Cart` is a large struct that contains a lot of information +fn pass_pointer(cart: Box) { + let cart = cart.unbox(); + println!("{} is shopping today and bought {} items", cart.buyer, cart.items); +} +``` From e19711978117e14946d537e5769780e2ffa3dbec Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 22:13:03 +0100 Subject: [PATCH 06/17] add hints --- .../chrono-realms-time-tree/.docs/hints.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/exercises/concept/chrono-realms-time-tree/.docs/hints.md b/exercises/concept/chrono-realms-time-tree/.docs/hints.md index e69de29b..7b25651c 100644 --- a/exercises/concept/chrono-realms-time-tree/.docs/hints.md +++ b/exercises/concept/chrono-realms-time-tree/.docs/hints.md @@ -0,0 +1,17 @@ +# Hints + +## General + +- [The Cairo Book: Smart Pointers] + +## 1. Build the ChronoChain from an array of `u32` values + +- We can iterate through the array and construct a chain in reverse, starting from the `End` and linking each value with the `Link` variant. +- Consider using `span.pop_back()` to iterate through the array in reverse order. This will help us create the chain from the end to the start. + +## 2. Sum the values in the ChronoChain + +- Use pattern matching to handle the two variants of `ChronoChain`. When you reach `End`, the sum is 0, and when you reach `Link`, you add the value and recursively sum the rest of the chain. +- This approach is similar to a recursive function that traverses the structure until it reaches the base case (`End`). + +[The Cairo Book: Smart Pointers]: https://book.cairo-lang.org/ch11-02-smart-pointers.html From ac36081e618aa54119d6c1acb5ce47273f7a03a4 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 22:14:42 +0100 Subject: [PATCH 07/17] write blurb --- exercises/concept/chrono-realms-time-tree/.meta/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/concept/chrono-realms-time-tree/.meta/config.json b/exercises/concept/chrono-realms-time-tree/.meta/config.json index edd96af6..45eb47f3 100644 --- a/exercises/concept/chrono-realms-time-tree/.meta/config.json +++ b/exercises/concept/chrono-realms-time-tree/.meta/config.json @@ -16,5 +16,5 @@ "Scarb.toml" ] }, - "blurb": "" + "blurb": "Learn smart pointers by building the magical Chrono Chain" } From 051bf78f7ef6fa63db45e3bf621b3468b89a5c09 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 22:17:25 +0100 Subject: [PATCH 08/17] format md files --- .../chrono-realms-time-tree/.docs/hints.md | 5 +++-- .../.docs/instructions.md | 18 +++++++++--------- .../.docs/introduction.md | 3 ++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/exercises/concept/chrono-realms-time-tree/.docs/hints.md b/exercises/concept/chrono-realms-time-tree/.docs/hints.md index 7b25651c..0f3e0573 100644 --- a/exercises/concept/chrono-realms-time-tree/.docs/hints.md +++ b/exercises/concept/chrono-realms-time-tree/.docs/hints.md @@ -7,11 +7,12 @@ ## 1. Build the ChronoChain from an array of `u32` values - We can iterate through the array and construct a chain in reverse, starting from the `End` and linking each value with the `Link` variant. -- Consider using `span.pop_back()` to iterate through the array in reverse order. This will help us create the chain from the end to the start. +- Consider using `span.pop_back()` to iterate through the array in reverse order, this will help us create the chain from the end to the start. ## 2. Sum the values in the ChronoChain -- Use pattern matching to handle the two variants of `ChronoChain`. When you reach `End`, the sum is 0, and when you reach `Link`, you add the value and recursively sum the rest of the chain. +- Use pattern matching to handle the two variants of `ChronoChain`. +- When you reach `End`, the sum is 0, and when you reach `Link`, you add the value and recursively sum the rest of the chain. - This approach is similar to a recursive function that traverses the structure until it reaches the base case (`End`). [The Cairo Book: Smart Pointers]: https://book.cairo-lang.org/ch11-02-smart-pointers.html diff --git a/exercises/concept/chrono-realms-time-tree/.docs/instructions.md b/exercises/concept/chrono-realms-time-tree/.docs/instructions.md index 9522b7f4..f07bef54 100644 --- a/exercises/concept/chrono-realms-time-tree/.docs/instructions.md +++ b/exercises/concept/chrono-realms-time-tree/.docs/instructions.md @@ -1,20 +1,20 @@ # Instructions -In **ChronoRealms**, TimeKeepers often deal with not just trees of timelines, but **ChronoChains**-sequences of linked **TimeNodes**, each representing a specific moment in time. -A **ChronoChain** is a straight path of sequential moments, where each **TimeNode** connects to the next. -These **ChronoChains** are useful when traveling through a series of specific events, as they allow TimeKeepers to follow a single timeline. +In **Chrono Realms**, Time Keepers often deal with not just trees of timelines, but **Chrono Chains**-sequences of linked **TimeNodes**, each representing a specific moment in time. +A **Chrono Chain** is a straight path of sequential moments, where each **TimeNode** connects to the next. +These **Chrono Chains** are useful when traveling through a series of specific events, as they allow Time Keepers to follow a single timeline. -However, to handle these potentially long **ChronoChains**, TimeKeepers use **Smart Pointers (Box)** to safely manage and traverse these lists of moments without causing unnecessary memory duplication or overflow. +However, to handle these potentially long **Chrono Chains**, Time Keepers use **Smart Pointers (Box)** to safely manage and traverse these lists of moments without causing unnecessary memory duplication or overflow. Each **TimeNode** holds a reference to the next node, forming a recursive structure. -Your task as an apprentice is to implement a **ChronoChain** as a recursive list structure using smart pointers. +Your task as an apprentice is to implement a **Chrono Chain** as a recursive list structure using smart pointers. In this exercise, you will: 1. Create a recursive `ChronoChain` enum, representing a list of moments. 2. Use the `Box` smart pointer to store the recursive nodes. -3. Implement a function to create a **ChronoChain** from an array of `u32` values. -4. Implement a function to traverse the **ChronoChain** and sum up the values stored in the list. +3. Implement a function to create a `ChronoChain` from an array of `u32` values. +4. Implement a function to traverse the `ChronoChain` and sum up the values stored in the list. ## 1. Define the Recursive `ChronoChain` Enum @@ -25,11 +25,11 @@ Create a recursive enum `ChronoChain` with two variants: ## 2. Create a Function to Build a ChronoChain -Write a function `build_chrono_chain` that takes an array of `u32` values and returns a **ChronoChain**, linking the values sequentially using smart pointers. +Write a function `build_chrono_chain` that takes an array of `u32` values and returns a `ChronoChain`, linking the values sequentially using smart pointers. ## 3. Implement the Sum Function -Write a function `sum_chain` to recursively traverse the **ChronoChain** and sum the values of all nodes. +Write a function `sum_chain` to recursively traverse the `ChronoChain` and sum the values of all nodes. ## Example Usage diff --git a/exercises/concept/chrono-realms-time-tree/.docs/introduction.md b/exercises/concept/chrono-realms-time-tree/.docs/introduction.md index 1c1ac3a7..880a6084 100644 --- a/exercises/concept/chrono-realms-time-tree/.docs/introduction.md +++ b/exercises/concept/chrono-realms-time-tree/.docs/introduction.md @@ -10,7 +10,8 @@ A smart pointer behaves like a regular pointer but tracks ownership and ensures Cairo provides several smart pointer types, such as `Box` and `Nullable`: -- **`Box`**: Stores data in a special memory segment, ideal for large or dynamically-sized data. It allows transferring ownership without copying the data. +- **`Box`**: Stores data in a special memory segment, ideal for large or dynamically-sized data. + It allows transferring ownership without copying the data. - **`Nullable`**: Points to either a valid value of type `T` or `null`, useful for handling optional values. ## Memory Safety From f225592dc59baa667248f9f54733552213590f5c Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 22:22:18 +0100 Subject: [PATCH 09/17] add design --- .../chrono-realms-time-tree/.meta/design.md | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/exercises/concept/chrono-realms-time-tree/.meta/design.md b/exercises/concept/chrono-realms-time-tree/.meta/design.md index e69de29b..1c3968bd 100644 --- a/exercises/concept/chrono-realms-time-tree/.meta/design.md +++ b/exercises/concept/chrono-realms-time-tree/.meta/design.md @@ -0,0 +1,35 @@ +# Design + +## Goal + +Introduce the student to working with recursive types and smart pointers in Cairo. + +## Learning objectives + +- Understand how to define and use recursive types with enums in Cairo. +- Learn how to use smart pointers (`Box`) for handling recursive data structures. +- Practice working with recursive functions to traverse and manipulate linked data. + +## Out of scope + +- Advanced memory management concepts related to smart pointers beyond `Box`. +- Deep dive into optimization of recursive data structures. + +## Concepts + +- Enums +- Recursive types +- Smart pointers (`Box`) + +## Prerequisites + +- Basic understanding of enums and data types in Cairo. +- Familiarity with smart pointers in Cairo. + +## Resources to refer to + +- [Cairo Book - The Box Type][box] +- [Cairo Book - Enums][enums] + +[box]: https://book.cairo-lang.org/ch11-02-smart-pointers.html#the-boxt-type-to-manipulate-pointers +[enums]: https://book.cairo-lang.org/ch06-01-enums.html From 73edefaea85cf230a0f4695f4fb177a42d4feb5b Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 22:24:32 +0100 Subject: [PATCH 10/17] update link in hints --- exercises/concept/chrono-realms-time-tree/.docs/hints.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/concept/chrono-realms-time-tree/.docs/hints.md b/exercises/concept/chrono-realms-time-tree/.docs/hints.md index 0f3e0573..d4fcf74e 100644 --- a/exercises/concept/chrono-realms-time-tree/.docs/hints.md +++ b/exercises/concept/chrono-realms-time-tree/.docs/hints.md @@ -2,7 +2,7 @@ ## General -- [The Cairo Book: Smart Pointers] +- [The Cairo Book: Smart Pointers][smart-pointers] ## 1. Build the ChronoChain from an array of `u32` values @@ -15,4 +15,4 @@ - When you reach `End`, the sum is 0, and when you reach `Link`, you add the value and recursively sum the rest of the chain. - This approach is similar to a recursive function that traverses the structure until it reaches the base case (`End`). -[The Cairo Book: Smart Pointers]: https://book.cairo-lang.org/ch11-02-smart-pointers.html +[smart-pointers]: https://book.cairo-lang.org/ch11-02-smart-pointers.html From 9ffe332b846a1e65e144b17edd5d0af970fdd729 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 22:53:59 +0100 Subject: [PATCH 11/17] add more tests + update to be trait-based --- .../.docs/instructions.md | 8 +- .../chrono-realms-time-tree/.meta/design.md | 1 + .../.meta/exemplar.cairo | 33 +-- .../chrono-realms-time-tree/src/lib.cairo | 17 +- .../tests/chrono_realms_time_tree.cairo | 252 ++++++++++++++++-- 5 files changed, 264 insertions(+), 47 deletions(-) diff --git a/exercises/concept/chrono-realms-time-tree/.docs/instructions.md b/exercises/concept/chrono-realms-time-tree/.docs/instructions.md index f07bef54..0201d2c8 100644 --- a/exercises/concept/chrono-realms-time-tree/.docs/instructions.md +++ b/exercises/concept/chrono-realms-time-tree/.docs/instructions.md @@ -25,21 +25,21 @@ Create a recursive enum `ChronoChain` with two variants: ## 2. Create a Function to Build a ChronoChain -Write a function `build_chrono_chain` that takes an array of `u32` values and returns a `ChronoChain`, linking the values sequentially using smart pointers. +Write a function `ChronoChain::build` that takes an array of `u32` values and returns a `ChronoChain`, linking the values sequentially using smart pointers. ## 3. Implement the Sum Function -Write a function `sum_chain` to recursively traverse the `ChronoChain` and sum the values of all nodes. +Write a function `ChronoChain::sum` to recursively traverse the `ChronoChain` and sum the values of all nodes. ## Example Usage ```rust fn main() { // Create a ChronoChain from an array of values - let chrono_chain = build_chrono_chain([10, 20, 30]); + let chrono_chain = ChronoChain::build(array![10, 20, 30]); // Sum the values in the ChronoChain - let total_sum = sum_chain(&chrono_chain); + let total_sum = chrono_chain.sum(); println!("Total Time Power: {}", total_sum); } diff --git a/exercises/concept/chrono-realms-time-tree/.meta/design.md b/exercises/concept/chrono-realms-time-tree/.meta/design.md index 1c3968bd..bdb2a7a2 100644 --- a/exercises/concept/chrono-realms-time-tree/.meta/design.md +++ b/exercises/concept/chrono-realms-time-tree/.meta/design.md @@ -23,6 +23,7 @@ Introduce the student to working with recursive types and smart pointers in Cair ## Prerequisites +- Traits - Basic understanding of enums and data types in Cairo. - Familiarity with smart pointers in Cairo. diff --git a/exercises/concept/chrono-realms-time-tree/.meta/exemplar.cairo b/exercises/concept/chrono-realms-time-tree/.meta/exemplar.cairo index f47658eb..a1a0cecc 100644 --- a/exercises/concept/chrono-realms-time-tree/.meta/exemplar.cairo +++ b/exercises/concept/chrono-realms-time-tree/.meta/exemplar.cairo @@ -5,23 +5,26 @@ pub enum ChronoChain { Link: (u32, Box), } -// Function to build a ChronoChain from an array of u32 values -pub fn build_chrono_chain(arr: Array) -> Box { - let mut chain = ChronoChain::End; +#[generate_trait] +pub impl ChronoChainImpl of ChronoChainTrait { + // Function to build a ChronoChain from an array of u32 values + fn build(arr: Array) -> ChronoChain { + let mut chain = ChronoChain::End; - // Iterate in reverse to build the chain from the end to the beginning - let mut span = arr.span(); - while let Option::Some(value) = span.pop_back() { - chain = ChronoChain::Link((*value, BoxTrait::new(chain))); - }; + // Iterate in reverse to build the chain from the end to the beginning + let mut span = arr.span(); + while let Option::Some(value) = span.pop_back() { + chain = ChronoChain::Link((*value, BoxTrait::new(chain))); + }; - BoxTrait::new(chain) -} + chain + } -// Function to sum the values in the ChronoChain -pub fn sum_chain(chain: @ChronoChain) -> u32 { - match chain { - ChronoChain::End => 0, - ChronoChain::Link((value, next)) => *value + sum_chain(@(*next).unbox()), + // Function to sum the values in the ChronoChain + fn sum(self: ChronoChain) -> u64 { + match self { + ChronoChain::End => 0, + ChronoChain::Link((value, next)) => value.into() + next.unbox().sum(), + } } } diff --git a/exercises/concept/chrono-realms-time-tree/src/lib.cairo b/exercises/concept/chrono-realms-time-tree/src/lib.cairo index 3a558df7..6d3b5410 100644 --- a/exercises/concept/chrono-realms-time-tree/src/lib.cairo +++ b/exercises/concept/chrono-realms-time-tree/src/lib.cairo @@ -5,12 +5,15 @@ pub enum ChronoChain { Link: (u32, Box), } -// Function to build a ChronoChain from an array of u32 values -pub fn build_chrono_chain(arr: Array) -> Box { - panic!("implement 'build_chrono_chain'") -} +#[generate_trait] +pub impl ChronoChainImpl of ChronoChainTrait { + // Function to build a ChronoChain from an array of u32 values + fn build(arr: Array) -> ChronoChain { + panic!("implement `ChronoChain::build`") + } -// Function to sum the values in the ChronoChain -pub fn sum_chain(chain: @ChronoChain) -> u32 { - panic!("implement 'sum_chain'") + // Function to sum the values in the ChronoChain + fn sum(self: ChronoChain) -> u64 { + panic!("implement `ChronoChain::sum`") + } } diff --git a/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo b/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo index f5dbe78a..b7f074e1 100644 --- a/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo +++ b/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo @@ -1,38 +1,248 @@ -use chrono_realms_time_tree::{ChronoChain, build_chrono_chain, sum_chain}; +use chrono_realms_time_tree::{ChronoChainTrait, ChronoChain}; +const U32_MAX: u32 = 0xFFFFFFFF; + +// Test for building a ChronoChain from an empty array +#[test] +fn test_empty_array() { + let chrono_chain = ChronoChainTrait::build(array![]); + + // The resulting chain should only contain "End" + match chrono_chain { + ChronoChain::End => (), + _ => panic!("Expected ChronoChain to be End for an empty array"), + } +} + +// Test for building a ChronoChain from a single element +#[test] +fn test_single_element_array() { + let chrono_chain = ChronoChainTrait::build(array![42]); + + // The first link should have value 42, and the next should be "End" + match chrono_chain { + ChronoChain::Link(( + value, next, + )) => { + assert_eq!(value, 42); + match next.unbox() { + ChronoChain::End => (), + _ => panic!("Expected next to be End"), + } + }, + _ => panic!("Expected ChronoChain to be Link for a single element array"), + } +} + +// Test for building a ChronoChain from multiple elements +#[test] +fn test_multiple_elements_array() { + let chrono_chain = ChronoChainTrait::build(array![1, 2, 3]); + + // The first link should have value 1, the second should have value 2, and the last should be + // "End" + match chrono_chain { + ChronoChain::Link(( + value, next, + )) => { + assert_eq!(value, 1); + match next.unbox() { + ChronoChain::Link(( + value, next, + )) => { + assert_eq!(value, 2); + match next.unbox() { + ChronoChain::Link(( + value, next, + )) => { + assert_eq!(value, 3); + match next.unbox() { + ChronoChain::End => (), + _ => panic!("Expected next to be End after the last link"), + } + }, + _ => panic!("Expected second link to be Link"), + } + }, + _ => panic!("Expected third link to be Link"), + } + }, + _ => panic!("Expected ChronoChain to be Link for multiple elements"), + } +} + +// Test for building a ChronoChain with duplicate values #[test] -fn test_build_chrono_chain() { - let chrono_chain = build_chrono_chain(array![10, 20, 30]); - // Verify the structure of the chain - if let ChronoChain::Link((first, next)) = chrono_chain.unbox() { - assert_eq!(first, 10); +fn test_duplicate_values_array() { + let chrono_chain = ChronoChainTrait::build(array![5, 5, 5]); + + // The chain should contain three links, all with value 5 + match chrono_chain { + ChronoChain::Link(( + value, next, + )) => { + assert_eq!(value, 5); + match next.unbox() { + ChronoChain::Link(( + value, next, + )) => { + assert_eq!(value, 5); + match next.unbox() { + ChronoChain::Link(( + value, next, + )) => { + assert_eq!(value, 5); + match next.unbox() { + ChronoChain::End => (), + _ => panic!("Expected next to be End after the last link"), + } + }, + _ => panic!("Expected third link to be Link"), + } + }, + _ => panic!("Expected second link to be Link"), + } + }, + _ => panic!("Expected ChronoChain to be Link for duplicate values"), + } +} - if let ChronoChain::Link((second, next)) = next.unbox() { - assert_eq!(second, 20); - if let ChronoChain::Link((third, next)) = next.unbox() { - assert_eq!(third, 30); +// Test for building a ChronoChain from large values +#[test] +fn test_large_values_array() { + let chrono_chain = ChronoChainTrait::build(array![U32_MAX, U32_MAX]); - if let ChronoChain::Link(_) = next.unbox() { - panic!("Expected 4th elements to be ChronoChain::End"); - } + // The first link should have value U32_MAX, and the second should also have value U32_MAX, + // followed by "End" + match chrono_chain { + ChronoChain::Link(( + value, next, + )) => { + assert_eq!(value, U32_MAX); + match next.unbox() { + ChronoChain::Link(( + value, next, + )) => { + assert_eq!(value, U32_MAX); + match next.unbox() { + ChronoChain::End => (), + _ => panic!("Expected next to be End after the last link"), + } + }, + _ => panic!("Expected second link to be Link"), } - } + }, + _ => panic!("Expected ChronoChain to be Link for large values"), + } +} + +// Test for building a ChronoChain from a large array of values +#[test] +fn test_large_array() { + let mut chrono_chain = ChronoChainTrait::build(array_in_range((1..1000))); + + // The sum of numbers 1 + 2 + ... + 999 is 999 * (999 + 1) / 2 = 499500 + let mut count = 1; + while let ChronoChain::Link((value, next)) = chrono_chain { + assert_eq!(value, count); + count += 1; + chrono_chain = next.unbox(); + }; + + // Verify the chrono_chain ends correctly + match chrono_chain { + ChronoChain::End => (), + _ => panic!("Expected ChronoChain to be End at the end of the chain"), } } +// Test for summing the values in a ChronoChain #[test] fn test_sum_chain() { - let chrono_chain = build_chrono_chain(array![10, 20, 30]); - let total_sum = sum_chain(@chrono_chain.unbox()); - assert_eq!(total_sum, 60); // 10 + 20 + 30 = 60 + let chrono_chain = ChronoChainTrait::build(array![1, 2, 3]); + + // Test that the sum of values is 6 (1 + 2 + 3) + let sum = chrono_chain.sum(); + assert_eq!(sum, 6); } +// Test for an empty ChronoChain (only End) #[test] fn test_empty_chain() { - // Empty chain should sum to 0 - let empty_chain = BoxTrait::new(ChronoChain::End); - let total_sum = sum_chain(@empty_chain.unbox()); - assert_eq!(total_sum, 0); + let chrono_chain = ChronoChainTrait::build(array![]); + + // Test that the sum of an empty chain is 0 + let sum = chrono_chain.sum(); + assert_eq!(sum, 0); +} + +// Test for a chain with only one value +#[test] +fn test_single_link_chain() { + let chrono_chain = ChronoChainTrait::build(array![5]); + + // Test that the sum of the chain with one value is 5 + let sum = chrono_chain.sum(); + assert_eq!(sum, 5); +} + +// Test for a chain with two values +#[test] +fn test_two_link_chain() { + let chrono_chain = ChronoChainTrait::build(array![3, 7]); + + // Test that the sum of the chain with values 3 and 7 is 10 (3 + 7) + let sum = chrono_chain.sum(); + assert_eq!(sum, 10); +} + +// Test for the chain having a large number of elements +#[test] +fn test_large_chain() { + let chrono_chain = ChronoChainTrait::build(array![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + + // The sum of 1 to 10 is 55 (1 + 2 + ... + 10) + let sum = chrono_chain.sum(); + assert_eq!(sum, 55); +} + +// Test for chain with large values +#[test] +fn test_large_values_in_chain() { + let chrono_chain = ChronoChainTrait::build(array![U32_MAX, U32_MAX]); + + // The sum of two `U32_MAX` values should be 2 * U32_MAX + let expected_sum: u64 = U32_MAX.into() * 2; + let sum = chrono_chain.sum(); + assert_eq!(sum, expected_sum); +} + +// Test for chain with all elements being zero +#[test] +fn test_zero_values_in_chain() { + let chrono_chain = ChronoChainTrait::build(array![0, 0, 0, 0, 0]); + + // The sum of zeros should be 0 + let sum = chrono_chain.sum(); + assert_eq!(sum, 0); } +// Test for chain with a very large number of elements +#[test] +fn test_very_large_chain() { + let chrono_chain = ChronoChainTrait::build(array_in_range((1..1000))); + + // The sum of values 1 + 2 + ... + 999 should be 999 * (999 + 1) / 2 = 499500 + let expected_sum = 999 * (999 + 1) / 2; + let sum = chrono_chain.sum(); + assert_eq!(sum, expected_sum); +} + +fn array_in_range(range: core::ops::Range) -> Array { + let mut arr = array![]; + for elem in range { + arr.append(elem); + }; + arr +} From 0128d8a7624a3628fd582d3b15ba08785ea71afb Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 22:56:35 +0100 Subject: [PATCH 12/17] Update config.json prerequisites --- config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.json b/config.json index 574ec5e8..d38fd03f 100644 --- a/config.json +++ b/config.json @@ -268,7 +268,8 @@ "smart-pointers" ], "prerequisites": [ - "structs" + "traits", + "enums" ], "status": "wip" } From 55fead3a13465b811edcbaf4cc8cf2db31d03a99 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 23:02:24 +0100 Subject: [PATCH 13/17] delete redundant whitespace in links --- concepts/smart-pointers/links.json | 1 - 1 file changed, 1 deletion(-) diff --git a/concepts/smart-pointers/links.json b/concepts/smart-pointers/links.json index fa9411a8..743fa914 100644 --- a/concepts/smart-pointers/links.json +++ b/concepts/smart-pointers/links.json @@ -8,4 +8,3 @@ "description": "Nullable Use Case with Dictionaries" } ] - \ No newline at end of file From 5553a1b65ce3e9eb38b59936e0c4be91a8449520 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sat, 21 Dec 2024 23:03:01 +0100 Subject: [PATCH 14/17] ignore all non-first tests --- .../tests/chrono_realms_time_tree.cairo | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo b/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo index b7f074e1..0a7759f3 100644 --- a/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo +++ b/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo @@ -16,6 +16,7 @@ fn test_empty_array() { // Test for building a ChronoChain from a single element #[test] +#[ignore] fn test_single_element_array() { let chrono_chain = ChronoChainTrait::build(array![42]); @@ -36,6 +37,7 @@ fn test_single_element_array() { // Test for building a ChronoChain from multiple elements #[test] +#[ignore] fn test_multiple_elements_array() { let chrono_chain = ChronoChainTrait::build(array![1, 2, 3]); @@ -73,6 +75,7 @@ fn test_multiple_elements_array() { // Test for building a ChronoChain with duplicate values #[test] +#[ignore] fn test_duplicate_values_array() { let chrono_chain = ChronoChainTrait::build(array![5, 5, 5]); @@ -110,6 +113,7 @@ fn test_duplicate_values_array() { // Test for building a ChronoChain from large values #[test] +#[ignore] fn test_large_values_array() { let chrono_chain = ChronoChainTrait::build(array![U32_MAX, U32_MAX]); @@ -139,6 +143,7 @@ fn test_large_values_array() { // Test for building a ChronoChain from a large array of values #[test] +#[ignore] fn test_large_array() { let mut chrono_chain = ChronoChainTrait::build(array_in_range((1..1000))); @@ -159,6 +164,7 @@ fn test_large_array() { // Test for summing the values in a ChronoChain #[test] +#[ignore] fn test_sum_chain() { let chrono_chain = ChronoChainTrait::build(array![1, 2, 3]); @@ -169,6 +175,7 @@ fn test_sum_chain() { // Test for an empty ChronoChain (only End) #[test] +#[ignore] fn test_empty_chain() { let chrono_chain = ChronoChainTrait::build(array![]); @@ -179,6 +186,7 @@ fn test_empty_chain() { // Test for a chain with only one value #[test] +#[ignore] fn test_single_link_chain() { let chrono_chain = ChronoChainTrait::build(array![5]); @@ -189,6 +197,7 @@ fn test_single_link_chain() { // Test for a chain with two values #[test] +#[ignore] fn test_two_link_chain() { let chrono_chain = ChronoChainTrait::build(array![3, 7]); @@ -199,6 +208,7 @@ fn test_two_link_chain() { // Test for the chain having a large number of elements #[test] +#[ignore] fn test_large_chain() { let chrono_chain = ChronoChainTrait::build(array![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); @@ -209,6 +219,7 @@ fn test_large_chain() { // Test for chain with large values #[test] +#[ignore] fn test_large_values_in_chain() { let chrono_chain = ChronoChainTrait::build(array![U32_MAX, U32_MAX]); @@ -220,6 +231,7 @@ fn test_large_values_in_chain() { // Test for chain with all elements being zero #[test] +#[ignore] fn test_zero_values_in_chain() { let chrono_chain = ChronoChainTrait::build(array![0, 0, 0, 0, 0]); @@ -230,6 +242,7 @@ fn test_zero_values_in_chain() { // Test for chain with a very large number of elements #[test] +#[ignore] fn test_very_large_chain() { let chrono_chain = ChronoChainTrait::build(array_in_range((1..1000))); From e25dea696e626702a0373afb436dadb53c760d97 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sun, 22 Dec 2024 15:00:03 +0100 Subject: [PATCH 15/17] remove redundant comments from tests --- .../tests/chrono_realms_time_tree.cairo | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo b/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo index 0a7759f3..b1e272d8 100644 --- a/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo +++ b/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo @@ -2,25 +2,21 @@ use chrono_realms_time_tree::{ChronoChainTrait, ChronoChain}; const U32_MAX: u32 = 0xFFFFFFFF; -// Test for building a ChronoChain from an empty array #[test] fn test_empty_array() { let chrono_chain = ChronoChainTrait::build(array![]); - // The resulting chain should only contain "End" match chrono_chain { ChronoChain::End => (), _ => panic!("Expected ChronoChain to be End for an empty array"), } } -// Test for building a ChronoChain from a single element #[test] #[ignore] fn test_single_element_array() { let chrono_chain = ChronoChainTrait::build(array![42]); - // The first link should have value 42, and the next should be "End" match chrono_chain { ChronoChain::Link(( value, next, @@ -35,14 +31,11 @@ fn test_single_element_array() { } } -// Test for building a ChronoChain from multiple elements #[test] #[ignore] fn test_multiple_elements_array() { let chrono_chain = ChronoChainTrait::build(array![1, 2, 3]); - // The first link should have value 1, the second should have value 2, and the last should be - // "End" match chrono_chain { ChronoChain::Link(( value, next, @@ -73,13 +66,11 @@ fn test_multiple_elements_array() { } } -// Test for building a ChronoChain with duplicate values #[test] #[ignore] fn test_duplicate_values_array() { let chrono_chain = ChronoChainTrait::build(array![5, 5, 5]); - // The chain should contain three links, all with value 5 match chrono_chain { ChronoChain::Link(( value, next, @@ -111,14 +102,11 @@ fn test_duplicate_values_array() { } -// Test for building a ChronoChain from large values #[test] #[ignore] fn test_large_values_array() { let chrono_chain = ChronoChainTrait::build(array![U32_MAX, U32_MAX]); - // The first link should have value U32_MAX, and the second should also have value U32_MAX, - // followed by "End" match chrono_chain { ChronoChain::Link(( value, next, @@ -141,13 +129,11 @@ fn test_large_values_array() { } } -// Test for building a ChronoChain from a large array of values #[test] #[ignore] fn test_large_array() { let mut chrono_chain = ChronoChainTrait::build(array_in_range((1..1000))); - // The sum of numbers 1 + 2 + ... + 999 is 999 * (999 + 1) / 2 = 499500 let mut count = 1; while let ChronoChain::Link((value, next)) = chrono_chain { assert_eq!(value, count); @@ -155,98 +141,81 @@ fn test_large_array() { chrono_chain = next.unbox(); }; - // Verify the chrono_chain ends correctly match chrono_chain { ChronoChain::End => (), _ => panic!("Expected ChronoChain to be End at the end of the chain"), } } -// Test for summing the values in a ChronoChain #[test] #[ignore] fn test_sum_chain() { let chrono_chain = ChronoChainTrait::build(array![1, 2, 3]); - // Test that the sum of values is 6 (1 + 2 + 3) let sum = chrono_chain.sum(); assert_eq!(sum, 6); } -// Test for an empty ChronoChain (only End) #[test] #[ignore] fn test_empty_chain() { let chrono_chain = ChronoChainTrait::build(array![]); - // Test that the sum of an empty chain is 0 let sum = chrono_chain.sum(); assert_eq!(sum, 0); } -// Test for a chain with only one value #[test] #[ignore] fn test_single_link_chain() { let chrono_chain = ChronoChainTrait::build(array![5]); - // Test that the sum of the chain with one value is 5 let sum = chrono_chain.sum(); assert_eq!(sum, 5); } -// Test for a chain with two values #[test] #[ignore] fn test_two_link_chain() { let chrono_chain = ChronoChainTrait::build(array![3, 7]); - // Test that the sum of the chain with values 3 and 7 is 10 (3 + 7) let sum = chrono_chain.sum(); assert_eq!(sum, 10); } -// Test for the chain having a large number of elements #[test] #[ignore] fn test_large_chain() { let chrono_chain = ChronoChainTrait::build(array![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); - // The sum of 1 to 10 is 55 (1 + 2 + ... + 10) let sum = chrono_chain.sum(); assert_eq!(sum, 55); } -// Test for chain with large values #[test] #[ignore] fn test_large_values_in_chain() { let chrono_chain = ChronoChainTrait::build(array![U32_MAX, U32_MAX]); - // The sum of two `U32_MAX` values should be 2 * U32_MAX let expected_sum: u64 = U32_MAX.into() * 2; let sum = chrono_chain.sum(); assert_eq!(sum, expected_sum); } -// Test for chain with all elements being zero #[test] #[ignore] fn test_zero_values_in_chain() { let chrono_chain = ChronoChainTrait::build(array![0, 0, 0, 0, 0]); - // The sum of zeros should be 0 let sum = chrono_chain.sum(); assert_eq!(sum, 0); } -// Test for chain with a very large number of elements #[test] #[ignore] fn test_very_large_chain() { let chrono_chain = ChronoChainTrait::build(array_in_range((1..1000))); - // The sum of values 1 + 2 + ... + 999 should be 999 * (999 + 1) / 2 = 499500 let expected_sum = 999 * (999 + 1) / 2; let sum = chrono_chain.sum(); assert_eq!(sum, expected_sum); From f5a6f931815d82d07d0ddbcad1c521803951e2a4 Mon Sep 17 00:00:00 2001 From: Nenad Date: Sun, 22 Dec 2024 17:07:57 +0100 Subject: [PATCH 16/17] turn time-tree into chrono-chain --- config.json | 6 +++--- .../.docs/hints.md | 0 .../.docs/instructions.md | 0 .../.docs/introduction.md | 0 .../.meta/config.json | 2 +- .../.meta/design.md | 0 .../.meta/exemplar.cairo | 0 .../Scarb.toml | 2 +- .../src/lib.cairo | 0 .../tests/chrono_realms_chrono_chain.cairo} | 2 +- 10 files changed, 6 insertions(+), 6 deletions(-) rename exercises/concept/{chrono-realms-time-tree => chrono-realms-chrono-chain}/.docs/hints.md (100%) rename exercises/concept/{chrono-realms-time-tree => chrono-realms-chrono-chain}/.docs/instructions.md (100%) rename exercises/concept/{chrono-realms-time-tree => chrono-realms-chrono-chain}/.docs/introduction.md (100%) rename exercises/concept/{chrono-realms-time-tree => chrono-realms-chrono-chain}/.meta/config.json (86%) rename exercises/concept/{chrono-realms-time-tree => chrono-realms-chrono-chain}/.meta/design.md (100%) rename exercises/concept/{chrono-realms-time-tree => chrono-realms-chrono-chain}/.meta/exemplar.cairo (100%) rename exercises/concept/{chrono-realms-time-tree => chrono-realms-chrono-chain}/Scarb.toml (71%) rename exercises/concept/{chrono-realms-time-tree => chrono-realms-chrono-chain}/src/lib.cairo (100%) rename exercises/concept/{chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo => chrono-realms-chrono-chain/tests/chrono_realms_chrono_chain.cairo} (98%) diff --git a/config.json b/config.json index d38fd03f..02009822 100644 --- a/config.json +++ b/config.json @@ -261,9 +261,9 @@ "status": "wip" }, { - "slug": "chrono-realms-time-tree", - "name": "Chrono Realms Time Tree", - "uuid": "a72139a1-825e-4349-a6b5-400b665fbe07", + "slug": "chrono-realms-chrono-chain", + "name": "Chrono Realms Chrono Chain", + "uuid": "e04f808a-25dc-4448-bc45-d3da0db9819a", "concepts": [ "smart-pointers" ], diff --git a/exercises/concept/chrono-realms-time-tree/.docs/hints.md b/exercises/concept/chrono-realms-chrono-chain/.docs/hints.md similarity index 100% rename from exercises/concept/chrono-realms-time-tree/.docs/hints.md rename to exercises/concept/chrono-realms-chrono-chain/.docs/hints.md diff --git a/exercises/concept/chrono-realms-time-tree/.docs/instructions.md b/exercises/concept/chrono-realms-chrono-chain/.docs/instructions.md similarity index 100% rename from exercises/concept/chrono-realms-time-tree/.docs/instructions.md rename to exercises/concept/chrono-realms-chrono-chain/.docs/instructions.md diff --git a/exercises/concept/chrono-realms-time-tree/.docs/introduction.md b/exercises/concept/chrono-realms-chrono-chain/.docs/introduction.md similarity index 100% rename from exercises/concept/chrono-realms-time-tree/.docs/introduction.md rename to exercises/concept/chrono-realms-chrono-chain/.docs/introduction.md diff --git a/exercises/concept/chrono-realms-time-tree/.meta/config.json b/exercises/concept/chrono-realms-chrono-chain/.meta/config.json similarity index 86% rename from exercises/concept/chrono-realms-time-tree/.meta/config.json rename to exercises/concept/chrono-realms-chrono-chain/.meta/config.json index 45eb47f3..8d9e967a 100644 --- a/exercises/concept/chrono-realms-time-tree/.meta/config.json +++ b/exercises/concept/chrono-realms-chrono-chain/.meta/config.json @@ -7,7 +7,7 @@ "src/lib.cairo" ], "test": [ - "tests/chrono_realms_time_tree.cairo" + "tests/chrono_realms_chrono_chain.cairo" ], "exemplar": [ ".meta/exemplar.cairo" diff --git a/exercises/concept/chrono-realms-time-tree/.meta/design.md b/exercises/concept/chrono-realms-chrono-chain/.meta/design.md similarity index 100% rename from exercises/concept/chrono-realms-time-tree/.meta/design.md rename to exercises/concept/chrono-realms-chrono-chain/.meta/design.md diff --git a/exercises/concept/chrono-realms-time-tree/.meta/exemplar.cairo b/exercises/concept/chrono-realms-chrono-chain/.meta/exemplar.cairo similarity index 100% rename from exercises/concept/chrono-realms-time-tree/.meta/exemplar.cairo rename to exercises/concept/chrono-realms-chrono-chain/.meta/exemplar.cairo diff --git a/exercises/concept/chrono-realms-time-tree/Scarb.toml b/exercises/concept/chrono-realms-chrono-chain/Scarb.toml similarity index 71% rename from exercises/concept/chrono-realms-time-tree/Scarb.toml rename to exercises/concept/chrono-realms-chrono-chain/Scarb.toml index 8865ffcb..e5af8176 100644 --- a/exercises/concept/chrono-realms-time-tree/Scarb.toml +++ b/exercises/concept/chrono-realms-chrono-chain/Scarb.toml @@ -1,5 +1,5 @@ [package] -name = "chrono_realms_time_tree" +name = "chrono_realms_chrono_chain" version = "0.1.0" edition = "2024_07" diff --git a/exercises/concept/chrono-realms-time-tree/src/lib.cairo b/exercises/concept/chrono-realms-chrono-chain/src/lib.cairo similarity index 100% rename from exercises/concept/chrono-realms-time-tree/src/lib.cairo rename to exercises/concept/chrono-realms-chrono-chain/src/lib.cairo diff --git a/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo b/exercises/concept/chrono-realms-chrono-chain/tests/chrono_realms_chrono_chain.cairo similarity index 98% rename from exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo rename to exercises/concept/chrono-realms-chrono-chain/tests/chrono_realms_chrono_chain.cairo index b1e272d8..05bad3cd 100644 --- a/exercises/concept/chrono-realms-time-tree/tests/chrono_realms_time_tree.cairo +++ b/exercises/concept/chrono-realms-chrono-chain/tests/chrono_realms_chrono_chain.cairo @@ -1,4 +1,4 @@ -use chrono_realms_time_tree::{ChronoChainTrait, ChronoChain}; +use chrono_realms_chrono_chain::{ChronoChainTrait, ChronoChain}; const U32_MAX: u32 = 0xFFFFFFFF; From e99b9baa7dc65e0dfbdd48fd8bb46755fe7bfc6a Mon Sep 17 00:00:00 2001 From: Nenad Date: Sun, 22 Dec 2024 17:17:57 +0100 Subject: [PATCH 17/17] remove test_ from test names --- .../tests/chrono_realms_chrono_chain.cairo | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/exercises/concept/chrono-realms-chrono-chain/tests/chrono_realms_chrono_chain.cairo b/exercises/concept/chrono-realms-chrono-chain/tests/chrono_realms_chrono_chain.cairo index 05bad3cd..5ccb740a 100644 --- a/exercises/concept/chrono-realms-chrono-chain/tests/chrono_realms_chrono_chain.cairo +++ b/exercises/concept/chrono-realms-chrono-chain/tests/chrono_realms_chrono_chain.cairo @@ -3,7 +3,7 @@ use chrono_realms_chrono_chain::{ChronoChainTrait, ChronoChain}; const U32_MAX: u32 = 0xFFFFFFFF; #[test] -fn test_empty_array() { +fn build_empty_array() { let chrono_chain = ChronoChainTrait::build(array![]); match chrono_chain { @@ -14,7 +14,7 @@ fn test_empty_array() { #[test] #[ignore] -fn test_single_element_array() { +fn build_single_element_array() { let chrono_chain = ChronoChainTrait::build(array![42]); match chrono_chain { @@ -33,7 +33,7 @@ fn test_single_element_array() { #[test] #[ignore] -fn test_multiple_elements_array() { +fn build_multiple_elements_array() { let chrono_chain = ChronoChainTrait::build(array![1, 2, 3]); match chrono_chain { @@ -68,7 +68,7 @@ fn test_multiple_elements_array() { #[test] #[ignore] -fn test_duplicate_values_array() { +fn build_duplicate_values_array() { let chrono_chain = ChronoChainTrait::build(array![5, 5, 5]); match chrono_chain { @@ -104,7 +104,7 @@ fn test_duplicate_values_array() { #[test] #[ignore] -fn test_large_values_array() { +fn build_large_values_array() { let chrono_chain = ChronoChainTrait::build(array![U32_MAX, U32_MAX]); match chrono_chain { @@ -131,7 +131,7 @@ fn test_large_values_array() { #[test] #[ignore] -fn test_large_array() { +fn build_large_array() { let mut chrono_chain = ChronoChainTrait::build(array_in_range((1..1000))); let mut count = 1; @@ -149,7 +149,7 @@ fn test_large_array() { #[test] #[ignore] -fn test_sum_chain() { +fn sum_chain() { let chrono_chain = ChronoChainTrait::build(array![1, 2, 3]); let sum = chrono_chain.sum(); @@ -158,7 +158,7 @@ fn test_sum_chain() { #[test] #[ignore] -fn test_empty_chain() { +fn sum_empty_chain() { let chrono_chain = ChronoChainTrait::build(array![]); let sum = chrono_chain.sum(); @@ -167,7 +167,7 @@ fn test_empty_chain() { #[test] #[ignore] -fn test_single_link_chain() { +fn sum_single_link_chain() { let chrono_chain = ChronoChainTrait::build(array![5]); let sum = chrono_chain.sum(); @@ -176,7 +176,7 @@ fn test_single_link_chain() { #[test] #[ignore] -fn test_two_link_chain() { +fn sum_two_link_chain() { let chrono_chain = ChronoChainTrait::build(array![3, 7]); let sum = chrono_chain.sum(); @@ -185,7 +185,7 @@ fn test_two_link_chain() { #[test] #[ignore] -fn test_large_chain() { +fn sum_large_chain() { let chrono_chain = ChronoChainTrait::build(array![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); let sum = chrono_chain.sum(); @@ -194,7 +194,7 @@ fn test_large_chain() { #[test] #[ignore] -fn test_large_values_in_chain() { +fn sum_large_values_in_chain() { let chrono_chain = ChronoChainTrait::build(array![U32_MAX, U32_MAX]); let expected_sum: u64 = U32_MAX.into() * 2; @@ -204,7 +204,7 @@ fn test_large_values_in_chain() { #[test] #[ignore] -fn test_zero_values_in_chain() { +fn sum_zero_values_in_chain() { let chrono_chain = ChronoChainTrait::build(array![0, 0, 0, 0, 0]); let sum = chrono_chain.sum(); @@ -213,7 +213,7 @@ fn test_zero_values_in_chain() { #[test] #[ignore] -fn test_very_large_chain() { +fn sum_very_large_chain() { let chrono_chain = ChronoChainTrait::build(array_in_range((1..1000))); let expected_sum = 999 * (999 + 1) / 2;