Вам дается в качестве входных данных две строки, представляющие натуральные числа в базе 10, такие как "12345"
и "42"
. Ваша задача - "518490"
в этом случае вывести строку, содержащую их продукт .
Суть в том, что вы не можете использовать любые числовые типы в вашем коде. Нет ints
, float
s, unsigned long
s и т. Д., Нет встроенных типов комплексных чисел или целых чисел произвольной точности, или что-нибудь в этом роде. Вы часто не используете литералы этих типов, ни какие-либо функции, методы, операторы и т. Д., Которые их возвращают.
Вы можете использовать строки, логические значения, массивы или что-либо еще, что обычно не используется для представления числа. (Но учтите, что ни индексация в массиве, ни получение его длины, вероятно, невозможны без вызова числового типа.) char
Разрешены, но вы не можете выполнять над ними какие-либо арифметические или побитовые операции или иначе рассматривать их как что-то другое, кроме токен, представляющий часть строки. (Лексикографическое сравнение char
s допускается.)
Вы не можете обойти ограничение. Это включает (но не ограничивается) использование числовых типов внутри eval
функции типа, неявное преобразование типов в числовые типы, использование числовых или побитовых операторов для нечисловых типов, которые их поддерживают, использование числовых типов, хранящихся в типах контейнеров, или вызов функций или внешние программы, которые возвращают числовые результаты в виде строки. (Я оставляю за собой право добавить в этот список, если в ответах появятся другие обходные пути.) Вы должны сами выполнить умножение, используя только нечисловые типы.
Ввод и вывод могут быть любым удобным способом, если данные входят и выходят из вашего кода в виде строки. Можно предположить, что каждый из двух входных аргументов содержит только символы ASCII [0-9]
и не будет начинаться с 0
. Ваш вывод также не должен иметь ведущих нулей.
Еще одна вещь: ваш код должен правильно обрабатывать вводы длиной не менее 10 символов и должен выполняться менее чем за минуту на современном компьютере для всех входов в этом диапазоне. Перед тем как отправить, пожалуйста , проверьте , что при предоставлении входа 9999999999
и 9999999999
ваша программа дает выход 99999999980000000001
, менее чем за минуту. Это ограничение существует специально для предотвращения ответов, которые работают путем выделения массива размера a*b
и последующей итерации по нему, поэтому имейте в виду, что ответы этой формы не будут иметь права на победу.
Это код-гольф , поэтому выигрывает самое короткое действительное решение (в байтах).
источник
"12345"
от STDIN, а не12345
? Или мы можем принять оба числа как"12345", "42"
?m
иn
и возвращает аргумент длиныm*n
. Но так как строки должны буквально содержать ASCII-представление чисел, я думаю, что это противоречит правилам.a,b="0123456789x".split('0');c=iter(b).next()
if c=='x':
c='0'
a,b="0123456789x".split(x);c,*d=b
if c=='x':
c='0'
d='123456789';I=dict(zip('0'+d,d+'0'))
Ответы:
Хаскелл - 180
206 214Реализует умножение путем повторного сложения, а все виды магии цифр обрабатываются путем сдвига и фильтрации
['0'..'9']
списка. Определяет оператор#
типаString -> String -> String
:источник
"0123456789"
- это список['0'..'9']
. Во-вторых, в Haskell [a..b] есть перечисление, типы, которые объявили экземпляры классаEnum
типов, могут быть перечислены таким же образом, и объявление описывает, как работает перечисление.Bool
, логический тип также имеет экземпляр, и поэтому вы также можете сделать[False..True]
. Есть только какие-то цифры.sed,
339338 байтЯ знаю, что это старый, но я просматривал, и это пробудило мой интерес. Достаточно реально зарегистрироваться как пользователь! Я думаю, меня поразило « Я бы очень хотел увидеть полное решение sed - Натаниэль » ...
Этот скрипт Sed ожидает двух десятичных чисел в качестве ввода, разделенных одним пробелом
Тесты:
Вы можете распознать последние два как RSA-100 (50 x 50 цифр) и RSA-768 (116 x 116 цифр).
Использование GNU sed на не очень современном (Intel Core 2 2007 года) последнем из них занимает больше минуты, но быстрее на более новом процессоре:
Младшее десятизначное умножение, указанное в вопросе, занимает менее секунды на любом из них (несмотря на то, что в нем полно патологических девяток).
Я полагаю, что это стандартный sed, без расширений. POSIX гарантирует хранение только 8192 байтов, что ограничивает нас умножением 400х400 цифр, но реализации могут обеспечить больше. GNU sed ограничен только доступной памятью, поэтому может управлять чем-то намного большим, если вы готовы подождать.
И я уверен, что я выполнил правила - это почти что дано в языке, в котором нет цифр. :-)
объяснение
Я использую унарный / десятичный гибрид, преобразовывая десятичные числа в последовательность унарных:
В одинарном десятичном виде сложение легко. Мы выполняем итерацию от наименее значимой к наиболее значимой цифре, объединяя x:
Затем мы удаляем пробелы и работаем с переносом, конвертируя 10 последовательных x в один из следующих блоков:
Как только у нас есть сложение, возможно умножение. Мы умножаем x * y, учитывая последнюю цифру y. Добавьте x к аккумулятору столько раз, затем перейдите к следующей цифре и сдвиньте x на один знак после запятой влево. Повторяйте, пока у не станет ноль.
Расширенный код
источник
sed, 379 байт
Благодарность за этот блестящий ответ идет @LuigiTiburzi на Unix & Linux.SE: https://unix.stackexchange.com/a/37213/34061 . Я просто случайно наткнулся на это несколько дней назад:
Широкое объяснение
12*3
становится<1<2*<3
|
символов. Таким<1<2*<3
становится<|<||*<|||
|<
с<||||||||||
тем чтобы переложить более высокие знаков после запятой все вплоть до позиции единиц. Таким<|<||*<|||
становится<||||||||||||*<|||
<
. Таким<||||||||||||*<|||
становится||||||||||||*|||
|
из RHS в*
. Таким||||||||||||*|||
становится||||||||||||*||
|
на RHS на все|
на LHS. Это имеет эффект умножения левой и правой частях числа ,|
чтобы дать номер продукта из|
Таким образом ,||||||||||||*||
становится||||||||||||||||||||||||||||||||||||*
*
. Таким||||||||||||||||||||||||||||||||||||*
становится||||||||||||||||||||||||||||||||||||
|
обратно в десятичную с обратной стороны первых нескольких шагов. Таким||||||||||||||||||||||||||||||||||||
становится36
.Выход:
К сожалению, это с треском проваливается из-за требований ко времени -
200*1000
на моей виртуальной машине Ubuntu уходит 41 секунда, и время выполнения эмпирически возрастает с квадратом конечного продукта.источник
length()
который возвращает число. Этот использует чисто подстановку регулярных выражений без числовых типов. Я думаю, что ваш ответ потенциально победит, хотя, если вы можете удалитьlength()
- возможно, вы могли бы вместо этого сделать какую-то аналогичную замену регулярному выражению?Питон -
312286273Если (много) начальных нулей разрешены, последние 12 символов не нужны.
По сути, это выполняет стандартное умножение вручную. Цифры представлены в виде строк повторяющихся
I
s (как примитивные римские цифры). Числа представлены в виде списков цифр в обратном порядке. Добавление однозначных чисел осуществляется путем объединения строк и удаления десятиI
секунд при необходимости.Вот негольфированная версия:
источник
def A(x,y):\n S=[];o=""
->def A(x,y,S=[],o=""):
. Также, к сожалению,["","1"][t in i]
это не разрешено; он использует bool для индексации, рассматривая его как число. Я думаю, что этоt in i and"1"or""
должно работать, хотя.S
в качестве аргумента по умолчанию не сработало бы, так как он всегда был бы одним и тем же списком даже для разных вызовов функции и, следовательно, не сбрасывался до[]
. Вы были правы["","1"][t in i]
, я исправил это. Я также добавил объяснение.Рубин:
752698Это просто чтобы получить ответ, просто сделано из любопытства. Отредактировано: сейчас немного поиграл в гольф.
Использование: У меня было это в файле с именем peasant.rb:
Объяснение: это крестьянское умножение, поэтому я многократно делю пополам. Деление пополам осуществляется путем деления пополам цифр и разметки остатков следующим образом: 1234 -> 0b1a1b2a; затем найдите и замените на b: 06a17a; затем уборка -> 617.
Сложение выполняется так ... во-первых, я дополняю обе строки до одинаковой длины и делаю пары из цифр. Затем я добавляю цифры, создавая строку, имеющую длину каждой цифры, и объединяю ее; Я удаляю строку такой длины с начала «0123456789abcdefghij», а затем сохраняю первый символ. Так, например, «9» + «9» -> «i». NB. Я избегаю фактически использовать здесь функции длины, чтобы полностью избежать типов чисел; удаление префикса выполняется с помощью регулярного выражения.
Так что теперь у меня есть строка, содержащая смесь цифр и букв. Буквы представляют цифры с переносной цифрой; Я добавляю 0 к числу, затем многократно заменяю цифро-буквенные шаблоны на результат переноса, пока сложение не будет завершено.
источник
Brainfuck (1328 байт)
Сначала соображения:
Я тестировал программу только с моим собственным переводчиком, вы можете найти его здесь .
Входными данными должны быть оба числа, разделенные одним пробелом ASCII.
Golfed:
Ungolfed:
Я взял код для вывода значения из этого ответа , спасибо автору за это!
Программа может быть недействительной, но в любом случае я хотел бы поделиться ею с вами ^^
Обновление: Теперь Вы можете проверить это (только для небольших умножений) здесь, благодаря @ Sp3000 в ответ на этот конкурс и новый стек Snippets SE,!
источник
Питон,
394349340 символовБеги как:
Занимает 50 миллисекунд.
Использует русское крестьянское умножение . При добавлении цифр мы конвертируем их в унарные ('5' => [R, R, R, R, R]), объединяем списки и затем конвертируем обратно.
U
конвертируется в одинарный, используяR
в качестве одинарной цифры. Мы вычисляемb/=2
какb=b*5/10
.источник
def A(a,b):\n r='';c=[]
->def A(a,b,r='',c=[]):
, аналогично дляdef M
. Вы могли бы быть в состоянии изменитьfor z in D:d.pop()\n c=['X']
к[d.pop()for z in D];c=['X']
, в этом случае вы могли бы даже свернуть его на предыдущийif
. Кроме того, можетif list(b).pop()in'13579'
быть простоif b[:].pop()in'13579'
?b
это строка, а не список.M
и написать полную программу;a,b=input()
разрешено.reduce
, который позволяет nicenA(b,A(b,A(b,A(b,b))))
кreduce(A,[b,b,b,b,b])
. К сожалению, это не влияет на количество персонажей.JavaScript (E6) 375
395 411 449Редактировать Golfed
Редактировать Исправлена ошибка: отсутствует очистка флага переноса
Это может быть сделано с помощью только манипуляции с символами в почти 0 раз.
В этой версии вы можете использовать любой символ вместо цифр, если символ находится в порядке возрастания.
Примечания: использование строк, hashmap со строковым ключом, массивы, используемые в качестве списка. Нет индексации, массивы просматриваются с помощью «карты» или вращаются с помощью push & shift.
Все «+» являются конкатенацией строк.
Меньше гольфа (возможно, я добавлю объяснение завтра)
Тест в консоли FireFox / FireBug
Выход
источник
9999999999
дела должен быть99999999980000000001
, а не99999999980000000081
Haskell, 231 байт
Это определяет оператор #, который умножает два строковых представления натуральных чисел. Он работает путем определения элементарной операции увеличения / уменьшения строк, а затем использует ее для построения сложения и умножения. Небольшое дополнительное волшебство дает некоторые экспоненциальные ускорения, которые делают все это возможным.
Этот подход достаточно быстр, и даже на ноутбуке 2008 года в неоптимизированном ghci REPL тестовый кейс занимает доли секунды:
Вот проверка того, что все двузначные продукты верны:
источник
Bash + ImageMagick: 52
Ожидается, что входные данные будут в переменных оболочки
a
иb
. Это не особенно умно или эффективно, но это делает работу. Вероятно, это было сделано раньше.Обратите внимание, что
x
обозначает размеры изображения; в этом контексте это не арифметический оператор.Я не проверял это, но я готов предположить, что для неэкстремального ввода это завершится менее чем за одну минуту. Я могу проверить это завтра.
На случай, если с версиями ImageMagick возникнут забавные ситуации, я использую именно эту:
ImageMagick 6.7.7-10
источник
9999999999
и9999999999
.dd if=/dev/zero bs=$a count=$b 2>&-|wc -c
.9999999999x9999999999
Изображение в формате 8bit будет занимать все пространство на жестком диске , который существует в настоящее время на Земле. Конечно, png будет намного меньше, если вы сможете создать его без предварительного создания необработанного изображения. (Хотя я сильно подозреваю, что у вас будут проблемы с целочисленным переполнением изображения такого размера.) Но, тем не менее, такой метод почти наверняка не справится с лазейкой "вызывающие вещи, которые возвращают числовые результаты в виде строк".$b
вместо${b}
.grep -vc g
вместоgrep -v g|wc -l
.Python 2 (подтверждение концепции)
Это решение работает с использованием только строк и списков и небольшого регулярного выражения. Я считаю, что это полностью соответствует спецификации, за исключением того, что это невозможно сделать
9999999999x9999999999
за минуту. Хотя, учитывая достаточно времени, это сработает. Он может очень быстро умножить 4-значное число.Поскольку это технически недействительно, я еще не удосужился полностью сыграть в гольф. Я сделаю это, если правила изменятся.
Примеры:
источник
Python 2 (555)
Обычно я не отвечал на свой вызов так быстро (или вообще), но я хотел доказать, что это возможно. (К счастью, некоторые другие ответы делали это до этого, но я не мог не захотеть закончить это.) Есть еще кое-что, что можно сделать, но я думаю, что это разумно. Он обрабатывает
9999999999x9999999999
случай менее 0,03 с на моей машине.Пример использования:
m("12345","42")
Это работает, делая длинное умножение, используя строковые манипуляции. Иногда переменные являются строками, а иногда итераторами над строками, что позволяет получить первый элемент без использования целочисленного литерала. Все хранится с обратными цифрами, так что первый элемент является наименее значащей цифрой.
Вот объяснение функции за функцией:
r
иs
бухгалтерские функции. (r
это просто псевдоним дляreversed
, который создает обратный итератор иs
преобразует итераторы в строки.)i
увеличивает число в строке на 1, включая такие случаи, как39+1=40
и99+1=100
.b
добавляетx
иy
, ноy
должен быть только одна цифра. Это работает, увеличиваяx
y
время.a
добавляет два числа вместе, которые могут иметь несколько цифр, вызываяb
каждую цифру вy
.n
умножаетсяx
иy
, ноy
должен быть только одна цифра. Это работает, добавляяx
к себеy
время.o
умножаетсяx
иy
, где оба аргумента могут иметь несколько цифр. Он использует классическое длинное умножениеm
просто преобразует свои строковые входные данные в обратные итераторы и передает ихo
, затем инвертирует результат и преобразует его в строку.источник
def a(x,y):
->def a(x,y,z=''):
и удалить следующую строку; подобные приемы для других функций, вdef o(x,y):
, изменить ,x=s(x)
чтобыx=s(x);l='';z=''
, в том , что цикл, аналогично удалить новую строку + шаги; вместо этого используйте;
. Кроме того, я думаю, что этоif h!='0':h+=s(x)\nelse:h+=i(x)
может быть простоh+=h!='0'and i(x)or s(x)
; возможно дажеh+=(h!='0'and i or s)(x)
; в противном случае просто измените наif'0'!=h
. Также такие вещи, какdef r(x):return reversed(x)
->r=reversed
s
,m
:s=lambda x:''.join(x)
,m=lambda x,y:s(r(o(r(x),r(y))))
вместо всего объявления функции. Благодаря тому, что я знаю, что это работает, ваш счетчик байтов уменьшается до 521.for
циклов:for c in'0'+d:\nif c==y:break\nz=a(iter(z),x)
->for c in'0'+d:\nif c!=y:z=a(iter(z),x)
, хотя это может значительно изменить скорость вашей программы.JavaScript:
37103604 байтаГольф:
Разгулялся с тестами:
Это выводит:
источник
Haskell
507496Это работает для сколь угодно больших целых чисел. Я определяю пользовательские представления для натуральных чисел от 0 до 18 (самое большое натуральное число, равное сумме двух цифр), и определяю умножение с прямым порядком байтов в терминах умножения цифр * чисел, которое я определяю в терминах сложения числа + числа , который я определяю с точки зрения сложения цифра + цифра. У меня есть функция сокращения, которая расширяет 10-18 значений в их цифровое разложение. Затем он просто читает и переворачивает две строки, переводит в пользовательские привязки, умножает и переводит обратно, обращаясь, чтобы получить правильный результат.
Редактировать 2
Я сохранил несколько персонажей, создавая короткие локальные псевдонимы для команд несколько символов , которые я использую более чем один раз, а также удаление пробелов и скобок, а замена
(
-)
пары с ,$
когда это возможно.Для справки: S - это пользовательский целочисленный тип данных,
p
это «плюс» (сложение цифра + цифра),s
вычитание (для уменьшения),r
уменьшение (расширение в цифровую декомпозицию),a
сложение (сложение числа + числа),m
это умножить (цифра * умножение числа),t
это времена (умножение числа * числа),i
это «интерпретировать» (преобразовать строку в списокS
),b
«назад» (список из S в строку), а f и g - просто сокращения для игры в гольф цели. Я не использовал числа, даже неявно; самое близкое, что я получил, - это использование преемников и предшественников, которые являются математическими понятиями гораздо более высокого уровня, чем сложение и умножение натуральных чисел.редактировать
Забыл включить профиль времени.
Просто для хорошей меры:
Пойдем с ума!
подтверждение
источник
Питон 2 -
1165, 712, 668,664Обратите внимание, что я не использую подобное логическое индексирование
Z = [X, Y][N == "0"]
, потому что это может быть интерпретировано как логическое приведение к числовому индексу.Ungolfed:
источник
Скала, 470 символов
(
⇒
это стандартное scala, но его можно эквивалентно заменить на=>
подсчет байтов)Здесь мы эмулируем цифры, используя длину списков, стараясь не использовать никаких числовых операций - только сгибы, карты, почтовые индексы и тому подобное. Число - это список этих цифр (стратегически обратный порядок в середине вычисления); мы умножаем отдельные цифры на
flatMap
и наши строки вверхreduce
.u
обрабатывает вычисление переноса (путем непосредственного сопоставления со списком из> 10 элементов и повторения) и преобразования цифр обратно в символы, и мы используем a,/:
чтобы пройти через этот стек. Требуемый пример завершается менее чем за секунду.источник