Generated: 2026-02-15T23:51:12.561669
/* Simple hash map implementation - fundamental data structure */
#include <stdlib.h>
#include <string.h>
#define HASHMAP_INITIAL_CAPACITY 16
typedef struct HashMapEntry {
char* key;
void* value;
struct HashMapEntry* next;
} HashMapEntry;
typedef struct {
HashMapEntry** buckets;
size_t capacity;
size_t size;
} HashMap;
/**
* Simple hash function (djb2)
*/
static unsigned long hash_string(const char* str) {
unsigned long hash = 5381;
int c;
while ((c = *str++)) {
hash = ((hash << 5) + hash) + c;
}
return hash;
}
/**
* Create a new hash map
*/
HashMap* hashmap_new(void) {
HashMap* map = (HashMap*)malloc(sizeof(HashMap));
if (!map) return NULL;
map->capacity = HASHMAP_INITIAL_CAPACITY;
map->size = 0;
map->buckets = (HashMapEntry**)calloc(map->capacity, sizeof(HashMapEntry*));
if (!map->buckets) {
free(map);
return NULL;
}
return map;
}
/**
* Insert or update a key-value pair
*/
int hashmap_put(HashMap* map, const char* key, void* value) {
if (!map || !key) return -1;
unsigned long hash = hash_string(key);
size_t index = hash % map->capacity;
// Check if key exists
HashMapEntry* entry = map->buckets[index];
while (entry) {
if (strcmp(entry->key, key) == 0) {
entry->value = value;
return 0;
}
entry = entry->next;
}
// Create new entry
HashMapEntry* new_entry = (HashMapEntry*)malloc(sizeof(HashMapEntry));
if (!new_entry) return -1;
new_entry->key = strdup(key);
if (!new_entry->key) {
free(new_entry);
return -1;
}
new_entry->value = value;
new_entry->next = map->buckets[index];
map->buckets[index] = new_entry;
map->size++;
return 0;
}
/**
* Get value for a key
*/
void* hashmap_get(HashMap* map, const char* key) {
if (!map || !key) return NULL;
unsigned long hash = hash_string(key);
size_t index = hash % map->capacity;
HashMapEntry* entry = map->buckets[index];
while (entry) {
if (strcmp(entry->key, key) == 0) {
return entry->value;
}
entry = entry->next;
}
return NULL;
}
/**
* Remove a key-value pair
*/
int hashmap_remove(HashMap* map, const char* key) {
if (!map || !key) return -1;
unsigned long hash = hash_string(key);
size_t index = hash % map->capacity;
HashMapEntry** indirect = &map->buckets[index];
HashMapEntry* entry = *indirect;
while (entry) {
if (strcmp(entry->key, key) == 0) {
*indirect = entry->next;
free(entry->key);
free(entry);
map->size--;
return 0;
}
indirect = &entry->next;
entry = entry->next;
}
return -1;
}
/**
* Free hash map and all entries
*/
void hashmap_free(HashMap* map) {
if (!map) return;
for (size_t i = 0; i < map->capacity; i++) {
HashMapEntry* entry = map->buckets[i];
while (entry) {
HashMapEntry* next = entry->next;
free(entry->key);
free(entry);
entry = next;
}
}
free(map->buckets);
free(map);
}
| Dimension | Score | Max | Details |
|---|---|---|---|
| Compilation | 25 | 25 | ✓ Compiles successfully |
| Safety | 20 | 20 | ✓ No unsafe blocks | ✓ Uses Result for error handling | ✓ Uses Option for nullable values | ✓ Smart pointer usage |
| Quality | 12 | 20 | ✓ Snake_case naming | ✓ Well documented (11 doc comments) | ✓ Proper type definitions |
| Correctness | 0 | 15 | No correctness indicators |
| Maintainability | 5 | 10 | ✓ Clear public API (9 items) | ✓ Uses constants |
| Performance | 10 | 10 | ✓ Minimal cloning | ✓ Reference usage |
✅ Compilation: PASSED
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
const HASHMAP_INITIAL_CAPACITY: usize = 16;
/// Entry in the hash map containing a key-value pair and a link to the next entry
struct HashMapEntry<T> {
key: String,
value: T,
next: Option<Box<HashMapEntry<T>>>,
}
/// Simple hash map implementation using separate chaining for collision resolution
pub struct HashMap<T> {
buckets: Vec<Option<Box<HashMapEntry<T>>>>,
capacity: usize,
size: usize,
}
impl<T> HashMap<T> {
/// Create a new hash map with initial capacity
pub fn new() -> Self {
let capacity = HASHMAP_INITIAL_CAPACITY;
let mut buckets = Vec::with_capacity(capacity);
for _ in 0..capacity {
buckets.push(None);
}
HashMap {
buckets,
capacity,
size: 0,
}
}
/// Simple hash function (djb2)
fn hash_string(s: &str) -> u64 {
let mut hash: u64 = 5381;
for c in s.bytes() {
hash = hash.wrapping_shl(5).wrapping_add(hash).wrapping_add(c as u64);
}
hash
}
/// Insert or update a key-value pair
pub fn put(&mut self, key: &str, value: T) -> Result<(), &'static str> {
let hash = Self::hash_string(key);
let index = (hash % self.capacity as u64) as usize;
// Check if key exists and update
let mut current = &mut self.buckets[index];
while let Some(entry) = current {
if entry.key == key {
entry.value = value;
return Ok(());
}
current = &mut entry.next;
}
// Create new entry at the beginning of the chain
let new_entry = Box::new(HashMapEntry {
key: key.to_string(),
value,
next: self.buckets[index].take(),
});
self.buckets[index] = Some(new_entry);
self.size += 1;
Ok(())
}
/// Get a reference to the value for a key
pub fn get(&self, key: &str) -> Option<&T> {
let hash = Self::hash_string(key);
let index = (hash % self.capacity as u64) as usize;
let mut current = &self.buckets[index];
while let Some(entry) = current {
if entry.key == key {
return Some(&entry.value);
}
current = &entry.next;
}
None
}
/// Get a mutable reference to the value for a key
pub fn get_mut(&mut self, key: &str) -> Option<&mut T> {
let hash = Self::hash_string(key);
let index = (hash % self.capacity as u64) as usize;
let mut current = &mut self.buckets[index];
while let Some(entry) = current {
if entry.key == key {
return Some(&mut entry.value);
}
current = &mut entry.next;
}
None
}
/// Remove a key-value pair, returning the value if it existed
pub fn remove(&mut self, key: &str) -> Result<T, &'static str> {
let hash = Self::hash_string(key);
let index = (hash % self.capacity as u64) as usize;
let mut current = &mut self.buckets[index];
while let Some(entry) = current {
if entry.key == key {
let mut removed_entry = current.take().unwrap();
*current = removed_entry.next.take();
self.size -= 1;
return Ok(removed_entry.value);
}
current = &mut entry.next;
}
Err("Key not found")
}
/// Get the number of entries in the map
pub fn size(&self) -> usize {
self.size
}
/// Get the capacity of the map
pub fn capacity(&self) -> usize {
self.capacity
}
/// Check if the map is empty
pub fn is_empty(&self) -> bool {
self.size == 0
}
}
impl<T> Default for HashMap<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Drop for HashMap<T> {
fn drop(&mut self) {
// Rust automatically cleans up all entries when buckets are dropped
}
}
| Dimension | Score | Max | Details |
|---|---|---|---|
| Compilation | 25 | 25 | ✓ Compiles successfully |
| Safety | 20 | 20 | ✓ No unsafe blocks | ✓ Uses Result for error handling | ✓ Uses Option for nullable values | ✓ Smart pointer usage |
| Quality | 14 | 20 | ✓ Snake_case naming | ✓ Well documented (8 doc comments) | ✓ Proper type definitions | ✓ Implementation blocks |
| Correctness | 3 | 15 | ✓ Pattern matching |
| Maintainability | 4 | 10 | ✓ Uses constants | ✓ Type aliases |
| Performance | 8 | 10 | ✓ Minimal cloning |
✅ Compilation: PASSED
use std::collections::hash_map::DefaultHasher;
use std::error::Error;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ptr;
const HASHMAP_INITIAL_CAPACITY: usize = 16;
#[derive(Debug)]
struct HashMapError(String);
impl fmt::Display for HashMapError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "HashMap Error: {}", self.0)
}
}
impl Error for HashMapError {}
type Result<T> = std::result::Result<T, HashMapError>;
#[derive(Debug)]
struct HashMapEntry<K, V> {
key: K,
value: V,
next: Option<Box<HashMapEntry<K, V>>>,
}
#[derive(Debug)]
struct HashMap<K, V> {
buckets: Vec<Option<Box<HashMapEntry<K, V>>>>,
capacity: usize,
size: usize,
}
impl<K, V> HashMap<K, V>
where
K: Eq + Hash + Clone,
{
/// Creates a new hash map with the initial capacity.
fn new() -> Self {
let capacity = HASHMAP_INITIAL_CAPACITY;
let buckets = vec![None; capacity];
HashMap {
buckets,
capacity,
size: 0,
}
}
/// Generates a hash value for the given key.
fn hash_string(key: &K) -> u64 {
let mut hasher = DefaultHasher::new();
key.hash(&mut hasher);
hasher.finish()
}
/// Inserts a key-value pair into the hash map.
fn put(&mut self, key: K, value: V) -> Result<()> {
let hash = Self::hash_string(&key);
let index = (hash % self.capacity as u64) as usize;
let bucket = &mut self.buckets[index];
match bucket {
Some(entry) => {
let mut current = entry;
loop {
if current.key == key {
current.value = value;
return Ok(());
}
match &mut current.next {
Some(next_entry) => {
current = next_entry;
}
None => {
break;
}
}
}
let new_entry = HashMapEntry {
key: key.clone(),
value,
next: None,
};
current.next = Some(Box::new(new_entry));
}
None => {
let new_entry = HashMapEntry {
key: key.clone(),
value,
next: None,
};
*bucket = Some(Box::new(new_entry));
}
}
self.size += 1;
Ok(())
}
/// Retrieves the value associated with the given key.
fn get(&self, key: &K) -> Option<&V> {
let hash = Self::hash_string(key);
let index = (hash % self.capacity as u64) as usize;
let bucket = &self.buckets[index];
match bucket {
Some(entry) => {
let mut current = entry;
loop {
if current.key == *key {
return Some(¤t.value);
}
match ¤t.next {
Some(next_entry) => {
current = next_entry;
}
None => {
return None;
}
}
}
}
None => None,
}
}
/// Removes a key-value pair from the hash map.
fn remove(&mut self, key: &K) -> Result<()> {
let hash = Self::hash_string(key);
let index = (hash % self.capacity as u64) as usize;
let bucket = &mut self.buckets[index];
match bucket {
Some(entry) => {
if entry.key == *key {
*bucket = entry.next.take();
self.size -= 1;
return Ok(());
} else {
let mut current = entry;
loop {
match &mut current.next {
Some(next_entry) => {
if next_entry.key == *key {
current.next = next_entry.next.take();
self.size -= 1;
return Ok(());
} else {
current = next_entry;
}
}
None => {
return Err(HashMapError("Key not found".to_string()));
}
}
}
}
}
None => Err(HashMapError("Key not found".to_string())),
}
}
/// Frees the hash map and all its entries.
fn free(&mut self) {
self.buckets.clear();
self.size = 0;
self.capacity = 0;
}
/// Returns the number of elements in the hash map.
fn len(&self) -> usize {
self.size
}
/// Returns if the hash map is empty
fn is_empty(&self) -> bool {
self.size == 0
}
}
| Model | Total | Compilation | Safety | Quality | Correctness | Maintainability | Performance |
|---|---|---|---|---|---|---|---|
| CLAUDE | 72/100 | 25/25 | 20/20 | 12/20 | 0/15 | 5/10 | 10/10 |
| GEMINI | 74/100 | 25/25 | 20/20 | 14/20 | 3/15 | 4/10 | 8/10 |
CELLO evaluates transpilation quality across 6 dimensions:
Total possible score: 100 points