Search code examples
pythonlistmaxmin

How to slice local minima and maxima in a list till last item, without using numpy


I want to search for local maxima and minima through a series of iterations until the list has only one element remaining. Then that last element is the 'winner'. The list contains pairs of player names with corresponding integers separated by a colon.
In short:

  1. For any iteration, I start by searching for minima, and then I proceed to check for maxima, only if my current list of minima has more than one element remaining.
  2. For each iteration, I only keep the list of local minima and minima, so obviously the lists will get smaller with each search/iteration.
  3. If I still have more than one element in the list, I iterate until I have only one.
  4. I would like to be able to see how many iterations were done -- using the variable 'round'.
  5. For a local minima search, the first item in the list is included only if it is smaller than the next item. Also, the last item is included if it is smaller than the previous item. And vice versa for the local maxima search.

The issue is, after the local minima search, I can't seem to correctly proceed to the local maxima search and to the next iteration when the list still has more than one item. So the results don't seem to match what I am expecting.

Here is my code.

def select_mid(players: str):

    player_list = players.split()  # Split the input string into individual name:identifier pairs
    ranks = [int(pair.split(":")[1]) for pair in player_list]  # Extract and convert the identifiers to integers

    minima_list = []
    maxima_list = []
    round = 0
    for i in range(1, len(ranks)):
        if len(player_list) > 1:
            # Here search is "current_rank < prev_rank and current_rank < next_rank"
            prev_rank, current_rank, next_rank = ranks[i-1], ranks[i], ranks[i] if i == len(ranks) - 1 else ranks[i+1]
            if current_rank < prev_rank and current_rank < next_rank:
                minima_list.append(player_list[i])
                player_list = minima_list 
            
            #Here search is "current_rank > prev_rank and current_rank > next_rank"
                if current_rank > prev_rank and current_rank > next_rank:
                    maxima_list.append(player_list[i])
                    player_list = maxima_list 
                round +=1 
                
        elif len(player_list) == 1:
            selection = player_list[0]
    
    return f"{selection} is selected in round: {round} "

# Example inputs:
    result = select_mid("Hulk:70 Kitana:83 Kunglao:20 goro:68 e:50 f:67 DE:40 Ef:177 Sindel:130 Konami:179 Fifa:95 ps:123 Fujin:101 name:134 Hola:89 Amari:205 Shakur:175 Rambo:303 Clay:33 Sheba:725 jaki:51")
    print(result)

I am getting Kunglao:20 as the winner in round 1. So obviously, am not able to correctly proceed to the maxima search and iterate accordingly till the final list has 1 element.

Expected results:

Iteration1

minima1 Hulk:70 Kunglao:20 e:50 DE:40 Sindel:130 Fifa:95 Fujin:101 Hola:89 Shakur:175 Clay:33 jaki:51

maxima1 Hulk:70 e:50 Sindel:130 Fujin:101 Shakur:175 jaki:51

iteration2

minima2 e:50 Fujin:101 jaki:51

maxima2 101

So the Winner here is 101, found in round 2.


Solution

  • Turns out, I had to rethink everything. Posting the answer in case this may be useful to someone in the future.

    def select_mid(all):
        rounds = 0  # Initialize the number of rounds to 0
        pairs_list = all.split()
        while len(pairs_list) > 1:
            rounds += 1  # Increment the round count at the start of each iteration
            local_minima = []  # List to store local minima
            local_maxima = []  # List to store local maxima
    
            # Search for local minima
            # Dealing with the first element in the list if its local less than next element
            if int(pairs_list[0].split(":")[1]) < int(pairs_list[1].split(":")[1]):
                local_minima.append(pairs_list[0])
                
            # Dealing with the elements within
            for i in range(1, len(pairs_list) - 1):
                name, rank = pairs_list[i].split(":")
                prev_rank = int(pairs_list[i - 1].split(":")[1])
                next_rank = int(pairs_list[i + 1].split(":")[1])
    
                if int(rank) < prev_rank and int(rank) < next_rank:
                    local_minima.append(pairs_list[i])
    
            # Include the last item in local minima if it is a local minima
            if int(pairs_list[-1].split(":")[1]) < int(pairs_list[-2].split(":")[1]):
                local_minima.append(pairs_list[-1])
    
            # If there are local minima and more than one element, search for local maxima
            if local_minima and len(local_minima) > 1:
                if int(local_minima[0].split(":")[1]) > int(local_minima[1].split(":")[1]):
                    local_maxima.append(local_minima[0])
    
                for i in range(1, len(local_minima) - 1):
                    name, rank = local_minima[i].split(":")
                    prev_rank = int(local_minima[i - 1].split(":")[1])
                    next_rank = int(local_minima[i + 1].split(":")[1])
    
                    if int(rank) > prev_rank and int(rank) > next_rank:
                        local_maxima.append(local_minima[i])
    
                # Include the last item in local maxima if it is a local maxima
                if int(local_minima[-1].split(":")[1]) > int(local_minima[-2].split(":")[1]):
                    local_maxima.append(local_minima[-1])
    
                # Update the list with local maxima
                pairs_list = local_maxima
            else:
                # If there are no local maxima, update the list with local minima
                pairs_list = local_minima
    
        # Extract and print the name from the remaining pair
        if pairs_list:
            name, id = pairs_list[0].split(":")
            
        return f"The winner is {name} (id: {id}) selected in round {rounds}"
    
    # Example list of pairs containing names and ranks
    all = "Hulk:70 Kitana:83 Kunglao:20 goro:68 e:50 f:67 DE:40 Ef:177 Sindel:130 Konami:179 Fifa:95 ps:123 Fujin:101 name:134 Hola:89 Amari:205 Shakur:175 Rambo:303 Clay:33 Sheba:725 jaki:51"
    result = select_mid(all)
    print(result)
    

    The result is as expected.