-
Notifications
You must be signed in to change notification settings - Fork 72
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
Added hashtable and removed some of the warnings + trapezoidal method for function integration + bingo sort #66
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beautiful contributions! Thanks ❤️
Sorry about the late review, I have been super busy.
A few structural changes and this is good to go!
src/data_structures/hashtable.rs
Outdated
|
||
impl<K: Hashable + std::cmp::PartialEq, V> HashTable<K, V> { | ||
pub fn new() -> HashTable<K, V> { | ||
let initial_capacity = 3000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Extract to a constant. const INITIAL_CAPACITY: usize = 3000;
.
Why was this value chosen? std::collection::HashMap
has an initial capacity of 6
for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To minimize resizing for larger datasets.
src/data_structures/hashtable.rs
Outdated
} | ||
|
||
pub fn insert(&mut self, key: K, value: V) { | ||
if self.count >= self.elements.len() * 3 / 4 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Extract to a constant. const LOAD_FACTOR_BOUND: f32 = 0.75;
.
This will make this section a bit uglier because of the casts, but the constant will be explained. wdyt?
src/data_structures/hashtable.rs
Outdated
} | ||
|
||
fn resize(&mut self) { | ||
let new_size = self.elements.len() * 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Extract to a constant. const GROWTH_FACTOR: usize = 2;
.
#[allow(dead_code)] | ||
pub fn z_array<T: Eq>(input: &[T]) -> Vec<usize> { | ||
match_with_z_array(input, input, 1, false) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind exporting z_array
next to match_pattern
in src/string/mod.rs
instead?
Co-authored-by: Alexander González <[email protected]>
A Generic Hash Table Implementation
This code implements a generic hash table using the
std::collections::LinkedList
container. It supports the core operations of inserting and searching for keys.Implementation Overview
A hash table is a data structure that maps keys to values. It uses a hash function to assign each key to a unique bucket in the table. The hash table stores key-value pairs in the corresponding buckets, allowing for efficient insertion, searching, and updating of data.
This implementation uses a linked list to store key-value pairs for each bucket. The
HashTable
struct maintains a vector of these linked lists, where theelements
vector stores references to the linked lists. Thecount
member tracks the number of key-value pairs in the hash table.The
Hashable
trait defines a hash function for the keys used in the hash table. TheHashTable
struct provides two methods:insert(key: K, value: V)
: Inserts a key-value pair into the hash table. If the hash table is full, it resizes itself to accommodate more data.search(key: K) -> Option<&V>
: Searches for a key in the hash table and returns the corresponding value, orNone
if the key is not found.Load Factor and Automatic Resizing
The
resize
method doubles the size of the hash table when the load factor, which is the ratio ofcount
toelements.len()
, exceeds 0.75. This ensures that the hash table remains efficient as it grows.Key-Value Pair Storage
Each key-value pair is stored as a tuple of the key and value. The
HashTable
struct maintains a linked list of these tuples for each bucket. When a key is inserted, its hash value is calculated and used to determine the corresponding bucket. The key-value pair is then appended to the linked list at that bucket.Search Operation
The
search
method iterates over the linked list at the specified hash bucket index. It checks each tuple's key against the given search key. If a matching key is found, the corresponding value is returned. Otherwise,None
is returned.Test Coverage
The
test
module includes unit tests that cover various scenarios for the hash table implementation. These tests ensure that the hash table behaves as expected under different conditions, including inserting and searching for keys, resizing the hash table, and handling non-existent keys.Key Features
Generic hash table implementation: Supports arbitrary key types.
Automatic resizing: Handles increasing load factors without performance degradation.
Efficient insert and search operations: Provides fast insertion and search times.
Comprehensive test coverage: Ensures reliable and robust behavior.
Usage
To use the hash table, first define a type that implements the
Hashable
trait. Then, create a new hash table using thenew
method:Sleep Sort Implementation in Rust
This Rust code implements a sleep sort algorithm that simulates a sorting process using threads and delays. The algorithm takes a vector of integers as input and returns a sorted vector. It works by spawning multiple threads, each of which sleeps for a duration proportional to its assigned integer value. Smaller numbers take less time to sort than larger numbers, so the sorted elements are gradually collected from the threads and returned.
Code Example:
Description:
The
sleep_sort
function takes a vector of integers as input.It creates a channel using the
mpsc::channel()
function. This channel will be used to communicate between the main thread and the worker threads.It iterates over each element in the input vector using a for-each loop.
For each element, it clones the sender (tx) of the channel. This is necessary because each worker thread will need its own copy of the sender to send data to the receiver.
It spawns a new thread for each element in the vector using the
thread::spawn()
function.Inside the worker thread, it simulates a delay based on the value of the element. This is done by calling the
thread::sleep()
function with a duration that is proportional to the element's value. For example, an element with the value 1 will sleep for 20 milliseconds, an element with the value 2 will sleep for 40 milliseconds, and so on.After the delay, it sends the element to the receiver through the channel using the
tx.send()
method.Finally, it collects the sorted elements from the receiver into a vector and returns it.
Example Usage:
Trapezoidal Integral Implementation in Rust
This Rust code implements the trapezoidal rule for approximating the definite integral of a function f(x) between the limits x = a and x = b. The trapezoidal rule divides the interval between a and b into a specified number of trapezoids and approximates the integral as the sum of the areas of the trapezoids.
Code Example
Description
The
trapezoidal_integral
function takes four arguments:a
: The lower bound of the integration intervalb
: The upper bound of the integration intervalf
: A function of the formf(x)
that represents the integrandprecision
: The number of trapezoids to use in the approximationThe function first defines a helper function
core
that performs the actual calculations for a single trapezoid. Thecore
function takes the same four arguments as thetrapezoidal_integral
function and returns the area of a single trapezoid.The
trapezoidal_integral
function then calculates the sum of the areas of the trapezoids using a for loop. The loop iterates over the range of0..precision
, which represents the indices of the trapezoids. For each trapezoid, theleft_side
andright_size
variables are calculated as the left and right endpoints of the trapezoid, respectively. The area of the trapezoid is then calculated using the formula:0.5 * (f(left_side) + f(right_size)) * delta
where
delta
is the width of the trapezoid. The final step is to add the area of each trapezoid to the running sum and return the result.Usage
The
trapezoidal_integral
function can be used to approximate the definite integral of any functionf(x)
within a specified interval. For example, the following code approximates the integral of the functionx^2
from 0 to 1:Bingo Sort Implementation in Rust
The provided Rust code implements the bingo sort algorithm for sorting a vector of integers. The bingo sort algorithm repeatedly identifies and moves the "bingo" elements, which are elements that equal the current bingo value.
Empty Vector Check
Initializing Bingo Elements
bingo
andnext_bingo
, are initialized with the first two elements of the vector.Identifying Maximum and Minimum
max_min
function is called to identify the maximum and minimum elements in the vector.next_bingo
for later use.Tracking Largest Element
largest_element
variable is set tonext_bingo
, which is the current minimum element.Position of Next Element to Swap
next_element_pos
variable keeps track of the position of the next element to swap with the current bingo element.Sorting Loop
A loop iterates over the range of
bingo..=largest_element
, which represents the sequence of bingo elements.Inside the loop:
a. Initializing Start Position:
start_pos
variable is set to the currentnext_element_pos
to serve as the starting position for iterating on the current bingo element.b. Iterating on Remaining Elements
The loop iterates over the remaining elements in the vector starting from the
start_pos
position.Swapping Equal Elements:
i
equals the current bingo elementbingo
, then the elements at positionsi
andnext_element_pos
are swapped.Updating Next Bingo Element:
i
is less than the current bingo elementbingo
, then it indicates that a new bingo element has been found.next_bingo
variable is updated to the current element to prepare for the next iteration.Updating Bingo and Next Bingo Elements
After the loop completes, the current and next bingo elements are updated:
bingo
variable is updated to the currentnext_bingo
element.next_bingo
variable is reset to thelargest_element
to start the next iteration with the next bingo element.This iterative process continues until all bingo elements are sorted into their correct positions.