diff --git a/examples/cairo/scripts/fizzbuzz/.tool-versions b/examples/cairo/scripts/fizzbuzz/.tool-versions new file mode 100644 index 0000000..fb22047 --- /dev/null +++ b/examples/cairo/scripts/fizzbuzz/.tool-versions @@ -0,0 +1 @@ +scarb 2.11.2 diff --git a/examples/cairo/scripts/fizzbuzz/Scarb.lock b/examples/cairo/scripts/fizzbuzz/Scarb.lock new file mode 100644 index 0000000..1a04bb1 --- /dev/null +++ b/examples/cairo/scripts/fizzbuzz/Scarb.lock @@ -0,0 +1,6 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "fizzbuzz" +version = "0.1.0" diff --git a/examples/cairo/scripts/fizzbuzz/Scarb.toml b/examples/cairo/scripts/fizzbuzz/Scarb.toml new file mode 100644 index 0000000..cdc4735 --- /dev/null +++ b/examples/cairo/scripts/fizzbuzz/Scarb.toml @@ -0,0 +1,11 @@ +[package] +name = "fizzbuzz" +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" diff --git a/examples/cairo/scripts/fizzbuzz/src/fizz_buzz.cairo b/examples/cairo/scripts/fizzbuzz/src/fizz_buzz.cairo new file mode 100644 index 0000000..9142ba1 --- /dev/null +++ b/examples/cairo/scripts/fizzbuzz/src/fizz_buzz.cairo @@ -0,0 +1,32 @@ +use core::array::ArrayTrait; +use crate::utils::number_converter::u32_to_felt252; + +/// Implementation of the classic FizzBuzz problem. +/// Takes a number n and returns an array of strings from 1 to n, where: +/// - Numbers divisible by 3 are replaced with "Fizz" +/// - Numbers divisible by 5 are replaced with "Buzz" +/// - Numbers divisible by both 3 and 5 are replaced with "FizzBuzz" +/// - Otherwise, the number itself is included as a string +pub fn fizzbuzz(n: u32) -> Array { + let mut result: Array = ArrayTrait::new(); + let mut i: u32 = 1; + + loop { + if i % 3 == 0 && i % 5 == 0 { + result.append('FizzBuzz'); + } else if i % 3 == 0 { + result.append('Fizz'); + } else if i % 5 == 0 { + result.append('Buzz'); + } else { + // Convert integer to string representation using our utility function + result.append(u32_to_felt252(i)); + } + + i += 1; + if i > n { + break; + } + } + result +} diff --git a/examples/cairo/scripts/fizzbuzz/src/lib.cairo b/examples/cairo/scripts/fizzbuzz/src/lib.cairo new file mode 100644 index 0000000..58c2aa6 --- /dev/null +++ b/examples/cairo/scripts/fizzbuzz/src/lib.cairo @@ -0,0 +1,4 @@ +pub mod fizz_buzz; +pub mod utils { + pub mod number_converter; +} diff --git a/examples/cairo/scripts/fizzbuzz/src/utils/number_converter.cairo b/examples/cairo/scripts/fizzbuzz/src/utils/number_converter.cairo new file mode 100644 index 0000000..1c83dbd --- /dev/null +++ b/examples/cairo/scripts/fizzbuzz/src/utils/number_converter.cairo @@ -0,0 +1,59 @@ +/// Converts a u32 integer to its string representation as felt252. +/// This function works for any u32 value, not just small numbers. +pub fn u32_to_felt252(mut num: u32) -> felt252 { + // Handle 0 separately + if num == 0 { + return '0'; + } + + // For single-digit numbers (1-9), return the ASCII directly + if num < 10 { + return num.into() + '0'; + } + + // For multi-digit numbers, build the string from right to left + let mut reversed_digits: Array = ArrayTrait::new(); + + loop { + let digit = (num % 10).into() + '0'; + reversed_digits.append(digit); + num /= 10; + + if num == 0 { + break; + } + } + + // Convert the array of digits to a single felt252 string + let mut result: felt252 = 0; + + // Start from the end (least significant digit) and build the number + let len = reversed_digits.len(); + let mut i: usize = 0; + while i != len { + let index = len - i - 1; + let digit = *reversed_digits.at(index); + result = result * 256 + digit; // Shift left by 8 bits (1 byte) and add the next digit + i += 1; + } + + result +} + +/// Utility function to calculate base^exp +fn pow(base: felt252, exp: u32) -> felt252 { + if exp == 0 { + return 1; + } + + let mut result: felt252 = 1; + let mut i: u32 = 0; + let target = exp; + + while i != target { + result *= base; + i += 1; + } + + result +} diff --git a/examples/cairo/scripts/fizzbuzz/tests/test_fizzbuzz.cairo b/examples/cairo/scripts/fizzbuzz/tests/test_fizzbuzz.cairo new file mode 100644 index 0000000..6f42b5f --- /dev/null +++ b/examples/cairo/scripts/fizzbuzz/tests/test_fizzbuzz.cairo @@ -0,0 +1,39 @@ +use fizzbuzz::fizz_buzz; + +#[test] +fn fizzbuzz_test_n3() { + let mut result = fizz_buzz::fizzbuzz(3); + assert(*result[0] == '1', 'First element should be 1'); + assert(*result[1] == '2', 'Second element should be 2'); + assert(*result[2] == 'Fizz', 'Third element should be Fizz'); +} + +#[test] +fn fizzbuzz_test_n5() { + let result = fizz_buzz::fizzbuzz(5); + assert(*result[0] == '1', 'First element should be 1'); + assert(*result[1] == '2', 'Second element should be 2'); + assert(*result[2] == 'Fizz', 'Third element should be Fizz'); + assert(*result[3] == '4', 'Fourth element should be 4'); + assert(*result[4] == 'Buzz', 'Fifth element should be Buzz'); +} + +#[test] +fn fizzbuzz_test_n15() { + let result = fizz_buzz::fizzbuzz(15); + assert(*result[0] == '1', 'Element at index 0'); + assert(*result[1] == '2', 'Element at index 1'); + assert(*result[2] == 'Fizz', 'Element at index 2'); + assert(*result[3] == '4', 'Element at index 3'); + assert(*result[4] == 'Buzz', 'Element at index 4'); + assert(*result[5] == 'Fizz', 'Element at index 5'); + assert(*result[6] == '7', 'Element at index 6'); + assert(*result[7] == '8', 'Element at index 7'); + assert(*result[8] == 'Fizz', 'Element at index 8'); + assert(*result[9] == 'Buzz', 'Element at index 9'); + assert(*result[10] == '11', 'Element at index 10'); + assert(*result[11] == 'Fizz', 'Element at index 11'); + assert(*result[12] == '13', 'Element at index 12'); + assert(*result[13] == '14', 'Element at index 13'); + assert(*result[14] == 'FizzBuzz', 'Element at index 14'); +} diff --git a/examples/cairo/scripts/search_insert_position/Scarb.lock b/examples/cairo/scripts/search_insert_position/Scarb.lock new file mode 100644 index 0000000..5beae69 --- /dev/null +++ b/examples/cairo/scripts/search_insert_position/Scarb.lock @@ -0,0 +1,6 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "search_insert_position" +version = "0.1.0" diff --git a/examples/cairo/scripts/search_insert_position/Scarb.toml b/examples/cairo/scripts/search_insert_position/Scarb.toml new file mode 100644 index 0000000..9970964 --- /dev/null +++ b/examples/cairo/scripts/search_insert_position/Scarb.toml @@ -0,0 +1,11 @@ +[package] +name = "search_insert_position" +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" diff --git a/examples/cairo/scripts/search_insert_position/src/lib.cairo b/examples/cairo/scripts/search_insert_position/src/lib.cairo new file mode 100644 index 0000000..f08a096 --- /dev/null +++ b/examples/cairo/scripts/search_insert_position/src/lib.cairo @@ -0,0 +1 @@ +pub mod search_insert_position; diff --git a/examples/cairo/scripts/search_insert_position/src/search_insert_position.cairo b/examples/cairo/scripts/search_insert_position/src/search_insert_position.cairo new file mode 100644 index 0000000..a5d39e2 --- /dev/null +++ b/examples/cairo/scripts/search_insert_position/src/search_insert_position.cairo @@ -0,0 +1,31 @@ +/// Finds the index of `target` in a sorted array `nums`. +/// If `target` is not present, returns the index where it would be inserted. +/// +/// # Arguments +/// +/// * `nums` - A sorted array of distinct integers +/// * `target` - The value to search for +/// +/// # Returns +/// +/// * The index of `target` in `nums` if found, or the index where it would be inserted +pub fn search_insert_pos(nums: @Array, target: u32) -> u32 { + if nums.len() == 0 { + return 0; // Empty array case + } + + let mut left: u32 = 0; + let mut right: u32 = nums.len(); + + // Binary search with a more efficient condition + while left != right { + let mid = left + (right - left) / 2; + + if *nums.at(mid) < target { + left = mid + 1; // Search in right half + } else { + right = mid; // Search in left half or target found + } + } + left +} diff --git a/examples/cairo/scripts/search_insert_position/tests/test_search_insert_position.cairo b/examples/cairo/scripts/search_insert_position/tests/test_search_insert_position.cairo new file mode 100644 index 0000000..382a7cc --- /dev/null +++ b/examples/cairo/scripts/search_insert_position/tests/test_search_insert_position.cairo @@ -0,0 +1,80 @@ +use search_insert_position::search_insert_position::search_insert_pos; + +#[test] +fn test_target_found() { + let nums = array![1, 3, 5, 6]; + let target = 5; + assert(search_insert_pos(@nums, target) == 2, 'Target 5 should be at index 2'); +} + +#[test] +fn test_target_not_found_middle() { + let nums = array![1, 3, 5, 6]; + let target = 2; + assert(search_insert_pos(@nums, target) == 1, 'Target 2 should insert at 1'); +} + +#[test] +fn test_target_smaller_than_all() { + let nums = array![1, 3, 5, 6]; + let target = 0; + assert(search_insert_pos(@nums, target) == 0, 'Target 0 should insert at 0'); +} + +#[test] +fn test_target_larger_than_all() { + let nums = array![1, 3, 5, 6]; + let target = 7; + assert(search_insert_pos(@nums, target) == 4, 'Target 7 should insert at 4'); +} + +#[test] +fn test_empty_array() { + let nums = array![]; + let target = 5; + assert(search_insert_pos(@nums, target) == 0, 'Empty array should return 0'); +} + +#[test] +fn test_single_element() { + let nums = array![1]; + let target = 2; + assert(search_insert_pos(@nums, target) == 1, 'Target 2 after single elem 1'); +} + +#[test] +fn test_single_element_found() { + let nums = array![5]; + let target = 5; + assert(search_insert_pos(@nums, target) == 0, 'Target 5 equals single elem'); +} + +#[test] +fn test_single_element_smaller() { + let nums = array![5]; + let target = 3; + assert(search_insert_pos(@nums, target) == 0, 'Target 3 before single elem 5'); +} + +#[test] +fn test_large_array() { + let nums = array![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]; + let target = 10; + assert(search_insert_pos(@nums, target) == 5, 'Target 10 in large array'); +} + +#[test] +fn test_edge_case_MAX() { + // Testing with u32::max value + let nums = array![1, 3, 5, 7]; + let target = 4294967295_u32; // u32::MAX + assert(search_insert_pos(@nums, target) == 4, 'u32::MAX should insert at end'); +} + +#[test] +fn test_edge_case_MIN() { + // Testing with u32::min value + let nums = array![1, 3, 5, 7]; + let target = 0_u32; // u32::MIN + assert(search_insert_pos(@nums, target) == 0, 'u32::MIN should insert at start'); +}