Число потомков хорошо подобрать по размеру кеш линии, которая для x86 64 байта. Соответственно если сравнивать просто 32битные ключи, то n=16. Для 64х битных уже 8. Простые сравнения чисел намного быстрее промахов кэша.
Там иллюстрация содержит подсказку к теоретическому решению. Не все таблетки однородны с равномерным распределением активных веществ. На таблетке может не быть засечек.
Проблема статьи в том, что в ней можно заменить менеджера проекта на любую другую профессию и никто не заметит разницы :). Очень мало специфики.
"пусть и на менеджерскую позицию" — это такой троллинг? Для многих переход на менеджерскую позицию является единственным способом зарплатного и карьерного роста и когда приз уходит новому человеку извне — это чертовски неприятно. Есть конечно и менеджерские позиции, которые никто не хотел, но там все относятся с пониманием.
Я полагаю что проблема будет в стоимости такой маски.
Маски — одноразовое медицинское изделие — дешевле и проще в эксплуатации.
Просто как декоративный аксессуар — настоящий респиратор неудобен.
Как прикольный респиратор — возможно подойдёт тем, кто часто работает со вредными веществами (например с красками/пульверизатором), но дети обычно не относятся к этой категории.
В git используется похожий механизм по работе с хешами, первый 00-FF уходит в имя папки, а внутри уже файл называется хешом без первой части.
По сути это на один шаг больше, чем 256 файлов описанный в статье.
Это было бы 256 папок и 256*256 файлов.
Если grep занимал две минуты, то после такой реструктуризации по логике он будет занимать какие-то доли секунды. Содержимое файлов при этом сортировать не обязательно, они такие-же текстовые и грепаются.
Ну это скорее всего плохие тесты от организаторов, раз приведённый пример кода решает задачу. Можно привести пример с n=1, после чего дать на вход три числа [1, 2, 2] — правильный ответ будет 1, так как дальше первого элемента работать не должно согласно условиям задачи
Всё верно, после добавления ip в список плохих счётчик удаляется и далее пропускается, счётчик ip не увеличивается.
Однако ip попадает в очередь и позже удаляется из очереди, при этом счётчик ip всегда уменьшается (при уменьшении счётчик для ip тоже создаётся), дополнительной проверки oldest_ip in bad_ips там нету.
Режим зануды:
В последнем примере кода если адрес уже есть в списке плохих, то от него остаётся счётчик, который уйдёт в отрицательные числа, и тогда при некоторых условиях число счётчиков превысит 1000.
print('\n'.join(current_ip for current_ip in sorted(bad_ips)))
Если заменить настоящие исключения на возврат объекта ошибки, то это будет быстрее работать — да. Только это уже не будет исключениями :)
Они на то и исключения, чтобы не возникать часто — насколько оправдано вообще с этим заморачиваться в плане штатной работы приложения?
По логике там хеш-таблица или какое-нибудь префиксное дерево. Обычный бинарный поиск тоже довольно быстр — ведь там не больше нескольких сотен тысяч слов, а это около 18ти сравнений.
Решение можно упростить с O(w*m*n) всегда до O(w*(m+n)) в худшем случае, заменив итерационное решение из оригинала на аналитическое (проходя только клетки, в которые попадает луч, но не с фиксированным шагом t, а с аналитически посчитанным до пересечения с сеткой).
Это позволит избавиться от формирования списка пересечений (он и сейчас по сути не нужен, можно же сразу искать минимум) и даст хороший выигрыш в скорости, если стена близко.
В моём понимании делать ставку на малые размеры поля нельзя, даже в Wolfenstein 3D образца 1992 года карта была 64*64 = 4096 — это в разы больше высоты экрана в пикселях (1080).
Я не совсем понял логику работы, похоже что вы считаете пересечения каждого луча с каждым блоком уровня.
# for each cell in map get collision wiht it, if exists
В оригинальной статье луч шёл до первого пересечения (https://github.com/ssloy/tinyraycaster/blob/master/tinyraycaster.cpp), читая только те пустые блоки, через которые луч проходит, никаких других collisions не нужно.
Оригинальный цикл был прост:
for (float t=0; t<20; t+=.01) { // ray marching loop
Если подумать, то 50 раз проверять что луч в одной и той же пустой клетке необязательно, после вычисления первых пересечений с горизонтальными и вертикальными линиями дальше можно шагать сразу по пересечениям сетки от ближнего к дальнему пока не попадём в стенку.
Они не привязаны к параметрам сортировки, поскольку она сама не параметризована, а жёстко задана в коде, нету «конфигурирования приоритетов извне» — приоритеты должны задаваться в рантайме, а не на этапе компиляции.
4й вариант где на 3 типа написано 9 функций сравнения плохо масштабируется при увеличении числа типов.
5й в принципе можно легко переделать и параметризовать, если очень надо без RTTI, то выбрал бы его.
Я поясню свой выбор 8 (как наиболее близкий), хотя на мой взгляд там нужен dynamic_cast, a не typeid, и можно ограничиться параметризованным функтором / компаратором
Приоритет при сортировке на мой взгляд привязан к параметрам сортировки, и элементы об этом ничего знать не должны.
Это исключает варианты 1 — 6 (6 вообще костыльный с побочными эффектами)
Вариант 7 и 8 похожи, но смысла возиться со строками нет, тем более писать для этого методы элемента, по сути дублирование встроенного RTTI.
Вариант 9 на мой взгляд плохо расширяем из-за строгой типизации
Кажутся ли вам циклы, построенные с использованием enumerate(), более читабельными, чем циклы, созданные с использованием range(len())?
Они не эквивалентны в случае, если итерируемый список изменяет длину в процессе итерации поскольку диапазон range фиксируется по длине в начале цикла и потом не меняется.
Я имел ввиду что вес одного самореза можно посчитать и вынести в отдельный артикул. Допустим их 500 штук на килограмм при цене 200 рублей за кило. Это 40 копеек штука. Ну сделайте навар и округлите до 1 рубля. Если мне нужно 3 штуки это выгоднее покупки 40 грамм. Лишние саморезы все равно станут мусором в кладовке, который будет храниться годами.
После такой рекламы мемом Леруа планирует пойти покупателям на встречу и продавать саморезы поштучно?
Или исправить весы, чтобы не изводить бумагу на нулевые чеки.
Число потомков хорошо подобрать по размеру кеш линии, которая для x86 64 байта. Соответственно если сравнивать просто 32битные ключи, то n=16. Для 64х битных уже 8. Простые сравнения чисел намного быстрее промахов кэша.
Там иллюстрация содержит подсказку к теоретическому решению. Не все таблетки однородны с равномерным распределением активных веществ. На таблетке может не быть засечек.
Правильный ответ на второй вопрос сильно зависит от типа таблеток. В общем случае так делать нельзя.
Проблема статьи в том, что в ней можно заменить менеджера проекта на любую другую профессию и никто не заметит разницы :). Очень мало специфики.
"пусть и на менеджерскую позицию" — это такой троллинг? Для многих переход на менеджерскую позицию является единственным способом зарплатного и карьерного роста и когда приз уходит новому человеку извне — это чертовски неприятно. Есть конечно и менеджерские позиции, которые никто не хотел, но там все относятся с пониманием.
Маски — одноразовое медицинское изделие — дешевле и проще в эксплуатации.
Просто как декоративный аксессуар — настоящий респиратор неудобен.
Как прикольный респиратор — возможно подойдёт тем, кто часто работает со вредными веществами (например с красками/пульверизатором), но дети обычно не относятся к этой категории.
По сути это на один шаг больше, чем 256 файлов описанный в статье.
Это было бы 256 папок и 256*256 файлов.
Если grep занимал две минуты, то после такой реструктуризации по логике он будет занимать какие-то доли секунды. Содержимое файлов при этом сортировать не обязательно, они такие-же текстовые и грепаются.
Если анимация одна и та же, то можно использовать видео.
Однако ip попадает в очередь и позже удаляется из очереди, при этом счётчик ip всегда уменьшается (при уменьшении счётчик для ip тоже создаётся), дополнительной проверки oldest_ip in bad_ips там нету.
В последнем примере кода если адрес уже есть в списке плохих, то от него остаётся счётчик, который уйдёт в отрицательные числа, и тогда при некоторых условиях число счётчиков превысит 1000.
Зачем так, можно же
Они на то и исключения, чтобы не возникать часто — насколько оправдано вообще с этим заморачиваться в плане штатной работы приложения?
Генерируем разбиения числа, например для 25 их всего 1958.
Для 25ти слов: 1, 24х: 1,…
{25: 1, 24: 1, 23: 2, 22: 3, 21: 5, 20: 7,
19: 11, 18: 15, 17: 22, 16: 30, 15: 42, 14: 56, 13: 77, 12: 100, 11: 131, 10: 164,
9: 201, 8: 230, 7: 248, 6: 235, 5: 192, 4: 120, 3: 52, 2: 12, 1: 1}
На 5 слов 192 разбиения. Нас не интересуют разбиения, содержащие единицу, больше одной двойки или больше одной тройки (как пример, это эвристика для «интересного» разбиения, можно отфильтровать и все 1958 разбиений, тут фильтр что ровно 5 слов)
После фильтрации остаётся 37 вариантов:
[6, 6, 6, 4, 3], [6, 6, 5, 5, 3], [6, 6, 5, 4, 4], [6, 5, 5, 5, 4], [5, 5, 5, 5, 5],
[7, 6, 5, 4, 3], [7, 6, 4, 4, 4], [7, 5, 5, 5, 3], [7, 5, 5, 4, 4], [6, 6, 6, 5, 2],
[7, 7, 6, 3, 2], [7, 7, 5, 4, 2], [7, 7, 4, 4, 3], [7, 6, 6, 4, 2], [7, 6, 5, 5, 2],
[8, 6, 5, 4, 2], [8, 6, 4, 4, 3], [8, 5, 5, 5, 2], [8, 5, 5, 4, 3], [8, 5, 4, 4, 4],
[9, 4, 4, 4, 4], [8, 8, 4, 3, 2], [8, 7, 5, 3, 2], [8, 7, 4, 4, 2], [8, 6, 6, 3, 2],
[9, 7, 4, 3, 2], [9, 6, 5, 3, 2], [9, 6, 4, 4, 2], [9, 5, 5, 4, 2], [9, 5, 4, 4, 3],
[11, 4, 4, 4, 2], [10, 6, 4, 3, 2], [10, 5, 5, 3, 2], [10, 5, 4, 4, 2], [10, 4, 4, 4, 3],
[12, 4, 4, 3, 2], [11, 5, 4, 3, 2], выбираем любой, перемешиваем :)
Это позволит избавиться от формирования списка пересечений (он и сейчас по сути не нужен, можно же сразу искать минимум) и даст хороший выигрыш в скорости, если стена близко.
В моём понимании делать ставку на малые размеры поля нельзя, даже в Wolfenstein 3D образца 1992 года карта была 64*64 = 4096 — это в разы больше высоты экрана в пикселях (1080).
# for each cell in map get collision wiht it, if exists
В оригинальной статье луч шёл до первого пересечения (https://github.com/ssloy/tinyraycaster/blob/master/tinyraycaster.cpp), читая только те пустые блоки, через которые луч проходит, никаких других collisions не нужно.
Оригинальный цикл был прост:
Если подумать, то 50 раз проверять что луч в одной и той же пустой клетке необязательно, после вычисления первых пересечений с горизонтальными и вертикальными линиями дальше можно шагать сразу по пересечениям сетки от ближнего к дальнему пока не попадём в стенку.
4й вариант где на 3 типа написано 9 функций сравнения плохо масштабируется при увеличении числа типов.
5й в принципе можно легко переделать и параметризовать, если очень надо без RTTI, то выбрал бы его.
Приоритет при сортировке на мой взгляд привязан к параметрам сортировки, и элементы об этом ничего знать не должны.
Это исключает варианты 1 — 6 (6 вообще костыльный с побочными эффектами)
Вариант 7 и 8 похожи, но смысла возиться со строками нет, тем более писать для этого методы элемента, по сути дублирование встроенного RTTI.
Вариант 9 на мой взгляд плохо расширяем из-за строгой типизации
Они не эквивалентны в случае, если итерируемый список изменяет длину в процессе итерации поскольку диапазон range фиксируется по длине в начале цикла и потом не меняется.
Я имел ввиду что вес одного самореза можно посчитать и вынести в отдельный артикул. Допустим их 500 штук на килограмм при цене 200 рублей за кило. Это 40 копеек штука. Ну сделайте навар и округлите до 1 рубля. Если мне нужно 3 штуки это выгоднее покупки 40 грамм. Лишние саморезы все равно станут мусором в кладовке, который будет храниться годами.
Или исправить весы, чтобы не изводить бумагу на нулевые чеки.