Расстояние Хэмминга между двумя строками одинаковой длины - это число позиций, в которых соответствующие символы различны.
Позвольте P
быть двоичной строкой длины n
и T
двоичной строкой длины 2n-1
. Мы можем вычислить n
расстояния Хэмминга между подстрокой P
каждой n
длины T
в порядке слева направо и поместить их в массив (или список).
Пример последовательности расстояний Хэмминга
Пусть P = 101
и T = 01100
. Последовательность расстояний Хэмминга, которую вы получаете от этой пары, такова 2,2,1
.
задача
Для увеличения, n
начиная с n=1
, рассмотрим все возможные пары двоичных строк P
длины n
и T
длины 2n-1
. Есть 2**(n+2n-1)
такие пары и, следовательно, много последовательностей расстояний Хэмминга. Однако многие из этих последовательностей будут идентичны. Задача состоит в том, чтобы найти, сколько разных для каждого n
.
Ваш код должен выводить одно число на значение n
.
Гол
Ваша оценка - самая высокая, которую n
ваш код достигает на моей машине за 5 минут. Время для общего времени работы, а не время только для этого n
.
Кто выигрывает
Человек с наибольшим количеством очков побеждает. Если два или более человека имеют одинаковый результат, выигрывает первый ответ.
Пример ответов
Для n
от 1
до 8
оптимальных ответов на этот вопрос 2, 9, 48, 297, 2040, 15425, 125232, 1070553
.
Языки и библиотеки
Вы можете использовать любой доступный язык и библиотеки, которые вам нравятся. Там, где это возможно, было бы хорошо иметь возможность запускать ваш код, поэтому, пожалуйста, включите полное объяснение того, как запускать / компилировать ваш код в Linux, если это вообще возможно.
Моя машина Время будет работать на моей 64-битной машине. Это стандартная установка Ubuntu с 8 ГБ ОЗУ, восьмиъядерным процессором AMD FX-8350 и Radeon HD 4250. Это также означает, что мне нужно иметь возможность запускать ваш код.
Ведущие ответы
- 11 в C ++ по feersum. 25 секунд
- 11 в C ++ Эндрю Эпштейн. 176 секунд
- 10 в Javascript от Нила. 54 секунды
- 9 в Хаскеле Ними. 4 минуты и 59 секунд.
- 8 в Javascript от fəˈnɛtɪk. 10 секунд.
fastest-code
оставляет больше места для оптимизаций благодаря оптимизации на уровне кода и хорошему алгоритму. Так что я думаю, чтоfaster-code
это лучше, чемfaster-algorithm
.Ответы:
C ++ 11 (должно доходить до 11 или 12)
На данный момент это однопоточный.
Компилировать:
источник
feersum.cpp:111:61: warning: shifting a negative signed value is undefined [-Wshift-negative-value] int middle = int(s >> npre * MAX_N_BITS) & ~(~0 << MAX_N_BITS);
Хаскелл, оценка 9
Компилировать с
-O3
. На моем 6-летнем ноутбуке требуется 6 минут 35 секундn=9
, поэтому на эталонном оборудовании это может быть меньше 5 минут.источник
JavaScript, оценка 10
Объяснение: Расчет
n=10
затруднен, поскольку существует более двух миллиардов пар и более 26 миллиардов потенциальных последовательностей. Чтобы ускорить процесс, я разделил расчет на 121 лот. Поскольку последовательности инвариантны относительно побитового дополнения, я могу предположить без ограничения общности, что средний битT
равен нулю. Это означает, что я могу определить первый и последний элементы последовательности независимо от верхнихn-1
и нижнихn-1
битовT
, Каждый контейнер соответствует разной паре первого и последнего элементов; Затем я перебираю все возможные наборы верхних и нижних битов, которые соответствуют каждому бину, и вычисляю оставшиеся элементы последовательности, наконец, подсчитывая уникальные последовательности для каждого бина. Затем остается всего 121 корзина. Первоначально это заняло 45 часов, теперь это заняло чуть меньше трех с половиной минут на моем AMD FX-8120. Редактировать: Спасибо @ChristianSievers за 50% ускорение. Полный вывод:источник
n
в качестве параметра. (Извините за неправильный выбор имени параметра там.)n=1
(не знаю, почему она зависает).С ++, оценка
1011Это перевод ответа @ Neil на C ++ с некоторым простым распараллеливанием.
n=9
завершается за 0,4 секунды,n=10
за 4,5 секунды иn=11
примерно за 1 минуту на моем Macbook Pro 2015 года. Также спасибо @ChristianSievers. Из-за его комментариев к ответу @ Neil, я заметил некоторые дополнительные симметрии. От первоначальных 121 сегмента (дляn=10
) до 66 сегментов при учете аннулирования я получил всего 21 сегмент.Используйте следующий скрипт для выполнения кода:
Вывод был следующим: (формат
M: result, seconds
)n=12
потребовалось 42 минуты, чтобы рассчитать на один поток, и дал результат 7368225813.источник
sudo apt-get install libiomp-dev
.__builtin_popcount
.__builtin_popcount
в контексте constexpr. Я мог бы пойти с наивной реализацией, и это не повлияло бы на время выполнения.JavaScript 2,9,48,297,2040,15425,125232,1070553,9530752
Запустите в консоли:
Попробуйте онлайн!
Или как фрагмент стека:
Показать фрагмент кода
Код инициализирует массив для ускорения добавления единиц в массив.
Код находит все последовательности расстояний Хэмминга и обрабатывает их как основание чисел (input + 1), использует их для размещения единиц в массиве. В результате создается массив с n 1, где n - количество уникальных последовательностей расстояний Хэмминга. Наконец, число 1 с подсчитывается с помощью array.reduce () для суммирования всех значений в массиве.
Этот код не сможет работать для ввода 10, так как он достигает пределов памяти
Этот код выполняется за O (2 ^ 2n) времени, потому что именно столько элементов он генерирует.
источник
n = 9
Мне нужно 5 минут и 30 секунд, используя node.js, так что это слишком медленно.n = 8
Изначально @Lembik на моем ПК заняла 24 секунды, но я смог оптимизировать код, так что этоn = 8
заняло 6 секунд. Затем я попытался,n = 9
и это заняло 100 секунд.