Я наткнулся на вопрос на сайте Code Review , что кажется интересным. Я думаю, что OP делает это неправильно, но не может быть уверен ... Так что давайте решим это для него! (написать программу, а не функцию / процедуру)
Ввод (стандартный или аналогичный):
Целое число x
в десятичной записи. Это больше чем 1 и меньше чем 2 ^ 31.
Выход (стандартный вывод или аналогичный):
Целое число y
в десятичной записи. Продукт x * y
в десятичном представлении должен содержать только цифры 0 и 1. Это должно быть минимальное такое число больше 0.
Примечание: вывод не ограничен - если минимальное значение y
составляет около 10 ^ 100, ваша программа должна вывести все свои 100 цифр (я не знаю, существует ли разумный предел, например 2 ^ 64, y
- не удалось его решить ).
Ваша программа должна завершиться за разумное время (1 секунда или 1 час? - что-то в этом роде) для всех x
в диапазоне.
Бонус:
Если ваша программа не имеет ограничений на размер входных данных (кроме ОЗУ) и имеет полиномиальную сложность, умножьте количество байтов вашей программы на 0.8
и округлите вниз.
Пример: ввод 2
; выход 5
, потому что 2 * 5 = 10
Пример: ввод 21
; выход 481
, потому что 21 * 481 = 10101
Отказ от ответственности: я не несу ответственности за вопрос на сайте Code Review. В случае любого несоответствия, только описание выше должно рассматриваться как правильная спецификация.
Ответы:
Pyth, 9 байт
демонстрация
Для каждого кратного числа преобразуйте в строку, вычтите цифры
10
(используя в этом случае удобную для Pyth int для str) и затем логически отрицайте результат, прерывая поиск только тогда, когда найдено правильное кратное число.Бонусное решение, 10 байт:
Это решение фактически проверяет, может ли строковое представление числа рассматриваться как двоичное число (
i ... 2
), и завершается, когда при этой попытке не выдается ошибка.источник
Python 2, эффективное решение, 99
Спасибо Sp3000 за некоторые советы по игре в гольф.
Я призываю всех остальных опубликовать (в своих собственных ответах), сколько времени потребуется, чтобы получить результат для ввода
72
или99
:) Если они действительно быстрые, попробуйте что-то вроде79992
следующего (все еще <1 сек. Здесь).Объяснение:
Я думал, что в этом нет необходимости (так как код достаточно читабелен), но я получил запрос, так что вот оно:
Первая идея состоит в том, что двоичное число представляет собой сумму 1 или более различных степеней 10. Поэтому мы можем пытаться добавлять различные степени 10 по-разному, пока не получим остаток 0.
Если мы делаем это наивно, это то же самое, что генерировать все двоичные числа и проверять их. Но многие остатки останутся прежними. Лучший способ - записать только наименьшее число, которое дало определенный остаток, и последовательно прибавлять 10 к числу, которое мы записали. Это то, что делает программа.
d
это словарь / карта, где ключи - это остатки, а значения - двоичные числа с этим остатком. Инициалn:0
- это особый случай: он должен быть0:0
таким, чтобы мы могли начать добавлять к нему полномочия, но алгоритм останавливается при поиске ключа 0, поэтому я использовалn
вместо этого, что гарантированно будет иметь тот же эффект и не мешать другим значениям.Затем мы начинаем прибавлять степени 10 (хранятся в
k
) ко всем существующим числам и записывать остатки. Мы добавляемk
к остатку:(x+k)%n
и к числу:d[x]+k
и записываем его, только если это новый остаток:,d.setdefault(…)
затем переходим к следующей степени:k*=10
и повторяем, пока не получим ключ 0:while min(d)
В конце
d[0]
дает двоичное число с остатком 0 modn
, поэтому мы делим егоn
на полученное решение.Примечание: программу можно сделать более эффективной, избегая больших чисел (запись показателей степени, а не степеней 10 и вычисление остатков степеней от предыдущих значений), но это код гольф, так что ...
На самом деле, здесь я написал более быструю версию:
источник
Python 2, 47 байт
Отслеживает введенный номер
n
и текущий множительa
. Когдаa
выглядит как двоичный файл, выведите соотношениеa/n
. Чтобы проверить, что число состоит из0
's' и1
's', мы сравниваем максимальное значение char в его строковом представлении с'1'
.Пользы
str(a)
вместо того,`a`
чтобы избежать длинных, заканчивающихся наL
. К сожалению,'L'
больше, чем'1'
.источник
Perl, 27 байт
Считая Шебанг как единое, ввод берется из стандартного ввода.
Образец использования
Perl, 25 байт
Двухбайтовое улучшение @skmrx .
Вместо проверки на регулярное выражение вместо этого делается попытка оценить продукт как двоичный литерал. При неудаче он переходит к следующему. Типично
oct
функция используется для этой цели, но она молча обрезает недопустимые цифры, что бесполезно в этой задаче.Perl, 40 байт
Гораздо более эффективное решение. Мы перебираем двоичные представления, интерпретируем их как основание 10, а затем проверяем на делимость. Время выполнения для всех значений до 100 пренебрежимо мало.
Образец использования
источник
eval"0b".$_*++$\||redo}{
use bigint
поддержку больших чисел, которые OP обязал поддерживать :(oct'0b'.++$\*$_
, но он молча обрезает недействительные цифры. Я не думал использоватьeval
вместо этого.Javascript, 43 байта
Это оказалось короче, чем я думал. Это в основном увеличивается
y
до 1 доy * (input number) = (binary-looking number)
. Очевидно, совершенно неэффективно.Javascript (более эффективное решение), 53 байта
Этот шаг увеличивается
y
в двоичном формате доy / (input number) = (number without a remainder)
. Тогда это выводит(number without a remainder)
.Javascript (еще более эффективное решение), 76 байт
Этот объединяет оба предыдущих метода, описанных выше. Он проверяет приращения
y
до тех пор, покаy * (input number) = (binary-looking number)
( либо означает, что выходные данныеy
), или ИЛИy / (input number) = (number without a remainder)
(означает, что выходные данные есть(number without a remainder)
).источник
Haskell,
7270646058 байтРедактировать: @ Ян Дворак помог мне сэкономить 4 байта.
Редактировать: @BlackCap сохранил 2 байта, переключившись на
do
нотацию. Благодарность!источник
main=print.f=<<readLn
main=readLn>>= \x->print$[y|y<-[1..],all(<'2')$show$x*y]!!0
main=do x<-readLn;print$[y|y<-[1..],all(<'2')$show$x*y]!!0
Python 2,
67656360 байтСпасибо Status за 2 байта и Shebang за 5 байтов!
источник
b=1
any(c in`a*b`for c in'23456789')
not c in`a*b`for c in'10'
работать?set('a*b')&set('23456789')
.`
производитL
на долго и'L'>'1'
.JavaScript (ES6) 222
250Использование математики произвольной точности (работа со строками десятичных цифр)
Это может быть немного больше(сделано), но мне нравится тот факт, что он не ограничивается стандартными числами JS (17 десятичных цифр точности) и что это быстро.Попробуйте запустить приведенный ниже фрагмент в браузере, совместимом с EcmaScript 6. Время приемлемо до 9998 - не пытайтесь 9999 и будьте терпеливы с 999.
Более читаемый
Это первая версия с модулем и длинным делением в качестве отдельных функций.
источник
Perl, 45 байт
источник
Pyth, 10 байт
Запустите код.
Порт моего Python-ответа , взявший у Малтисена использование
f
для поиска первого положительного числа, удовлетворяющего условию.источник
PHP, 50 байт
Некоторые тестовые случаи
источник
CJam,
191716 байтовПопробуйте онлайн
Решение грубой силы, пробуя значения последовательно, пока не будет найдено одно условие.
Последняя версия экономит 2 байта благодаря использованию
As
вместо"01"
построения строки, содержащей0
и1
, как предлагает @aditsu. Полное предлагаемое решение в комментарии сохраняет еще один байт, но выглядит он совсем не так, как мой, поэтому я не хотел публиковать его под своим именем.И еще 1 байт, сохраненный @Dennis.
Объяснение:
источник
li0{1$+_sAs-}g\/
As
строку, чтобы построить строку, так как это очень локальное изменение, о котором в ретроспективе (что всегда намного проще ...) я должен был подумать.li:V!{)_V*sAs-}g
также0{)_easi*sAs-}g
(15 байт) работает с интерпретатором Java и аргументами командной строки.Python
32,10176 байт-25 байт благодаря @aditsu
почти так же эффективно, как решение @ aditsu
Вместо того, чтобы пытаться перебирать мультипликаторы в возрастающем порядке, я пытаюсь перебрать продукты, которые я генерирую в «двоичной» форме.
источник
n=input()
),while b%n:
(инициализируйтеb
до 1), без отступовbin(m)[2:]
должен быть короче строки формата. Двойное назначениеb=m=1
должно также спасти несколько.Java, 213 байт
Пользы
BigInteger
s и как таковой имеет (для всех разумных намерений и целей) неограниченный размер ввода. Не уверен насчет сложности, хотя, это зависит от скорости роста нашей функции здесь.Спасибо geobits и ypnypn за сохранение нескольких байтов.
источник
static
модификатор к методу.b.ONE
и!(b.multiply(c)+"")
(вместоtoString()
).C 3675 байт
Так долго для Code Golf ...
Запуск без параметров командной строки - она получает
n
отstdin
и выводит результатstdout
. Запустите с именем файла - он записывает результатыn = 1...10000
в этот файл и измеряет время.Производительность за 1 ... 10000: 140 мс
Этот код использует алгоритм, предложенный aditsu , реализованный на C для скорости. Я не приложил усилий, чтобы поиграть в гольф, поэтому код будет легче читать.
Я реализовал это сначала в C ++, используя
std::map
для записи результатов поиска, и это было довольно медленно. Однако ключиmap
являются последовательными целыми числами (я называю ихmod
s, потому что они представляют числа по модулюn
), поэтому естественно использовать массив - поэтому я переписал его на C.Дополнительная оптимизация касается значений отображения - во избежание хранения большого целого числа для каждого
mod
я сохраняю там только наибольшую степень 10 - достаточно информации, чтобы перейти к предыдущемуmod
. Таким образом, массив - это действительно поисковое дерево / граф. Когда поиск прибываетmod = 0
, отслеживание узлов дерева назад к корню дает полномочия 10 в порядке убывания.Так как поиск обычно останавливается довольно быстро, и посещается только небольшая часть узлов, мне нужен список активных узлов. Он реализован в виде массива
mod_list
с длинойmod_list_length
.Немного статистики во время выполнения (на машине с 16 ГБ ОЗУ, что кажется важным для больших
n
, потому что программа выделяет5n
байты памяти):99999999
- 2 секунды999999999
- 27 секунд (результат111111111222222222333333333444444444555555555666666666777777777888888889
- вероятно, самый большой возможный результат для 32-разрядных целых)2147483647
- 26 секунд (результат есть4661316525084584315813
)1999999998
- 52 секунды (вероятно, самое длинное время выполнения для 32-разрядных целых чисел)источник
C ++ 11, много байтов, очень быстро, вау (1,5 с на 1999999998, 0,2 с на 1… 10000)
(Гольф-версия Python ниже.)
Мы начнем с концепции, несколько похожей на решение aditsu, где мы индуктивно создаем коллекцию модульных остатков, достижимых за n шагов. Но вместо того, чтобы ждать, пока мы не найдем остаток 0, мы проверяем два найденных остатка a и b, так что a · 10 ^ n + b = 0. Такой подход к встрече в середине сокращает вдвое глубину дерева поиска, поэтому намного быстрее на больших входах и использует намного меньше памяти.
Некоторые тесты:
Код:
Python, 280 байт (8,6 секунды на 1999999998 с PyPy)
источник
Mathematica 115 байтов
источник
Java 156 байт
Огромное спасибо адицу :)
источник
[]
,y
может бытьlong
, вы забылиx*y+""
хитрость во 2-й программе, используйтеisEmpty
вместо проверки длины, используйте;
вместо{}
long
если вы сделаете y , код не станет корочеlong x=…,y;
y
должно начинаться с 1, вы можете инициализировать его в объявлении, ваш класс не должен быть публичным, и вы можете перейтиy++
кx*y
части (x*y++
)Pyth -
1211 байтИспользует фильтр с числовым аргументом, чтобы получить первое натуральное число, которое соответствует предикату, по умолчанию 1, что мы и хотим. Поочередно diff, чтобы проверить, если только нули и единицы.
Тестовый пакет .
источник
"01
. Сохраняет один символR, 45 байт
Использование:
источник
Джава,
198193181 байтСпасибо @aditsu за сокращение 5 байтов и увеличение диапазона тестируемых чисел!
Обратите внимание, что некоторые значения зацикливаются отрицательно из-за того, что Java анализирует целые числа. BigInteger мог обойти это, но бонус был просто менее ценным.
Я знаю, что не собираюсь побеждать, но я надеюсь, что это вдохновит других, более короткие ответы.
Ungofled:
источник
Long
корочеInteger
:)C
107101 байт (10599 байт для 32-бит)Существует явный недостаток ответов в C на коде гольф. Действительно, C не лучший выбор для написания самой маленькой программы, но это не так уж и плохо:
Вы можете обойтись без #include, но тогда все определения функций будут неявными. Основным недостатком является то, что это вызывает предположение, что все функции возвращают целые числа. Это проблема на 64-битных машинах для функций, которые фактически возвращают указатель. Если вы работаете на 32-битной машине, 2 байта могут быть сброшены с помощью вышеуказанного решения:
Несколько более читаемая версия:
источник
Время C # около 5 секунд (от 1 до 10000)
В соответствии с просьбой, здесь есть программа C # для игры в гольф, отвечающая на первоначальный вызов. Ввод в качестве аргумента командной строки, вывод в консоль.
Затем, что касается вознаграждения: вознаграждение должно идти к aditsu, поскольку я думаю, что его алгоритм не может быть побежден с точки зрения производительности. Но самоответ Анатолия тоже удивителен.
Вот моя быстрая реализация в C #. Я полагаю, что в C ++ это может быть быстрее (возможно, в 2 раза). Скомпилировано и протестировано с Visual Studio 2010, .NET Framework 4, 64 бита, перенаправляя вывод в nul. Время: 00: 00: 05.2604315
источник
Keys.Reverse
? Важен ли порядок? Если это просто, чтобы избежать проблем параллелизма,ToList
короче.C с GMP (621 байт, быстрый)
Я пытался быть быстрым и коротким, но предпочитал быстро. В этой реализации используется слегка улучшенная версия теоретико-числового ускорения, о котором я упоминал в комментарии к ответу aditsu .
Сохранить как
pseudobinary.c
и скомпилировать сgcc pseudobinary.c -lgmp -o pseudobinary
. Обратите внимание, что это выделяет так много памяти для больших входов, что вам нужно будет скомпилировать ее для 64-битной платформы.Версия цикла для синхронизации (751 байт)
Версия без петель
источник
C + GMP, 669
Это действительно быстро для небольших чисел; он начинает задыхаться, когда результат имеет более 64 цифр.
Версия с циклом до 10000 (671 байт):
Вот несколько команд для тестирования моего кода, а также моих конкурентов и результатов на моем ноутбуке:
источник
T-SQL,
164156155154159 байт(-1 байт. Спасибо Джонатан!)
(-1 больше, потому что почему у меня в конце есть пробелы? SMH)
(+5 понял, что мой гольф сломал вещи)
Я не знаю, почему я продолжаю возвращаться к этим вопросам, где я должен конвертировать в Binary ... T-SQL не знает, как это сделать правильно.
В любом случае, вот SQLFiddle .
Un-golfed:
Насколько я знаю, большая часть этого материала требуется для написания функции на T-SQL.
Создайте пустую строку, которую мы будем хранить как наше двоичное число.
Сохраните входное значение для использования в конце. Кажется, должен быть способ использовать исходный ввод, даже если мы изменим значение, но я не могу его найти.
Итак, мы берем наш исходный ввод, изменим его на 2, чтобы найти остаток, и это будет наша следующая маленькая цифра. Например, 5% 2 = 1
Затем мы берем наш номер и делим его пополам. Поскольку это
int
тип, он округляет его до ближайшего целого числа, поэтому 5/2 = 2. КОНЕЦ Затем мы перебираем это до тех пор, пока значение не станет 0. Таким образом, мы в итоге получим 5% 2 = 1 5/2 = 2 2 % 2 = 0 2/2 = 1 1% 2 = 1 1/2 = 0, что дает нам значение нашей двоичной строки 101.Мы берем нашу двоичную строку и снова конвертируем ее в
int
.Мы возвращаем нашу двоичную строку,
int
деленную на наше исходное значение, в соответствии с источником вопроса.источник
@>0 SELECT
Не пропущено ли пространство ?Рубин, 46 байт
Я действительно должен исключить цикл while с помощью альтернативного цикла.
Редактировать: Спасибо @manatwork за сбрить 1 байт!
Edit2: Спасибо @histocraft за безумные 9 байтов!
Редактировать: Спасибо @manatwork еще раз за сбрить 7 байтов!
источник
z!=z[/[01]+/]
корочеz[/[^01]/]
еще короче.z="#{n.to_i*k+=1}"while z[/[^01]/]
Скала, 114 байт
Читаемая версия
источник
gawk4 перебор, 28 + 2 = 30 байт
Должен быть вызван с
-M
возможностью использования больших чисел. Конечно, это смехотворно медленно, использование больших чисел замедляет его еще больше, но теоретически вход не ограничен, а использование ОЗУ незначительно.Пример использования (если у вас есть время впустую
;)
)gawk4 оптимизирован, 69 + 2 = 71 байт
Ну, это закончилось тем, что стало клоном ответа Адицу. Посмотрев на этот вопрос, я все еще выяснял, как закодировать часть суммы подмножества, когда я не мог удержаться, глядя на другие ответы здесь.
В массиве awk элементы имеют (странное?) Поведение, которое заключается в том, что если вы сравниваете несуществующий элемент с чем-то, он каким-то образом инициализируется как пустой перед сравнением (я признаю, что не совсем уверен в том, что там происходит). Таким образом , после проверки
!a[0]
наfor(i in a)
цикл начинается даже без инициализацииa[$0]
для0
как и aditsu.Конечно,
-M
опция должна быть использована и для этого.Хотя он довольно быстрый, он все же заметно медленнее, чем Python. На
79992
это уходит 2 секунды на моем 2GHz Core2Duo. И я бы не сказал, что он работает для входов до 2 ^ 31, потому что в худшем случае он должен создать массив больших чисел (для этого gawk4 использует GMP), который имеет размер входного числа. В качестве «бонуса» большие массивы очень-очень медленно работают в awk ...источник
Дьялог АПЛ , 25
Это определяет правильную программу «P» (не просто безымянную функцию):
2∘
начинайте с 2 в качестве левого аргумента,0::
если есть какая-либо ошибка ...⍵∇⍨1+⍺
вызывайте себя с увеличенным левым аргументом,⍺×⍵
умножайте левый и правый аргументы,⍕
превращая их в строку,⍎¨
превращайте каждый символ в~
попытку числового логического НЕ (в случае неудачи перейдите к обработке ошибок выше, еще ...)⍺⊣
вернуть текущий левый аргумент.источник