generated from eigerco/beerus
-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
230 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// The Boyer-Moore string search algorithm | ||
use dict::Felt252DictTrait; | ||
|
||
// Find `pattern` in `text` and return the index of every match. | ||
/// * `text` - The text to search in. | ||
/// * `pattern` - The pattern to search for. | ||
/// # Returns | ||
/// * `Array<usize>` - The index of every match. | ||
fn bm_search(text: @ByteArray, pattern: @ByteArray) -> Array<usize> { | ||
let mut positions: Array<usize> = array![]; | ||
let n = text.len(); | ||
let m = pattern.len(); | ||
if n == 0 || m == 0 || m > n { | ||
return positions; | ||
} | ||
|
||
let mut collection = felt252_dict_new::<usize>(); | ||
let mut collect_id = 0; | ||
loop { | ||
if collect_id == m { | ||
break; | ||
} | ||
let c = pattern.at(collect_id).unwrap(); | ||
collection | ||
.insert( | ||
c.into(), collect_id + 1 | ||
); // avoid 0 since felt252_dict init every entry to 0 by default | ||
collect_id += 1; | ||
}; | ||
|
||
let mut shift: usize = 0; | ||
loop { | ||
if shift > n - m { | ||
break; | ||
} | ||
|
||
let mut j = m; | ||
loop { | ||
if j == 0 || @pattern.at(j - 1).unwrap() != @text.at(shift + j - 1).unwrap() { | ||
break; | ||
} | ||
j -= 1; | ||
}; | ||
if j == 0 { | ||
positions.append(shift); | ||
let add_to_shift = { | ||
if shift + m < n { | ||
let c = text.at(shift + m).unwrap(); | ||
let index = collection.get(c.into()); | ||
if index == 0 { | ||
m + 1 | ||
} else { | ||
m - index + 1 | ||
} | ||
} else { | ||
1 | ||
} | ||
}; | ||
shift += add_to_shift; | ||
} else { | ||
let c = text.at(shift + j - 1).unwrap(); | ||
let index = collection.get(c.into()); | ||
if j <= (index + 1) { | ||
shift += 1; | ||
} else { | ||
shift += j - index; | ||
} | ||
} | ||
}; | ||
|
||
positions | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
mod binary_search; | ||
mod bm_search; | ||
mod dijkstra; | ||
|
||
#[cfg(test)] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
mod binary_search_test; | ||
mod bm_search_test; | ||
mod dijkstra_test; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
use alexandria_searching::bm_search::bm_search; | ||
|
||
|
||
// Check if two arrays are equal. | ||
/// * `a` - The first array. | ||
/// * `b` - The second array. | ||
/// # Returns | ||
/// * `bool` - True if the arrays are equal, false otherwise. | ||
fn is_equal(mut a: Span<u32>, mut b: Span<u32>) -> bool { | ||
if a.len() != b.len() { | ||
return false; | ||
} | ||
loop { | ||
match a.pop_front() { | ||
Option::Some(val1) => { | ||
let val2 = b.pop_front().unwrap(); | ||
if *val1 != *val2 { | ||
break false; | ||
} | ||
}, | ||
Option::None => { break true; }, | ||
}; | ||
} | ||
} | ||
|
||
|
||
#[test] | ||
#[available_gas(5000000)] | ||
fn bm_search_test_1() { | ||
// AABCAB12AFAABCABFFEGABCAB -> 41,41,42,43,41,42,31,32,41,46,41,41,42,43,41,42,46,46,45,47,41,42,43,41,42 | ||
let mut text: ByteArray = Default::default(); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x43_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x31_u8); | ||
text.append_byte(0x32_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x46_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x43_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x46_u8); | ||
text.append_byte(0x46_u8); | ||
text.append_byte(0x45_u8); | ||
text.append_byte(0x47_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x43_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
// ABCAB -> 41,42,43,41,42 | ||
let mut pattern: ByteArray = Default::default(); | ||
pattern.append_byte(0x41_u8); | ||
pattern.append_byte(0x42_u8); | ||
pattern.append_byte(0x43_u8); | ||
pattern.append_byte(0x41_u8); | ||
pattern.append_byte(0x42_u8); | ||
|
||
let positions = bm_search(@text, @pattern); | ||
let ground_truth: Array<usize> = array![1, 11, 20]; | ||
assert(is_equal(positions.span(), ground_truth.span()), 'invalid result'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(5000000)] | ||
fn bm_search_test_2() { | ||
// AABCAB12AFAABCABFFEGABCAB -> 41,41,42,43,41,42,31,32,41,46,41,41,42,43,41,42,46,46,45,47,41,42,43,41,42 | ||
let mut text: ByteArray = Default::default(); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x43_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x31_u8); | ||
text.append_byte(0x32_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x46_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x43_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x46_u8); | ||
text.append_byte(0x46_u8); | ||
text.append_byte(0x45_u8); | ||
text.append_byte(0x47_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x43_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
// FFF -> 46,46,46 | ||
let mut pattern: ByteArray = Default::default(); | ||
pattern.append_byte(0x46_u8); | ||
pattern.append_byte(0x46_u8); | ||
pattern.append_byte(0x46_u8); | ||
|
||
let positions = bm_search(@text, @pattern); | ||
let ground_truth: Array<usize> = array![]; | ||
assert(is_equal(positions.span(), ground_truth.span()), 'invalid result'); | ||
} | ||
|
||
#[test] | ||
#[available_gas(5000000)] | ||
fn bm_search_test_3() { | ||
// AABCAB12AFAABCABFFEGABCAB -> 41,41,42,43,41,42,31,32,41,46,41,41,42,43,41,42,46,46,45,47,41,42,43,41,42 | ||
let mut text: ByteArray = Default::default(); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x43_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x31_u8); | ||
text.append_byte(0x32_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x46_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x43_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x46_u8); | ||
text.append_byte(0x46_u8); | ||
text.append_byte(0x45_u8); | ||
text.append_byte(0x47_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
text.append_byte(0x43_u8); | ||
text.append_byte(0x41_u8); | ||
text.append_byte(0x42_u8); | ||
// CAB -> 43,41,42 | ||
let mut pattern: ByteArray = Default::default(); | ||
pattern.append_byte(0x43_u8); | ||
pattern.append_byte(0x41_u8); | ||
pattern.append_byte(0x42_u8); | ||
|
||
let positions = bm_search(@text, @pattern); | ||
let ground_truth: Array<usize> = array![3, 13, 22]; | ||
assert(is_equal(positions.span(), ground_truth.span()), 'invalid result'); | ||
} |