Skip to content
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 examples/cairo/scripts/remove_duplicates/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
1 change: 1 addition & 0 deletions examples/cairo/scripts/remove_duplicates/.tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
scarb 2.11.2
6 changes: 6 additions & 0 deletions examples/cairo/scripts/remove_duplicates/Scarb.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Code generated by scarb DO NOT EDIT.
version = 1

[[package]]
name = "remove_duplicates"
version = "0.1.0"
11 changes: 11 additions & 0 deletions examples/cairo/scripts/remove_duplicates/Scarb.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "remove_duplicates"
version = "0.1.0"
edition = "2024_07"

# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html

[dependencies]

[dev-dependencies]
cairo_test = "2.11.2"
1 change: 1 addition & 0 deletions examples/cairo/scripts/remove_duplicates/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod remove_duplicates;
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use core::array::ArrayTrait;

/// Removes duplicates from a sorted array and returns the number of unique elements.
///
/// # Arguments
/// * `ref nums` - A reference to the sorted array of integers to be modified
///
/// # Returns
/// * The number of unique elements in the array
///
/// # Cairo-specific considerations
/// Since Cairo arrays are immutable by design, this implementation simulates
/// in-place modification by creating a new array of unique elements and then
/// replacing the original array's content with these unique elements.
pub fn remove_duplicate(ref nums: Array<u32>) -> u32 {
if nums.len() == 0 {
return 0;
}

let mut unique_elements: Array<u32> = ArrayTrait::new();

unique_elements.append(*nums.at(0));

let mut i: u32 = 1;
while i < nums.len() {
if *nums.at(i) != *unique_elements.at(unique_elements.len() - 1) {
unique_elements.append(*nums.at(i));
}
i += 1;
}

let unique_count = unique_elements.len();

// Create a new empty array and replace nums with the unique elements
// This is a workaround since we can't directly modify the original array in Cairo
let mut result: Array<u32> = ArrayTrait::new();

let mut j: u32 = 0;
while j < unique_elements.len() {
result.append(*unique_elements.at(j));
j += 1;
}

loop {
match nums.pop_front() {
Option::Some(_) => {},
Option::None => { break; },
};
}

let mut k: u32 = 0;
while k < result.len() {
nums.append(*result.at(k));
k += 1;
}

unique_count
}

/// An alternative implementation that might be more gas-efficient
/// but doesn't simulate true in-place modification as in traditional languages.
pub fn remove_duplicates_optimized(ref nums: Array<u32>) -> u32 {
if nums.len() == 0 {
return 0;
}

let mut result: Array<u32> = ArrayTrait::new();
result.append(*nums.at(0));

let mut i: u32 = 1;
while i < nums.len() {
if *nums.at(i) != *result.at(result.len() - 1) {
result.append(*nums.at(i));
}
i += 1;
}

let unique_count = result.len();

loop {
match nums.pop_front() {
Option::Some(_) => {},
Option::None => { break; },
};
}

let mut j: u32 = 0;
while j < result.len() {
nums.append(*result.at(j));
j += 1;
}

unique_count
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// examples/cairo/scripts/remove_duplicate/tests/test_remove_duplicates.cairo

use core::array::ArrayTrait;
use remove_duplicates::remove_duplicates::{remove_duplicate, remove_duplicates_optimized};


#[test]
fn test_remove_duplicates_empty_array() {
let mut nums: Array<u32> = ArrayTrait::new();
let result = remove_duplicate(ref nums);
assert(result == 0, 'Should return 0 for empty array');
}

#[test]
fn test_remove_duplicates_no_duplicates() {
let mut nums: Array<u32> = ArrayTrait::new();
nums.append(1);
nums.append(2);
nums.append(3);

let result = remove_duplicate(ref nums);

assert(result == 3, 'Should return 3 unique elements');
assert(*nums.at(0) == 1, 'First element should be 1');
assert(*nums.at(1) == 2, 'Second element should be 2');
assert(*nums.at(2) == 3, 'Third element should be 3');
}

#[test]
fn test_remove_duplicates_example1() {
// Example 1: nums = [1,1,2]
let mut nums: Array<u32> = ArrayTrait::new();
nums.append(1);
nums.append(1);
nums.append(2);

let result = remove_duplicate(ref nums);

assert(result == 2, 'Should return 2 unique elements');
assert(*nums.at(0) == 1, 'First element should be 1');
assert(*nums.at(1) == 2, 'Second element should be 2');
}

#[test]
fn test_remove_duplicates_example2() {
// Example 2: nums = [0,0,1,1,1,2,2,3,3,4]
let mut nums: Array<u32> = ArrayTrait::new();
nums.append(0);
nums.append(0);
nums.append(1);
nums.append(1);
nums.append(1);
nums.append(2);
nums.append(2);
nums.append(3);
nums.append(3);
nums.append(4);

let result = remove_duplicate(ref nums);

assert(result == 5, 'Should return 5 unique elements');
assert(*nums.at(0) == 0, 'First element should be 0');
assert(*nums.at(1) == 1, 'Second element should be 1');
assert(*nums.at(2) == 2, 'Third element should be 2');
assert(*nums.at(3) == 3, 'Fourth element should be 3');
assert(*nums.at(4) == 4, 'Fifth element should be 4');
}

#[test]
fn test_remove_duplicates_all_duplicates() {
let mut nums: Array<u32> = ArrayTrait::new();
nums.append(1);
nums.append(1);
nums.append(1);
nums.append(1);

let result = remove_duplicate(ref nums);

assert(result == 1, 'Should return 1 unique element');
assert(*nums.at(0) == 1, 'First element should be 1');
}

// Tests for the optimized version
#[test]
fn test_remove_duplicates_optimized_example1() {
// Example 1: nums = [1,1,2]
let mut nums: Array<u32> = ArrayTrait::new();
nums.append(1);
nums.append(1);
nums.append(2);

let result = remove_duplicates_optimized(ref nums);

assert(result == 2, 'Should return 2 unique elements');
assert(*nums.at(0) == 1, 'First element should be 1');
assert(*nums.at(1) == 2, 'Second element should be 2');
}

#[test]
fn test_remove_duplicates_optimized_example2() {
// Example 2: nums = [0,0,1,1,1,2,2,3,3,4]
let mut nums: Array<u32> = ArrayTrait::new();
nums.append(0);
nums.append(0);
nums.append(1);
nums.append(1);
nums.append(1);
nums.append(2);
nums.append(2);
nums.append(3);
nums.append(3);
nums.append(4);

let result = remove_duplicates_optimized(ref nums);

assert(result == 5, 'Should return 5 unique elements');
assert(*nums.at(0) == 0, 'First element should be 0');
assert(*nums.at(1) == 1, 'Second element should be 1');
assert(*nums.at(2) == 2, 'Third element should be 2');
assert(*nums.at(3) == 3, 'Fourth element should be 3');
assert(*nums.at(4) == 4, 'Fifth element should be 4');
}
Loading