Search
Write a publication
Pull to refresh
4
0
Алексей Исмагилов @alexejisma

Пользователь

Send message

Понял. А пробовали ли Вы использовать предобуславливатели? На моей практике без предобуславливания методы ведут себя не очень хорошо.

Можно добавить проверку в духе

for dx, dy in neigbours:
    if (xx := x + dx) in range(w) and (yy := y + dy) in range(h):
        paint_it_black(xx, yy)

где w - ширина области, h - высота

Для обхода всех соседей можно использовать такой код:

r = (-1, 0, 1)
for dx in r:
    for dy in r:
        if dx or dy:
            paint_it_black(x + dx, y + dy)

Можно сделать код лаконичнее (убрав несколько уровней вложенности):

r = (-1, 0, 1)
neighbors = [
    (dx, dy)
    for dx in r  
    for dy in r   
    if dx or dy
]
for dx, dy in neighbors:
    paint_it_black(x + dx, y + dy)

Ну и, как мне кажется, самый изящный способ, который можно использовать для любого количества измерений, следующий:

import itertools

dims = 2
neighbors = [
    n
    for n in itertools.product((-1, 0, 1), repeat=dims)
    if any(n)
]
for dx, dy in neighbors:
    paint_it_black(x + dx, y + dy)

P.S. во всех трех вариантах можно убрать if ("if dx or dy" и "if any(n)")и тогда будут не только соседи, но и точка (x, y).

neighbors = [n for n in itertools.product((-1, 0, 1), repeat=dims)]
# or
neighbors = list(itertools.product((-1, 0, 1), repeat=dims))

P.P.S. Для ортогональных соседей ((-1, 0), (0, -1), (0, 1), (1, 0)) можно "if any(n)" заменить на "if sum(abs(x) for x in n) == 1" или "sum(map(abs, n)) == 1" (кому что больше нравится), а "if dx or dy" заменить, например, на "if dx + dy in (-1, 1)" или "if abs(dx + dy) == 1":

neighbors = [
    n
    for n in itertools.product((-1, 0, 1), repeat=dims)
    if sum(map(abs, n)) == 1
]

P.P.P.S. Для диагональных соседей ((-1, -1), (-1, 1), (1, -1) и (1, 1)) можно в коде выше заменить (-1, 0, 1) на (-1, 1) и убрать if, так как он будет не нужен.

neighbors = [n for n in itertools.product((-1, 1), repeat=dims)]
# or
neighbors = list(itertools.product((-1, 1), repeat=dims))

Почему выбор пал на точный метод вместо итерационного? Разве не будет расход памяти огромный?

Когда я учился в университете нам рассказывали именно такой вариант. Для этого метода матрица не обязательна быть положительно определенной. Когда возникает необходимость извлекать квадратный корень sqrt(x), то извлекается корень из модуля числа sqrt(abs(x)), а диагональный элемент принимает значение знака того числа из модуля которого извлекается корень sign(x). Это существенно расширяет класс "хороших" матриц.

Подскажите, пожалуйста, системы с какими матрицами можно решить методом LDL, которые нельзя решить методом Холецкого (разложение матрицы в виде L*D*L^t, где L нижнетреугольная, D диагональная с +1/-1 на диагонали)?

Пробовали ли Вы flatpack или snap? Какие были недостатки с ними?

Еще так можно:

r = (-1, 0, 1)
[(i, j)   for i in r   for j in r   if i or j]

Вместо user_last_photo_time можно использовать bot.user_data , см. https://github.com/python-telegram-bot/python-telegram-bot/wiki/Storing-bot%2C-user-and-chat-related-data. Это словарь, который python-telegram-bot создает для каждого пользователя и предоставляет к нему доступ.

Библиотека std::ranges основана на библиотеке range-v3, которая работает на C++14 и новее. Поэтому можно эту библиотеку добавить в свой проект. Кроме того, на сколько я помню, в std::ranges вошли не все возможности из range-v3.

Ссылка: https://github.com/ericniebler/range-v3

Что обозначает буква k в именах перечислений?

Ты осторожнее с вопросами, вдруг нас ждет еще один пост с ответом именно на этот вопрос))

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

