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

Add Custom set exercise #18

Merged
merged 5 commits into from
Jun 24, 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
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
scarb 2.6.5
7 changes: 7 additions & 0 deletions concepts/operator-overload/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"blurb": "<todo>",
"authors": [
"misicnenad"
],
"contributors": []
}
1 change: 1 addition & 0 deletions concepts/operator-overload/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Operator Overload
1 change: 1 addition & 0 deletions concepts/operator-overload/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Introduction
1 change: 1 addition & 0 deletions concepts/operator-overload/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
7 changes: 7 additions & 0 deletions concepts/structs/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"blurb": "<todo>",
"authors": [
"misicnenad"
],
"contributors": []
}
1 change: 1 addition & 0 deletions concepts/structs/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Structs
1 change: 1 addition & 0 deletions concepts/structs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Introduction
1 change: 1 addition & 0 deletions concepts/structs/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
30 changes: 29 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,28 @@
"slug": "low-power-embedded-game",
"name": "low-power-embedded-game",
"uuid": "f3b7ce44-1667-42b4-b792-401d36aee2f1",
"practices": ["tuples", "traits", "control-flow"],
"practices": [
"tuples",
"traits"
],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "custom-set",
"name": "Custom Set",
"uuid": "aad80498-750c-4a7d-b82a-f52f90c54e11",
"practices": [
"structs",
"traits",
"operator-overload"
],
"prerequisites": [],
"difficulty": 4
}
],
"foregone": [
"hangman"
]
},
"concepts": [
Expand Down Expand Up @@ -164,6 +182,16 @@
"uuid": "fe83c9a6-cf50-47b1-9993-21ddd1e895ee",
"slug": "traits",
"name": "Traits"
},
{
"uuid": "4e1f6433-3125-4428-837d-47b0c10fddea",
"slug": "structs",
"name": "Structs"
},
{
"uuid": "0b069f59-f8b4-4979-935a-c3172538f4c9",
"slug": "operator-overload",
"name": "Operator Overload"
}
],
"key_features": [
Expand Down
7 changes: 7 additions & 0 deletions exercises/practice/custom-set/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Instructions

Create a custom set type.

Sometimes it is necessary to define a custom data structure of some type, like a set.
In this exercise you will define your own set.
How it works internally doesn't matter, as long as it behaves like a set of unique elements.
18 changes: 18 additions & 0 deletions exercises/practice/custom-set/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"authors": [
"misicnenad"
],
"files": {
"solution": [
"src/lib.cairo",
"Scarb.toml"
],
"test": [
"src/tests.cairo"
],
"example": [
".meta/example.cairo"
]
},
"blurb": "Create a custom set type."
}
175 changes: 175 additions & 0 deletions exercises/practice/custom-set/.meta/example.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
use core::clone::Clone;
use core::array::ArrayTrait;
use core::box::BoxTrait;

#[derive(Drop, Debug)]
pub struct CustomSet<T> {
pub collection: Array<T>,
}

pub impl CustomSetEq<
T, +Copy<T>, +Drop<T>, +PartialEq<T>, +core::fmt::Display<T>
> of PartialEq<CustomSet<T>> {
fn eq(lhs: @CustomSet<T>, rhs: @CustomSet<T>) -> bool {
if lhs.collection.len() != rhs.collection.len() {
return false;
}
lhs.is_subset(rhs) && rhs.is_subset(lhs)
}

fn ne(lhs: @CustomSet<T>, rhs: @CustomSet<T>) -> bool {
!(lhs == rhs)
}
}

#[generate_trait]
pub impl CustomSetImpl<
T, +Copy<T>, +Drop<T>, +core::fmt::Display<T>, +PartialEq<T>
> of CustomSetTrait<T> {
fn new(inputs: @Array<T>) -> CustomSet<T> {
let mut set = CustomSet::<T> { collection: array![], };
let mut i = 0;
while let Option::Some(val) = inputs
.get(i) {
let unboxed = val.unbox();
set.add(unboxed.clone());
i += 1;
};
set
}

fn add(ref self: CustomSet<T>, element: T) {
if !self.contains(@element) {
self.collection.append(element)
}
}

fn contains(self: @CustomSet<T>, other: @T) -> bool {
let mut is_contained = false;
let mut i = 0;
while let Option::Some(boxed) = self
.collection
.get(i) {
let val = boxed.unbox();
if val == other {
is_contained = true;
break;
}
i += 1;
};
is_contained
}

fn is_empty(self: @CustomSet<T>) -> bool {
self.collection.is_empty()
}

fn is_subset(self: @CustomSet<T>, other: @CustomSet<T>) -> bool {
if self.collection.len() > other.collection.len() {
return false;
}
let mut result = true;
let mut i = 0;
while let Option::Some(val) = self
.collection
.get(i) {
if !other.contains(val.unbox()) {
result = false;
break;
}
i += 1;
};
result
}

fn is_disjoint(self: @CustomSet<T>, other: @CustomSet<T>) -> bool {
let mut are_disjoint = true;

// a more efficient way is to iterate the smaller set
let mut to_iterate = self;
let mut to_compare = other;
if to_iterate.collection.len() > to_compare.collection.len() {
to_iterate = other;
to_compare = self;
};

let mut i = 0;
while let Option::Some(val) = to_iterate
.collection
.get(i) {
if to_compare.contains(val.unbox()) {
are_disjoint = false;
break;
}
i += 1;
};

are_disjoint
}

#[must_use]
fn intersection(self: @CustomSet<T>, other: @CustomSet<T>) -> CustomSet<T> {
let mut collection: Array<T> = array![];

// a more efficient way is to iterate the smaller set
let mut to_iterate = self;
let mut to_compare = other;
if to_iterate.collection.len() > to_compare.collection.len() {
to_iterate = other;
to_compare = self;
};

let mut i = 0;
while let Option::Some(val) = to_iterate
.collection
.get(i) {
let unboxed = val.unbox();
if to_compare.contains(unboxed) {
collection.append(*unboxed);
}
i += 1;
};

CustomSetImpl::<T>::new(@collection)
}

#[must_use]
fn union(self: @CustomSet<T>, other: @CustomSet<T>) -> CustomSet<T> {
let mut collection: Array<T> = array![];
let mut i = 0;
while let Option::Some(val) = self
.collection
.get(i) {
collection.append(*val.unbox());
i += 1;
};
i = 0;
while let Option::Some(val) = other
.collection
.get(i) {
collection.append(*val.unbox());
i += 1;
};
CustomSetImpl::<T>::new(@collection)
}

#[must_use]
fn difference(self: @CustomSet<T>, other: @CustomSet<T>) -> CustomSet<T> {
let mut collection: Array<T> = array![];
let mut i = 0;
while let Option::Some(val) = self
.collection
.get(i) {
let unboxed = val.unbox();
if !other.contains(unboxed) {
collection.append(unboxed.clone());
}
i += 1;
};
CustomSetImpl::<T>::new(@collection)
}
}


#[cfg(test)]
mod tests;
Loading
Loading