Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Module for detecting voter fraud using a hash table.
- Students need to complete the contains method for the VoterHashTable
- and then complete the fraud_detect_hash function
- """
- from classes import VoterList, VoterName
- from stats import StatCounter, HASH_TABLES_CREATED
- class VoterHashTable:
- """A chaining hash table to store VoterName objects.
- You should use the default hash function for VoterName objects as the basis for
- determining which slot items go/are in, eg, hash(my_voter_name)
- You should be able to add other objects when testing,
- as long as they are hashable with hash(my_testing_thing)...
- But make sure you test it with VoterName objects as this will let you compare
- your comparisons_used with the actual comparisons used.
- ************************************************************************
- ************************************************************************
- ****==== DON'T change any methods expcept the contains method!!! ===****
- ************************************************************************
- ************************************************************************
- """
- # class variables - used for keeping track of things
- _memory_used = 0
- def __init__(self, initial_size):
- """ Initialises a hash table with initial_size slots.
- The slots are basically stored as a list of VoterLists,
- which are intially empty.
- The performance counters are all set to zero.
- """
- self.number_of_slots = initial_size
- self.number_of_names = 0
- self.comparisons_used = 0
- self._data = []
- # setup the given number of slots, each containing an empty VoterList
- for _ in range(initial_size):
- self._data.append(VoterList())
- VoterHashTable._memory_used += initial_size
- StatCounter.increment(HASH_TABLES_CREATED)
- def add(self, voter_name):
- """ Takes a Votername object and adds it to the hash table,
- Does nothing if it's already in the table.
- Adds item to the list/chain at the appropriate index
- Note that this method does not count comparisons of Voternames directly,
- but the contains check will - you need to write contains
- so that it counts any comparisons that it does.
- """
- if not self.contains(voter_name):
- slot_index = hash(voter_name) % self.number_of_slots
- slot_list = self._data[slot_index]
- slot_list.append(voter_name)
- VoterHashTable._memory_used += 1
- self.number_of_names += 1
- def contains(self, voter_name):
- """ Returns True if the hash table contains the given voter_name.
- Make sure you update self.comparisons_used so that it counts
- any comparisons of VoterName objects.
- Hint: Which slot will voter_name be in if it's in the table?
- """
- # ---start student section---
- if self.getitem(hash(voter_name)) == voter_name:
- return True
- elif self.getitem(hash(voter_name)) == None:
- return False
- else:
- evac = 0
- hash_holder = hash(voter_name)
- while evac == 0:
- hash_holder += 1
- if self.getitem(hash_holder) == voter_name:
- evac = 1
- return True
- elif self.getitem(hash_holder) == None:
- evac = 1
- return False
- # ===end student section===
- def __repr__(self):
- """ This is rather ugly, you are better to do a print(my_hashtable)
- which will use the __str__ method to give more readable output.
- """
- return repr(self._data)
- def __str__(self):
- string_thing = 'VoterHashTable:\n'
- for slot_index, slot_list in enumerate(self._data):
- string_thing += f'{slot_index:6}: {repr(slot_list)}\n'
- string_thing += (f'Num of names = {self.number_of_names}\n')
- string_thing += (f'Num of slots = {self.number_of_slots}\n')
- string_thing += (f'Load factor = {self.load_factor():.2f}')
- return string_thing
- def __eq__(self, other):
- return self._data == other._data
- def __len__(self):
- return len(self._data)
- def __contains__(self, item):
- raise TypeError(
- "You can't use the 'in' keyword with a VoterHashTable")
- def load_factor(self):
- """ Returns the load factor for the hash table """
- return self.number_of_names / self.number_of_slots
- def index(self, start=None):
- """ Points out that we can't do this! """
- raise TypeError(f"{type(self)} doesn't allow using index")
- def __getitem__(self, i):
- return self._data[i]
- @classmethod
- def get_memory_used(cls):
- """ Returns the amount of memory used """
- return cls._memory_used
- @classmethod
- def reset_memory_used(cls):
- """ Resets the the memory tracker """
- cls._memory_used = 0
- def fraud_detect_hash(first_booth_voters, second_booth_voters, load_factor=0.5):
- """This function takes a VoterList from two voting booths and makes a list
- of voters that appear in both lists.
- The function should return two things:
- 1. A VoterList containing the fraudulent voters,
- 2. The number of comparisons that were used to find the fraudulent voters
- The hashtable is initialised such that adding the voters from the second booth
- will result in a load factor of approximately load_factor, with the
- default load_factor set to 0.5.
- That is, the table size is set to be int(len(second_booth_voters)/load_factor)
- **** NOTE: Remember to complete the VoterHashTable definition above!
- """
- table_size = int(len(second_booth_voters) / load_factor)
- voter_hash_table = VoterHashTable(table_size)
- fraudulent_voters = VoterList()
- # ---start student section---
- for voter_name in first_booth_voters:
- VoterHashTable.add(voter_name)
- for voter_2 in second_booth_voters:
- if VoterHashTable.contains(voter_2) == True:
- fraudulent_voters.append(voter_2)
- # ===end student section===
- comparisons = voter_hash_table.comparisons_used
- return fraudulent_voters, comparisons
- asd = VoterList()
- asd.append(VoterName('bob'))
- asd.append(VoterName('katylin'))
- asd.append(VoterName('harrison'))
- asd.append(VoterName('shaun'))
- fgh = VoterList()
- fgh.append(VoterName('bob'))
- fgh.append(VoterName('harrison'))
- fgh.append(VoterName('katylin'))
- fgh.append(VoterName('shaun'))
- print(fraud_detect_hash(asd, fgh))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement