Решение с использование регулярных выражений на базе UDF из приемов: https://www.planetaexcel.ru/techniques/7/4844/ Выделяем целые числа из формулы Если указать значение 1 или опустить, то будет первое число, если указать -1, то последнее число, -2 - предпоследнее и т.п. Проверки на ошибки не делалось Если нужны и дробные значения, то можно переделать шаблон для регулярного выражения
Во вложении генератор спирали на VBA, пример матрицы 99 на 99 для больших чисел может не хватить памяти, но матрицу 999 на 999 можно построить достаточно быстро
Код на VBA:
Скрытый текст
Код
Function ulam_spiral(n As Long) As Variant()
Dim not_primes() As Boolean
Dim matrix() As Variant
Dim i As Long, j As Long, x As Long, y As Long
Dim dx As Long, dy As Long, dx_prev As Long
ReDim not_primes(n * n) As Boolean
not_primes(0) = True
not_primes(1) = True
i = 2
While i <= n
If Not not_primes(i) Then
For j = i * i To n * n Step i
not_primes(j) = True
Next j
End If
i = i + 1
Wend
ReDim matrix(1 To n, 1 To n) As Variant
x = n
y = n
dx = -1
dy = 0
matrix(y, x) = -1
For i = n * n - 1 To 1 Step -1
If x + dx < 1 Or x + dx > n Or y + dy < 1 Or y + dy > n Then
dx_prev = dx
dx = -dy
dy = dx_prev
ElseIf matrix(y + dy, x + dx) <> 0 Then
dx_prev = dx
dx = -dy
dy = dx_prev
End If
x = x + dx
y = y + dy
If not_primes(i) Then
matrix(y, x) = -1
Else
matrix(y, x) = i
End If
Next i
For y = 1 To n
For x = 1 To n
If matrix(y, x) = -1 Then
matrix(y, x) = Empty
End If
Next x
Next y
ulam_spiral = matrix
End Function
Sub main()
Dim n As Long
n = Val(InputBox("Введите нечетное положительное N (от 1 до 999"))
If n < 1 Or n Mod 2 = 0 Or n > 999 Then
MsgBox ("Неверное значение N")
Exit Sub
End If
Cells.Clear
Cells(1, 1).Resize(n, n) = ulam_spiral(n)
Cells(1, 1).Resize(n, n).EntireColumn.AutoFit
End Sub
написал: Как сделать простые числа на спирали чисел автоматизировать
Речь о Спирали Улама? Реализовал на Python спираль 999 х 999: Решетом Эратосфена находим все простые числа в массиве от 0 до 999*999 Далее закручиваем числа в спираль - создаем матрицу со значениями True/False (Простое/Составное) И рисуем картинку
Не знаю, актуальна ли еще задача или нет? Для решения можно использовать линейное программирование, по исходному описанию 10A + 10Б рюкзаков по 5 отделений глубиной 50/60 см и шириной 10/15/20 см - не очень большая вариативность, можно перебрать все возможные комбинации, свести задачу к построению целочисленной линейной модели с правильным указанием целевой функции и решить задачу симплекс-методом.
в Python целочисленная арифметика по умолчанию - длинная. Все целочисленные операции: +, -, *, // (целочисленное деление), ** (степень), % (остаток от деления) - производятся с длинными числами, не ограниченными по количеству знаков, ничего подключать не нужно.
Обычно длинка работает достаточно быстро, т.к. реализована на C++, сравнивал с вычислениями на dotNet (в частности PascalABC.NET), Python большие числа Фибоначчи рассчитал значительно быстрее, чем BigInteger в PascalABC
Задал идентичный вопрос Алисе, получил точно такой же ответ, возможно Алиса переспрашивает у Chat GPT
Скрытый текст
напиши код на языке программирования VBA который бы удалил активный лист в файле Excel не спрашивая у пользователя подтверждения Код на VBA для удаления активного листа в файле Excel без подтверждения:
Код
Sub DeleteActiveSheet()
Application.DisplayAlerts = False
ActiveSheet.Delete
Application.DisplayAlerts = True
End Sub
В этом коде мы сначала устанавливаем значение свойства Application.DisplayAlerts в False, чтобы скрыть все предупреждения и запросы подтверждения от пользователя. Затем мы удаляем активный лист с помощью метода ActiveSheet.Delete. Наконец, мы устанавливаем значение свойства DisplayAlerts обратно в True, чтобы восстановить поведение по умолчанию.
А если сразу генерировать буквенно-цифровую строку из 10 символов, должно быть быстрее, а уникальность определяется огромным числом вариантов (но не гарантируется), если нужно, то можно обратно в число преобразовать
Сергей написал: Соотв если менять кол-ва посещений и дату первой оплаты все предложенные формулы могут привести к разным результатам
Вы мою формулу из 6го сообщения смотрели, она достаточно универсальна, выходные и рабочие дни задаются строкой "0101000", где 0 - выходной, 1 - рабочий день. Будут другие условия, формулу легко поправить. Формула должна корректно вычислять любой график работы в горизонте ближайших - 98 дней (можно исправить на нужный)
И да, формула медленная и постоянна пересчитывается, что дает свои ограничения, по сравнению с математическими формулами.
Jack Famous, алгоритм зависит от задачи Если слагаемых мало - даже перебор подойдет Если искомая сумма небольшая - динамическое программирование Если нет жесткого требования к оптимальности результата - жадный алгоритмы с частичными переборами с оптимизациями и отсечениями неперспективных ветвей решения используя эвристики Можно линейное программирование прикрутить
Код Игоря считает быстро, когда решение точно есть, я пока не разобрался в алгоритме
Пока с алгоритмом до конца не разобрался Вижу перебор но с отсечением (как бы используем метод ветвей и границ), как только находим результат, останавливаем решение Возможно ошибаюсь
Если поменять тип переменных с Variant на Long и Double, то можно еще немного ускорить Что заметил, если точного решения нет (если нельзя ровно разделить на два равных по сумме списка) то расчет уходит в долгую Например, первое число 999, второе число 1001 и далее 198 двоек Разделить данный список на два равных по сумме невозможно, можно в одном списке 999 + 99*2, в другом 1001 + 99 *2 (или 999 + 100*2 и 1001 + 98*2), что динамикой решается очень быстро
Alien Sphinx написал: Отработал на 20 числах. Тестировал и 30, но ушел в ошибку run out of memory
Протестировал свой код на 200 чисел (код не менял, добавил случайные данные), общая сумма для поиска - 13 млн, отработал не очень быстро но за разумное время. Скорость решения и выделяемая память больше зависит от величины искомой суммы, и линейно зависит от количества слагаемых Сложность алгоритма O(s * n), где s - искомая сумма, n - количество слагаемых, выделяемая память O(s)
Сведение задачи к решению к "Задачи сумма подмножеств" В первый список помещаем все слагаемые которые дают сумму не более половины общей суммы, во второй список - все остальные слагаемые
На базе решения динамическим программированием: Количество слагаемых может быть большим (несколько сотен - легко) Может работать с суммами с копейками Для каждого слагаемого указывается количество данных слагаемых
Суммы распределяет максимально равномерно, если это возможно, но по количеству слагаемых списки могут различаться и не быть равномерными Если нужно и количество слагаемых распределить примерно поровну, то можно реализовать другой алгоритм
Пришлите на почту из профиля или выложите здесь пример исходных данных Озвучьте бюджет проекта.
На вскидку обычный рюкзак с двумя ограничениями (по весу и по кол-ву), возможно подойдет решение задачи "сумма подмножеств" и ее вариации. Алгоритмы аналогичные как в "задаче упаковки в контейнеры" (Bin packing problem) / "задача раскроя" (Cutting stock problem) В зависимости от исходных данных и их кол-ва можно будет решить оптимально с помощью линейного программирования.
В рамках текущего набора данных можно распределить все товары на 6 паллет При этом паллеты будут высотой от 1500 до 1650 мм Монопаллет (с одним товаром) будет только один Остальные можно распределить - не более трех различных товаров на паллете в двух - трех паллетах верхний ряд будет сборный
На сколько является важным потратить много времени на расчет укладки и уложить товар на 6 паллет или допустимо раскидать по быстрому весь товар на 7 паллет, где будет 2 или 3 монопаллета, остальное распределено жадным алгоритмом без явной оптимизации?
Исходя из информации из предыдущего сообщения, то указанный объем можно разместить на 6ти паллетах 800х1200х1650 Для этого нужно еще ограничения: сколько разных товаров может быть на паллете (скорее всего предпочтительно один товар на паллете и минимизация сборных паллет) В теории, если сложить все объемы товаров и разделить на максимальный объем паллета (800х1200х1650) то получается 4,999... паллет, т.е. в 5 паллет точно не поместится, т.к. при укладке есть потери пространства.
Задача укладка на паллет относится к 3D укаладке и в общем случае достаточно сложная. можно ее упростить и решать задачу 2D укладки каждого товара по слоям Можно использовать следующий алгоритм: 1. объединяем схожие размеры товаров 2. раскладываем каждый вид товара на паллет в один слой, для этого используем 2D раскладку с возможностью вращения коробок (см. вложение) 3. раскладываем полученные карты раскладки на целые палеты с учетом ограничения по высоте паллета, при этом можно объединять разные слои товаров, если это приводит к уменьшению количества целых паллет. Возможно нужно еще вводить ограничение по весу паллета, т.к. он обычно регламентируется. 4. то что не влезает в паллет размещаем на сборных паллетах, либо в ручную либо частично автоматизируем процесс.
Пример 2D укладки во вложении. Если задачи разовые, то можно использовать данный калькулятор как помощник для определения оптимальной укладки коробок по слоям, если задача регулярная и объемная, то нужно реализовывать нормальный алгоритм раскладки. На первом этапе может подойти даже жадный алгоритм, далее нужно применить генерацию оптимальных схем раскладки и с помощью линейного программирования (симплекс метода) определять минимальное кол-во паллет.
Дополнил решение, сделал второй вариант (изменение кол-ва): 1. Пропорционально меняем количество под нужную сумму 2. Цены не меняем (округляем до нужной точности) 3. Подгоняем цены, меняя некоторые позиции в ценах (+/- несколько копеек)
Jack Famous написал: только непонятно, как это делать
Пример разложения числа на биты через остаток от деления на 2 Генерируем 10 случайных чисел от 0 до 65535 с выводом их битов
Код
Function get_bits(ByVal n As Long, nums As Long) As Long()
Dim i As Long
Dim out_array() As Long
ReDim out_array(nums - 1) As Long
While n > 0 And i < nums
out_array(i) = n Mod 2
n = n \ 2
i = i + 1
Wend
get_bits = out_array()
End Function
Sub print_array(a() As Long)
Dim x As Variant
For Each x In a
Debug.Print x;
Next x
Debug.Print
End Sub
Sub test()
Dim a() As Long, n As Long, i As Long
For i = 1 To 10
n = Int(Rnd * 256 * 256)
a = get_bits(n, 16)
Debug.Print n,
print_array a()
Next i
End Sub
Биты числа в обратном порядке при выводе, нумерация битов в массиве от 0 до nums-1
То что я имел в виду: разложение целого числа на биты по затратам сопоставимо с разложением десятичного числа на разряды, где каждая цифра может быть либо 0 либо 1, при этом охватываемый диапазон числе с побитным представлением для типа Long - 31 бит
Ігор Гончаренко написал: потом чтобы этими ноликами/единичками воспользоваться - нужно каждое значение снова разобрать на 0 / 1в общем - такая себе идея с сомнительным итоговым результатом
Думаю, что по скорости десятки разбирать (при делении на 10), что биты (при делении на 2) будет сопоставимо, только зачем в итоге разделять на десятки, когда можно с битами работать?
самый простой способ получить все варианты с битами: for i = 1 to 2 ^ d - 1 Ограничение для типа Long - 31 бит, это 2 млрд. комбинаций (их еще и перебрать нужно) Разделение числа на биты аналогично разделению десятичного числа состоящего из цифр 1 и 0 на разряды, а может и быстрее
Sub Digist01(a() As Double, d As Long)
Dim i As Long, j As Long, k As Long, t As Long
ReDim a(2 ^ d - 1) As Double
i = 1
k = 1
For t = 1 To d
For j = 0 To i - 1
a(i + j) = k + a(j)
Next j
i = i * 2
k = k * 10
Next t
End Sub