2
\$\begingroup\$

This project I'm dealing with will read the size of free memory segments and size of processes from a text file and then will try to allocate a memory partition for each process using the first-fit, best-fit and worst-fit allocation algorithms. Below is the first part of the code I wrote.

import sys

filename = sys.argv[1]

with open(filename, "r") as file:
        free_memory = file.readline().strip().split(',')
        process_size = list(map(int, file.readline().strip().split(',')))       

file = open("output.txt","w")



#---------------------------#
#First-Fit Memory Allocation#
#---------------------------#

file.write(f"First-Fit Memory Allocation\n{'-'*60}\n") 
file.write(f"start => {' '.join(free_memory)}\n")

memory = list(map(int, free_memory)) 
memory_str = list(free_memory)

for process in process_size:
        data = f"{process} => "
        allocated = False
        for index in range(len(memory)):
                if not allocated and memory[index] >= process:
                        memory[index] -= process
                        memory_str[index] = memory_str[index][:-1*len(str(process))]
                        memory_str[index] += f"{process}*" 

                        if(memory[index] != 0):
                                memory_str[index] += f" {memory[index]}"
                        allocated = True
                
                data += f"{memory_str[index]} " 

        if(not allocated):
                data = f"{process} => not allocated, must wait"              

        file.write(data+'\n')
\$\endgroup\$
2
  • \$\begingroup\$ Please show an example input file. \$\endgroup\$
    – Reinderien
    Jun 3 at 15:53
  • 1
    \$\begingroup\$ There appears to be this duplicate question - does the input there suffice as the input here? \$\endgroup\$ Jun 3 at 18:13
0
\$\begingroup\$

I think from a prior question the input is:

300,600,350,200,750,125
115,500,358,200,375

I believe the assignment asked for a simplification of the code as it is a little convoluted at the moment. I'll try to clean it up a bit.

I've added what I guess are the other additional "strategies" as well.

I think the major difference between the given code and what I am going to offer is that the original maintains a string and integer version of the memory regions for what looks like the purpose of flagging a region as "in use" with a *. I'm going to use a tuple to indicate the (size, availability) of the memory block. then when printing we can look to add the flag as appropriate.

At the moment, our strategy is set to "First Fit":

## ---------------------------
## We print a nice display of memory in a few places so let's make a method to do that
## ---------------------------
def format_memory(memory_blocks):
    return ' '.join(str(x[0]) + ("" if x[1] else "*") for x in memory_blocks)
## ---------------------------

## ---------------------------
## Pick one of these to be your fit_strategy.
## ---------------------------
def get_fit_strategy(key):
    def find_candidates(memory_blocks, process_size):
        return [(idx, val) for (idx, val) in enumerate(memory_blocks) if val[1] and val[0] >= process_size]

    def first_fit(memory_blocks, process_size):
        candidates = find_candidates(memory_blocks, process_size)
        return next((candidate[0] for candidate in candidates), None)

    def best_fit(memory_blocks, process_size):
        candidates = find_candidates(memory_blocks, process_size)
        candidates = sorted(candidates, key=lambda x: x[1][0])
        return next((candidate[0] for candidate in candidates), None)

    def worst_fit(memory_blocks, process_size):
        candidates = find_candidates(memory_blocks, process_size)
        candidates = sorted(candidates, reverse=True, key=lambda x: x[1][0])
        return next((candidate[0] for candidate in candidates), None)
    
    ## ---------------------------
    ## keep the name and the implementation aligned.
    ## ---------------------------
    strategies = {
        "first" : {"nm": "First Fit", "fn": first_fit},
        "best" : {"nm": "Best Fit", "fn": best_fit},
        "worst" : {"nm": "Worst Fit", "fn": worst_fit}
    }
    ## ---------------------------

    ## ---------------------------
    ## get a strategy falling back to "first"
    ## ---------------------------
    selected_strategy = strategies.get(key, strategies["first"])
    ## ---------------------------

    ## ---------------------------
    ## when called, return the name and implementation of our strategy
    ## ---------------------------
    return (selected_strategy["nm"], selected_strategy["fn"])
    ## ---------------------------

fit_strategy_name, get_free_block_index = get_fit_strategy("first")
## ---------------------------

## ---------------------------
## Read our two lines of input.
## ---------------------------
with open("memory.txt", "r") as input_file:
    ## list of tuples(size, is_available)
    memory_blocks = [(int(x), True) for x in input_file.readline().split(',')]

    ## list of process requirements
    process_sizes = [int(x) for x in input_file.readline().split(',')]
## ---------------------------

## ---------------------------
## Append each "line" to print to a list of lines to be printed at the end
## ---------------------------
results = []
results.append(f"{ fit_strategy_name } Memory Allocation")
results.append(f"{ '-' * 60 }")
results.append(f"start => { format_memory(memory_blocks) }")
## ---------------------------

## ---------------------------
## For each process (an entry in process_sizes) attempt to find a block of memory
## ---------------------------
for process_size in process_sizes:

    ## ---------------------------
    ## Using our selected strategy find the index (or None) of a block that is
    ## "free" and "big enough"
    ## ---------------------------
    index = get_free_block_index(memory_blocks, process_size)
    ## ---------------------------

    ## ---------------------------
    ## There was no appropriate block found to host this process
    ## ---------------------------
    if index is None:
        results.append(f"{ process_size } => not allocated, must wait")
        continue
    ## ---------------------------

    ## ---------------------------
    ## Insert a new memory block representing what will be the remaining memory after we
    ## allocate process_size memory out of memory_blocks[index] flagging it as available
    ## ---------------------------
    remaining_allocation = memory_blocks[index][0] - process_size
    if remaining_allocation:
        memory_blocks.insert(index+1, (remaining_allocation, True))
    ## ---------------------------

    ## ---------------------------
    ## Allocate our memory flagging it as unavailable (False)
    ## ---------------------------
    memory_blocks[index] = (process_size, False)
    ## ---------------------------

    results.append(f"{ process_size } => { format_memory(memory_blocks) }")
## ---------------------------

## ---------------------------
## now write the results that we stored in the list
## ---------------------------
with open("output.txt","w") as output_file:
    output_file.write('\n'.join(results))
## ---------------------------

When run it will produce a file (output.txt) with the following contents:

First Fit Memory Allocation
------------------------------------------------------------
start => 300 600 350 200 750 125
115 => 115* 185 600 350 200 750 125
500 => 115* 185 500* 100 350 200 750 125
358 => 115* 185 500* 100 350 200 358* 392 125
200 => 115* 185 500* 100 200* 150 200 358* 392 125
375 => 115* 185 500* 100 200* 150 200 358* 375* 17 125
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.