Про сложность говорить смысла особо нету, так как размер доски небольшой и оба алгоритма отработают мгновенно.

Что-то я накосячил с оформлением формул в пост скриптуме. Я хотел написать ".. O(mn), а не O(mn log(mn))".

Существует и другой, как мне кажется более простой, способ проверять решаемость головоломки. Заключается он в том, чтобы вычислить некую характеристику для start и для goal и сравнить ее: если характеристика совпала, то существует "путь" от позиции start к позиции goal.

Теперь непосредственно про вычисление характеристики.

1. Необходимо обойти головоломку "змейкой", то есть обойти в следующем порядке:

   1  2  3  4
   8  7  6  5
   9 10 11 12
  16 15 14 13

Данный обход можно обощить на любой размер доски: обходим доску строчку за строчкой, четные (предполагается нумерация с 0) обходим слева направо, нечетные справа налево.

2. Выписать встретившиеся значения фишек, то есть выписать только ненулевые значения ячеек. Полученная набор чисел является перестановкой множества чисел от 1 до 15.

Для приведенного автором статьи примера

  12 13 11  2
   4  5  3 14
   1  9 15  6
   8  7  0 10

 числа будут выписаны в следующем порядке: 12, 13, 11, 2, 14, 3, 5, 4, 1, 9, 15, 6, 10, 7, 8.

3. Характеристикой является четность описанной в прошлом пункте перестановки. Как посчитать четность? Отсортировать массив, подсчитав количество swap'ов. Четностью перестановки будет четность количества swap'ов.

Какова сложность данного алгоритма?

По памяти: \mathcal{O}(m n).

По времени: \mathcal{O}(m n).

P.S. Может возникнуть вопрос почему сложность по времени , а не \mathcal{O}(m n). Ошибки здесь нету. Все дело в том, что в данной задаче массив имеет специфичный вид и за счет этого его можно отсортировать за линейное время. Кому интересно предлагаю самостоятельно разобраться почему это так, я же просто оставлю код сортировки массива, являющегося перестановкой множества \{ 0, \, 1, \, 2, \, \ldots, \, k-1 \}:

for (int i = 0; i < perm.length; i++) {
    while (perm[i] != i) {
        // swap(a, i, j) меняет местами a[i] и a[j]
        swap(perm, i, perm[i]);
    }
}

Отмечу, что в отсортированном массиве perm[i] == i для всех i от 0 до perm.length и что именно это свойство является ключевым.

Можно строки заменить на векторы: x = (1, 0, 0), y = (0, 1, 0), z = (0, 0, 1). Либо самому написать простенький класс, либо, например, воспользоваться numpy.

При исполнении байт кода у JVM есть два сценария: 1. интерпретировать байт код; 2. компилировать байт код. В первом случае, как мне кажется, накладные расходы на интерпретацию будут слишком высоки и прироста в скорости работы заметить не получится. Во втором же случае происходит ровно тоже, что и в случае С++, поэтому ускорение должно наблюдаться.

Где-то я читал, что начиная с какой-то версии JVM всегда компилирует байт код. Мог не так понять. В любом случае, желательно код перед бенчмарками "прогреть", то есть выполнить многократный вызов функции с кодом, чтобы вызвать срабатывание механизма компиляции.

Еще, на сколько мне известно, JVM может обнаружить, что один и тот же код выполняется в цикле и оптимзировать это. Поэтому, возможно, придется как-то аккуратно запускать бенчмарк.

На ubuntu, как и на большинство дистрибутивов легко можно накатить другое окружение рабочего стола. Или сразу скачать версию с другим окружением рабочего стола: ubuntu - gnome, xubuntu - xfce, kubuntu - kde, ubuntu mate - mate и т.д. Для fedora есть fedora spins (xfce, kde, mate, etc.).

В некоторых случаях будет достаточно отслеживать не дату пуша коммита, а дату сборки проекта. Для этих целей есть макросы DATE и TIME:

LOG_INFO(FILE_PC, "Build: %s %s", __DATE__, __TIME__);
// Выведет: "Build: Feb  6 2024 23:53:52"

Безопасный компьютер -- выключенный компьютер =)

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Registered
Activity