Как непрерывно генерировать 2D-списки до тех пор, пока не будет выполнена определенная спецификация

#python

#python

Вопрос:

Я написал следующую программу на Python:

Эта программа генерирует 2D-список размером 30×30 и случайным образом размещает 10 меток вокруг сетки. Я хочу модифицировать эту программу, чтобы она непрерывно генерировала это 30×30 2D при размещении меток и останавливалась только тогда, когда каждая метка находится на заданном расстоянии друг от друга (например, минимум на расстоянии 5 метров). Я знаю, что для этого мне пришлось бы использовать теорему Пифагора, но не уверен, как реализовать ее в моем коде.

 import random
listSize = 30
marks = 10
grid = []
for i in range(listSize): 
    grid.append([0] * listSize)
for i in range(marks):
    x = random.randint(0, listSize - 1)
    y = random.randint(0, listSize - 1)
    grid[x][y] = 1 
for row in grid:
    print(row)
 

Комментарии:

1. Ваш вопрос мне непонятен. Что вы подразумеваете под stop only when each mark is a set amount of spaces apart . Установить количество пробелов отдельно от предыдущей отметки?

2. Никакие 2 метки не могут быть ближе 5 метров друг к другу для всех 10 меток.

3. Вместо того, чтобы постоянно создавать новые сетки, почему бы просто не разместить метки в соответствии с ограничениями?

4. Поскольку размещаемые метки генерируются случайным образом (посмотрите на мой код)

5. Таким образом, в этом случае расстояние между вашими метками должно быть больше, чем 5.Am я прав?

Ответ №1:

Вместо того, чтобы хранить метки в сетке, вы должны создать список дополнений, в котором хранятся позиции x, y каждой метки, а затем перебирать их, чтобы проверить, удовлетворяет ли каждая пара условию. Итак, что-то вроде этого:

 import math

points = [(0,0), (5,10), (100,200)]
for n, point_n in enumerate(points):
    for point_m in points[n 1:]:
        if math.dist(point_n, point_m) < 5:
            print('distance less than 5!')
 

Примечание math.dist доступно только в Python3.8 и выше, вам придется самостоятельно кодировать функцию расстояния в более низких версиях.

Ответ №2:

Вот несколько наивный подход «попадание или промах»:

 from math import sqrt
from random import randint
from itertools import combinations

def dist(p,q):
    return sqrt((p[0]-q[0])**2   (p[1]-q[1])**2)

def rand_points(n,k):
    """picks n random points with coordinates in range(k)"""
    #assumes that this is feasible!
    choices = set()
    for _ in range(n):
        while True:
            p = (randint(0,k-1),randint(0,k-1))
            if p not in choices:
                choices.add(p)
                break
    return list(choices)

def check_points(points,min_dist):
    """checks if each point is at least min_dist away from other points"""
    return all(dist(p,q) >= min_dist for p,q in combinations(points,2))

def find_points(grid_size,num_points,min_dist,max_trials = 1000):
    for trial in range(max_trials):
        points = rand_points(num_points,grid_size)
        if check_points(points,min_dist):
            return points
 

Например:

 >>> find_points(30,10,5)
[(26, 9), (6, 0), (29, 23), (17, 13), (12, 19), (2, 22), (2, 28), (3, 9), (1, 16), (18, 5)]
 

Конечно, легко загрузить такой список точек в сетку:

 def grid_from_points(grid_size,points):
    grid = [[0]*grid_size for _ in range(grid_size)]
    for p,q in points:
        grid[p][q] = 1
    return grid
        points = rand_points(num_points,grid_size)
        if check_points(points,min_dist):
            return points