Модификация списков в алгоритме матрицы Python - PullRequest
0 голосов
/ 11 января 2019

Я работаю над некоторыми проблемами алгоритма, чтобы получить больше практики Python. У меня возникли некоторые проблемы с проблемой, которая требует изменения значений внутри матрицы Python (список списков).

# Challenge
# After they became famous, the CodeBots all decided to move to a new building and live together. The building is represented by a 
# rectangular matrix of rooms. Each cell in the matrix contains an integer that represents the price of the room. Some rooms are 
# free (their cost is 0), but that's probably because they are haunted, so all the bots are afraid of them. That is why any room 
# that is free or is located anywhere below a free room in the same column is not considered suitable for the bots to live in.
# ex: matrix = [[0, 1, 1, 2],      [[x, 1, 1, 2],
#               [0, 5, 0, 0],  -->  [x, 5, x, x],  --> 5 + 1 + 1 + 2 = 9
 #              [2, 0, 3, 3]]       [x, x, x, x]]

Мой подход двоякий: 1) сначала найдите все нули в матрице и замените это значение на «x». 2) Как только это произойдет, переберите все списки и найдите индекс существующего «x», затем используйте это значение индекса и найдите его в других списках. Замените числовое значение на «x», если это число «ниже» «существующий« х ».. надеюсь, это имеет смысл. У меня есть первая часть, и я пробовал вторую часть несколькими различными способами, но сейчас я сталкиваюсь с ошибкой ... Я чувствую, что я очень близок. Я также чувствую, что мой код довольно неэффективен (я новичок в Python), поэтому, если есть более эффективный способ сделать это, пожалуйста, дайте мне знать.

Я понимаю, что означает ошибка, но мне трудно исправить ее, получая правильный ответ. Ошибка в том, что индекс выходит за пределы допустимого диапазона.

Мой код:

def matrixElementsSum(matrix):
    numList = len(matrix) # essentially the number of 'rows' -> number of lists
    numCol = len(matrix[0]) # number of values in each list

    # replace 0's in each list with 'x'
    for x in matrix:
        if x.count(0) > 0:
            for index, i in enumerate(x):
                if i == 0:
                    x[index] = 'x'

    for x in matrix:
        for y in matrix[x]:
            if(matrix[x][y] == 'x'):
                x_ind = y
                for z in matrix:
                    if(z < x):
                        matrix[z][x_ind] = 'x'
     print(matrix)

Тестовый сценарий:

matrixElementsSum([[0, 1, 1, 2], 
                   [0, 5, 0, 0], 
                   [2, 0, 3, 3]])

1 Ответ

0 голосов
/ 11 января 2019

Вы по-прежнему будете каким-то образом требовать вложенных циклов для циклов, поскольку вы перебираете список списков, но вы могли бы немного упростить логику, используя их списки.

def solver(matrix):
     mx = [[v if v else 'x' for v in row] for row in matrix]
     mxx = [[v1 if v2 else 'x' for v1, v2 in zip(row1, row2)] for row1, row2 in zip(mx[1:], matrix)]
     return mx[:1] + mxx

Сначала я перебираю матрицу и заменяю 0 на "x" s в новой матрице mx.

mx = [[v if v else 'x' for v in row] for row in matrix]

Это просто понимание вложенного списка, в котором мы оперируем каждым элементом в строке, каждой строкой в ​​матрице. ... if ... else ... - это просто ваш классический троичный оператор. Если v выполнено (в нашем случае это не ноль), то оно вычисляется до значения перед «if», в противном случае оно оценивается до значения после «else» - в данном случае 'x'.

Затем я повторяю процесс, но смещая строки на одну, чтобы я мог проверить, является ли вышеприведенный элемент "x".

mxx = [[v1 if v2 else 'x' for v1, v2 in zip(row1, row2)] for row1, row2 in zip(mx[1:], matrix)]

Здесь есть что сломать. Давайте начнем с «снаружи» и продолжим наш путь.

... for row1, row2 in zip(mx[1:], matrix)

Это сжатие новой матрицы, смещенной на единицу (используя [1:] обозначение среза), с исходной матрицей. Таким образом, он возвращает итеративно функционально эквивалентный следующий список:

[(mx_row1, matrix_row0), (mx_row2, matrix_row1), (mx_row3, matrix_row2), ...]

Это позволяет нам извлекать данную строку и строку над ней одновременно, как row1 и row2. Тогда другая половина -

[v1 if v2 else 'x' for v1, v2 in zip(row1, row2)]

- повторяет аналогичный процесс для каждого элемента в строке, а не для строки в матрице. Мы не смещаем элементы в каждой строке, как мы смещаем строки матрицы mx, но в остальном логика идентична. Затем мы снова сравниваем с нашим троичным оператором, чтобы увидеть, является ли вышеуказанный элемент 0, и, если это так, оценим 'x'. Мы могли бы легко изменить это, чтобы сравнить каждый элемент каждой строки от mx до 'x' вместо matrix до 0, но я решил отразить понимание первого списка.

Получив эту новую матрицу mxx, я просто добавляю к первой строке mx, потому что мы эффективно пропускаем эту строку, когда смещаем наше сравнение. В результате получается матрица со всеми 0 с и элементами ниже, замененными на "x" с.


В соответствии с разъяснениями в комментариях, если вы хотите отметить "x", если любой из вышеперечисленных элементов равен 0, а не только непосредственно указанному выше, вы можете сделать это, взяв часть этого столбца матрицы и использование встроенного all(), чтобы увидеть, есть ли 0. Пересмотренный код ниже

def solver(matrix):
    return [[v if all(col) else 'x' for v, col in zip(row, zip(*matrix[:idx]))] for idx, row in enumerate(matrix, 1)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...