Brazilian Social Security Benefits - linear search
Tags: python, hashmap, linearsearch, codecademy
Published: 2022-06-03 12:59:48


There are a great deal of benefits provided by the Brazilian Social Security Agency. Each of them has its own set of requirements that it's challenging finding out whether one is entitled to it.
Regardless one's knowledge about legal affairs related to this matter, most people in Brazil have a common sense about these benefits. 
In order to help to figure out if one has the right to a given benefit, the program, written in Python3, intends to be a straightforward way to learn about its legal requirements.
For instance: if the user wants to learn what the requirements are to get a retirement pension ('aposentadoria' in Portuguese), all that one should do is typing few letters such as "apo".

![Searching retirement pensions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ju6m14snhhwsm6u3hiu2.png)

After confirming, the user can see all the eight(!) types of retirement pensions available and criteria that should be met.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jesxztzpfppvd4skaaxc.png)

## Hash Map algorithm

I chose a Hash Map data structure to organize the information  about the benefits.

A map relates two pieces of information where the inputs (called keys) have a single output (called value) only. There can't be more than one value per key.

In order to keep track of values (=requirements) in memory, an array was created, so each benefit (key) was given an index in the array by using a *hashing function*.

First of all, a `Hash Map` class[^1] was created to implement an array. Then, two methods to find out the indices (`hash` and `compressor`) and another one to assign the key-value pair to an index (`assign`) were implemented like so:

```
class HashMap:
    def __init__(self, array_size):
        self.array_size = array_size
        self.array = [None for item in range(array_size)]

    def hash(self, key,count_collisions=0):
        key_bytes = key.encode()
        hash_code = sum(key_bytes)
        return hash_code + count_collisions

    def compressor(self, hash_code):
        return hash_code % self.array_size

    def assign(self, key, value):
        array_index = self.compressor(self.hash(key))
        current_array_value = self.array[array_index]
        if current_array_value is None:
            self.array[array_index] = [key, value]
            return
        if current_array_value[0] == key:
            self.array[array_index] = [key, value]
            return
        number_collisions = 1
        while (current_array_value[0] != key):
            new_hash_code = self.hash(key, number_collisions)
            new_array_index = self.compressor(new_hash_code)
            current_array_value = self.array[new_array_index]
            if current_array_value is None:
                self.array[new_array_index] = [key, value]
                return
            if current_array_value[0] == key:
                self.array[new_array_index] = [key, value]
                return

            number_collisions += 1
        return
```

## Linear Search

`Linear Search`is an algorithm used to locate and retrieve information from a list by scanning every item sequentially. If the target is found, the search stops and returns the position (index) in the list where the target value is located. Otherwise, it returns a message that the target is not in the list.

Here is the way the algorithm was implemented:

```
def linear_search(lista):
    matches = []
    data = []
    while True:
        target_chunk = input("  Digite as iniciais do benefício a pesquisar e pressione <enter>. \n  Sua escolha: ")
        for key, value in lista:
            if (target_chunk in key) or (target_chunk in value.values()):
                matches.append(key)
                data.append(value)
        if len(matches) == 0:
            raise ValueError(f"  Nenhum tópico com as letras {target_chunk} foi encontrado.")
        else:
            break

```

After the user typed the letters, the program checks whether these letters are part of the benefit's name. If there's a match, the corresponding key is added to a list called *matches* whereas its value is appended to another list called *data*.

The program runs recursively until there's only one type of benefit in the *matches* list.

```
 if len(matches) > 1:
        print(f"  Com essas letras, as opções são: {matches}")
        linear_search(lista)
    else:
        print(f"  A opção disponível com essas letras é {matches[0]}. Você quer consultar {matches[0]}?"
              f" Digite 'S' para sim.")
        answer = input("  Sua escolha: ")
        if answer == "S":
            os.system("clear")
            print(f"\n  Estes são os dados do benefício escolhido: {matches[0]}")
            if type(list(data[0].values())[0]) is not str:
                for beneficio, item in data[0].items():
                    print("\n ", beneficio.upper())
                    for dado, valor in item.items():
                        print(f"  - {dado}: {valor}")
            else:
                print("\n ", matches[0].upper())
                for dado, valor in data[0].items():
                    print(f"  - {dado}: {valor}")
```

Finally, the program retrieves the data stored in the *data* list where *beneficio* is the key and *item* is the value.

##Main

Putting everything together:

```
def main():
    os.system('clear')
    welcome_message = "Plano de benefícios da Previdência Social"
    print("\n  " + ((len(welcome_message) + 40) * '=') + '\n  ' + (len(welcome_message) + 40) * '=' + "\n")
    print(("  " + " " * 20) + f"{welcome_message:20}")
    print("\n  " + ((len(welcome_message) + 40) * '=') + '\n  ' + (len(welcome_message) + 40) * '=' + "\n")
    try:
        linear_search(plano_HM.array)
    except ValueError as error_message:
        print("{}".format(error_message))
        linear_search(plano_HM.array)
    while True:
        print()
        again = input("  Gostaria de realizar nova pesquisa? Digite 'S' para sim ou qualquer tecla para sair.\n"
                      '  Sua escolha: ')
        if again == "S":
            os.system("clear")
            linear_search(plano_HM.array)
        else:
            print("  Até a próxima!")
            break
    os.system('exit')
```

Check it out: [video](https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:6929782563968278528" height="546" width="504" frameborder="0" allowfullscreen="" title="Embedded post"></iframe>), [GitHub](https://github.com/ElianeSato/recommendation_program)

[^1]: The code was borrowed from Codecademy.