-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhashassignment.cpp
141 lines (112 loc) · 3.22 KB
/
hashassignment.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* hashassignment.cpp
* An implementation of a specific
* hash set data structure for an assignment.
*/
#include <array>
#include <string>
#include <vector>
#include <iostream>
#include <optional>
class SpecificSet {
public:
template<typename ...T>
void process_input(T&&... args);
private:
int hash_key (const std::string&) const;
std::optional<int> search (const std::string&) const;
void insert_key (const std::string&);
void delete_key (const std::string&);
enum SlotStatus {
NEVER_USED,
TOMBSTONE,
OCCUPIED
};
struct Slot {
SlotStatus status = NEVER_USED;
std::string key = "";
};
static constexpr int NUM_SLOTS = 26;
std::array<Slot, NUM_SLOTS> slots;
};
int SpecificSet::hash_key(const std::string& key) const {
char last = std::tolower(key.back());
// Get the index of the character in the alphabet
int index = last - 'a';
return index;
}
std::optional<int>
SpecificSet::search(const std::string& key) const {
int index = hash_key(key);
std::optional<int> ret;
// No match if the hash hasn't been used
if (slots[index].status == NEVER_USED) {
return ret;
}
// Loop over the rest of the slots until
// a match is found.
for (int _ = 0; _ < NUM_SLOTS; ++_) {
const Slot& slot = slots[index];
if (slot.status == OCCUPIED && slot.key == key) {
ret = index;
break;
}
// Wrap around when reaching the end of the slots array.
index = (index + 1) % NUM_SLOTS;
}
return ret;
}
void SpecificSet::insert_key(const std::string& key) {
constexpr int MAX_KEY_SIZE = 10;
// Search for the key.
auto res = search(key);
bool found = res.has_value();
// Do nothing if the key is already in the array.
if (found || key.size() > MAX_KEY_SIZE) {
return;
}
int index = hash_key(key);
// Find the first unoccupied slot to store the key
for (int _ = 0; _ < NUM_SLOTS; ++_) {
Slot& slot = slots[index];
if (slot.status == NEVER_USED || slot.status == TOMBSTONE) {
slot.status = OCCUPIED;
slot.key = key;
return;
}
index = (index + 1) % NUM_SLOTS;
}
}
void SpecificSet::delete_key(const std::string& key) {
auto res = search(key);
bool found = res.has_value();
if (found) {
int index = res.value();
Slot& slot = slots[index];
slot.status = TOMBSTONE;
}
}
template<typename ...T>
void SpecificSet::process_input(T&&... args) {
std::vector<std::string> inputs({ args... });
for (const auto& input : inputs) {
// Take the first char as the operation, and the rest as the key
char first = input[0];
auto key = input.substr(1);
if (first == 'A') insert_key(key);
else if (first == 'D') delete_key(key);
}
for (const auto& slot : slots) {
if (slot.status == OCCUPIED) {
std::cout << slot.key << "\n";
}
}
}
int main() {
SpecificSet s;
s.process_input(
"Aapple",
"Aorange",
"Dapple",
"Astrawberry"
);
}