How do I compare two lists of diffrent sizes, find matches and return the indices of those matches in both lists

Question:

In pygame I am building a GA simulation. The simulation involves 10 creatures and 100 pieces of food. I am creating them as sprites. I tried to use built in sprite collision detection but I need to detect collisions between unique sprites, not sprites and groups or groups and groups. That led me to realize I need a custom solution. Since my numbers are low I figured I could throw the positions of the food and creatures into lists and compare them. That part works but what I can’t figure out is how to get the inidices for the matches in the lists. I’m not too worried about speed because I think my comparison is fast enough, especially given the small amount of data involved and the relative rarity of collisions but I’d still like an inexpensive solution to find those indices. I could create dictionaries, etc. I’m not sure what’s the best route. My test code for the comparison is below, and working great and gives me half of my answer, the indices of the bots making the collisions. All I need now is the indices of the food collided with.

from random import *
food = [(randint(0, 1000), randint(0, 1000)) for i in range(100)]
while True:
    bots = [(randint(0, 1000), randint(0, 1000)) for i in range(10)]
    for i in range(len(bots)):
        if bots[i] in food:
            print(i, bots[i])
    for i in range(len(food)):
        if food[i] in bots:
            print(i, food[i])

The above code does precisely what I want but is a dirty bodge and extremely expensive. It gets me going for now but it will have to be refined.

Asked By: Dave

||

Answers:

It’s hard to give a concrete answer because I don’t know what a GA simulation is. Genetic Algorithm? Is it 2d, 3d, nd? The approach for any of them will be similar.

It’s probably best to approach this a little differently.

We have a "Location" that contains: it’s identifier ie x,y(,z…) coordinates, a value for a bot to exist, and a value for food to exist. Then the primary data structure is a list of all these locations.

Now, for every frame (step/generation/etc), we iterate all possible locations and if the value exists for both food and a bot at any location, we know we have a collision. From there, it’s just integrating whatever logic you want for your sim.

Answered By: zelarian

For food, use dictionary instead of list….

from random import randint

food = {i:(randint(0, 1000), randint(0, 1000)) for i in range(100)}
while True:
    
    bots = [(randint(0, 1000), randint(0, 1000)) for i in range(10)]
    for i in range(len(bots)):
        if bots[i] in food.values():
            
            print(f'Bot num {i} collided with food num {list(food.keys())[list(food.values()).index(bots[i])]}')
            # "list(food.keys())[list(food.values()).index(bots[i])]" finds the key of the given value (here, the bot position)

Output:

Bot num 3 collided with food num 80
Bot num 6 collided with food num 51
Bot num 3 collided with food num 32
Bot num 8 collided with food num 86
Bot num 7 collided with food num 98
Bot num 9 collided with food num 94
Bot num 5 collided with food num 88

This continues till I stop.

Answered By: Tirth Bhagwat
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.