Помножте два числа, не використовуючи жодних чисел


30

Вам вводяться в якості двох рядків, що представляють додатні цілі числа в базі 10, такі як "12345"і "42". У "518490"цьому випадку ваше завдання - вивести рядок, що містить їхній продукт .

Поворот полягає в тому, що ви не можете використовувати будь-які числові типи у своєму коді. Ні ints, floats, unsigned longs та ін., Ніяких вбудованих складних типів чисел чи довільних цілих чисел чи будь-чого іншого в цих рядках. Ви багато хто не використовуєте літерали цих типів, ані будь-яку функцію, метод, оператор тощо, що їх повертає.

Ви можете використовувати рядки, булеві масиви, масиви чи будь-що інше, що зазвичай не використовується для представлення числа. (Але зауважте, що ні індексування масиву, ні отримання його довжини, ймовірно, неможливо без виклику числового типу.) charS дозволяється, але ви не можете виконувати над ними арифметичні чи бітові операції або іншим чином трактувати їх як будь-що інше, ніж маркер, що представляє частину рядка. ( charДозволено лексикографічне порівняння s.)

Ви не можете обійти обмеження. Сюди входить (але не обмежується цим) використання числових типів усередині evalфункції типу, неявні перетворення типів у числові типи, використання чисельних чи порозрядних операторів для нечислових типів, які їх підтримують, використання числових типів, що зберігаються всередині типів контейнерів, або виклику функцій або зовнішні програми, які повертають числові результати у рядковій формі. (Я залишаю за собою право додати до цього списку, якщо у відповідях з’являються інші обхідні шляхи.) Ви мусите реалізовувати множення самостійно, використовуючи лише нечислові типи.

Введення та виведення можна будь-яким зручним способом, якщо дані вводять і виходять з коду у вигляді рядка. Ви можете припустити, що кожен з двох вхідних аргументів містить лише символи ASCII [0-9]і не буде починатися з 0. Ваш вихід також не повинен мати початкових нулів.

І ще одне: ваш код повинен правильно обробляти входи довжиною щонайменше 10 символів , а на сучасному комп'ютері повинен працювати менше хвилини для всіх входів цього діапазону. Перш ніж публікувати повідомлення, переконайтеся, що, коли дані надані, 9999999999і 9999999999ваша програма дає вихід 99999999980000000001менше ніж за хвилину. Це обмеження існує спеціально для запобігання відповідям, які працюють, виділяючи масив розміру, a*bа потім повторюючи його, тому врахуйте, що відповіді цієї форми не можуть бути переможними.

Це , тому найкоротше діюче рішення (у байтах) виграє.


Чи можемо ми прийняти "12345"від STDIN, а не 12345? Або ми можемо прийняти обидва числа як "12345", "42"?
Джастін

Моя перша думка була написати функцію , приймаючу рядкові аргументи довжини mі nі повертає аргумент довжини m*n. Але оскільки рядки повинні буквально містити ASCII-представлення чисел, я думаю, це суперечить правилам.
Рівень р. Св.

1
@xnor багатьма мовами може бути коротше, щоб виписати всі справи. Але я знайшов такий шлях у Python:a,b="0123456789x".split('0');c=iter(b).next() if c=='x': c='0'
Натаніель

1
або в Python 3,a,b="0123456789x".split(x);c,*d=b if c=='x': c='0'
Натаніел

2
@Nathanield='123456789';I=dict(zip('0'+d,d+'0'))
Джастін

Відповіді:


6

Haskell - 180 206 214

r=reverse
f=filter
z=['0'..'9']
a?f|f="1"!a
a?_=a
(a:b)!(c:d)=e:b!d?(e<a)where e=fst$last$zip(f(>=c)z++z)$f(<=a)z
a!c=a++c
a%(b:c)=foldr(!)('0':a%c)$f(<b)z>>[a]
_%b=b
a#b=r$r a%r b

Реалізує множення за допомогою повторного додавання, а всі види магічних цифр обробляються шляхом переміщення та фільтрації ['0'..'9']списку. Визначає оператора #типу String -> String -> String:

*> :set +s
*> "9990123456789"#"9999876543210"
"99900001219316321126352690"
(0.02 secs, 9862288 bytes)

Схоже, у нас є новий переможець! (Хоча, як і раніше, я не можу прочитати Haskell такого ступеня витонченості - може хтось самостійно перевірити, чи відповідає він специфікації?)
Натаніел

(Також ['0' .. '9'] трохи схоже на те, що неявно трактує символи як числа, які можна повторити - чи існує короткий спосіб генерувати цей список із рядка "0123456789" замість?)
Натаніел

@Nathaniel Ну перш за все рядок "0123456789" - це список ['0'..'9']. По-друге, у Haskell [a..b] - це перерахування, типи, які оголосили екземпляри класу Enumtype, можуть бути перераховані так, а декларація описує, як працює перерахування. Bool, булівський тип також має екземпляр, і тому ви також можете робити [False..True]. Тут задіяні ледь якісь номери.
mniip

14

sed, 339 338 байт

Я знаю, що це старе, але я переглядав, і це викликало мою зацікавленість. Досить насправді зареєструватися як користувач! Напевно, мене похитнуло " я б дуже хотів побачити повне рішення sed - Натаніел " ...

s/[1-9]/0&/g
s/[5-9]/4&/g
y/8/4/
s/9/4&/g
s/4/22/g
s/[37]/2x/g
s/[26]/xx/g
s/[1-9]/x/g
:o
s/\( .*\)0$/0\1/
/x$/{
x
G
s/ .*/\n/
:a
s/\(.*\)0\(x*\)\n\(.*\)0\(x*\)\n/\1\n\3\n0\2\4/
ta
s/\n//g
:c
s/^x/0x/
s/0xxxxxxxxxx/x0/
tc
x
s/x$//
}
/ 0/bo
g
s/0x/-x/g
s/xx/2/g
y/x/1/
s/22/4/g
s/44/8/g
s/81/9/g
s/42/6/g
s/21/3/g
s/61/7/g
s/41/5/g
s/-//g

Цей сценарій sed очікує на вхід два десяткових числа, розділені пробілом

тести:

time test 518490 = $(./40297.sed <<<)"12345 42" || echo fail
time test 99999999980000000001 = $(./40297.sed <<<"9999999999 9999999999") || echo fail
time test 1522605027922533360535618378132637429718068114961380688657908494580122963258952897654000350692006139 = $(./40297.sed <<<"37975227936943673922808872755445627854565536638199 40094690950920881030683735292761468389214899724061") || echo fail
time test 1230186684530117755130494958384962720772853569595334792197322452151726400507263657518745202199786469389956474942774063845925192557326303453731548268507917026122142913461670429214311602221240479274737794080665351419597459856902143413 = $(./40297.sed <<<"33478071698956898786044169848212690817704794983713768568912431388982883793878002287614711652531743087737814467999489 36746043666799590428244633799627952632279158164343087642676032283815739666511279233373417143396810270092798736308917") || echo fail

Ви можете розпізнати останні два як RSA-100 (50 x 50 цифр) та RSA-768 (116 x 116 цифр).

Використовуючи GNU sed на не дуже сучасному (епоха Intel Core 2), останній з них займає більше хвилини, але він стає швидшим на більш новій процесорі:

  • Q6600:> 1 хвилина
  • i7-3770: 26 секунд
  • i7-6700: 22 секунди

Десяте десятизначне множення, зазначене у запитанні, забирає за секунду будь-яке з них (незважаючи на те, що воно переповнене патологічними дев'ятками).

Я вважаю, що це стандартний sed, без розширень. POSIX гарантує простір у розмірі лише 8192 байти, що обмежує нам множення цифр 400х400, але реалізація може забезпечити більше. GNU sed обмежений лише наявною пам'яттю, тому ви можете керувати чимось значно більшим, якщо ви готові зачекати.

І я впевнений, що я дотримувався правил - це майже дані мовою, яка не має цифр. :-)

Пояснення

Я використовую одинарний / десятковий гібрид, перетворюючи десяткові числа в послідовність одинарних:

 42 => _xxxx_xx

В одинарній десятковій частині додавання легко. Ми повторюємо від найменш значущої до найзначнішої цифри, поєднуючи х:

   X=965                   Y=106                                 SUM
   _xxxxxxxxx_xxxxxx_xxxxx _x__xxxxxx
   _xxxxxxxxx_xxxxxx       _x_                          _xxxxxxxxxxx
   _xxxxxxxxx              _x                    _xxxxxx_xxxxxxxxxxx
                                      _xxxxxxxxxx_xxxxxx_xxxxxxxxxxx

Потім ми видаляємо пробіл і займаємося перенесенням, перетворюючи 10 послідовних х у один із наступних одиниць:

 _xxxxxxxxxx_xxxxxx_xxxxxxxxxxx       10.6.11
 _xxxxxxxxxx_xxxxxxx_x                10.7.1
 _x__xxxxxxx_x                        1.0.7.1 

Після того, як ми додамо, можливе множення. Помножимо x * y, враховуючи останню цифру y. Додайте x до акумулятора багато разів, потім перейдіть до наступної цифри і змістіть x на один десятковий знак ліворуч. Повторюйте, поки y не дорівнює нулю.

Розширений код

#!/bin/sed -f

# Convert to unary decimal.  We save two or three bytes of code by
# reusing 0 as the digit separator.
s/[1-9]/0&/g
s/[5-9]/4&/g
y/8/4/
s/9/4&/g
s/4/22/g
s/[37]/2x/g
s/[26]/xx/g
s/[1-9]/x/g

# until y==0

:one

# y ends in zero => x *= 10 and y /= 10
s/\( .*\)0$/0\1/

# while y%10, acc += x, y -= 1
/x$/{
x
G
s/ .*/\n/
# Add x
:add
s/\(.*\)0\(x*\)\n\(.*\)0\(x*\)\n/\1\n\3\n0\2\4/
tadd
s/\n//g
:carry
s/^x/0x/
s/0xxxxxxxxxx/x0/
tcarry

# repeat for each unit of y
x
s/x$//
}

# y?
/ 0/bone


# convert hold space to decimal
g
s/0x/-x/g
s/xx/2/g
y/x/1/
s/22/4/g
s/44/8/g
s/81/9/g
s/42/6/g
s/21/3/g
s/61/7/g
s/41/5/g
s/-//g

1
Дуже задоволена відповідь, дякую!
Натаніел

9

sed, 379 байт

Подяка за цю блискучу відповідь належить @LuigiTiburzi на Unix & Linux.SE: https://unix.stackexchange.com/a/37213/34061 . Я просто випадково натрапив на це кілька днів тому:

s/[0-9]/<&/g
s/0//g
s/1/|/g
s/2/||/g
s/3/|||/g
s/4/||||/g
s/5/|||||/g
s/6/||||||/g
s/7/|||||||/g
s/8/||||||||/g
s/9/|||||||||/g
:t
s/|</<||||||||||/g
tt
s/<//g
s/.*\*$/0/
s/^\*.*/0/
s/*|/*/
:m
s/\(|*\)\*|/\1<\1*/
tm
s/*//g
s/<//g
:b
s/||||||||||/</g
s/<\([0-9]*\)$/<0\1/
s/|||||||||/9/
s/||||||||/8/
s/|||||||/7/
s/||||||/6/
s/|||||/5/
s/||||/4/
s/|||/3/
s/||/2/
s/|/1/
s/</|/g
tb

Широке пояснення

  • Відокремте кожну цифру. Таким чином 12*3стає<1<2*<3
  • Перетворіть кожну цифру в цю кількість |символів. Таким чином <1<2*<3стає<|<||*<|||
  • Неодноразово підміняйте |<їх <||||||||||, щоб перенести більш високі десяткові знаки вниз до позиції одиниць. Таким чином <|<||*<|||стає<||||||||||||*<|||
  • Видалити <. Таким чином <||||||||||||*<|||стає||||||||||||*|||
  • Вийміть 1 |із РЗС *. Таким чином ||||||||||||*|||стає||||||||||||*||
  • Неодноразово замінюйте кожен |на РЗС всім |на LHS. Це має ефект множення лівої і правої частинах числа , |щоб дати номер продукту з | Таким чином , ||||||||||||*||стає||||||||||||||||||||||||||||||||||||*
  • Видалити *. Таким чином ||||||||||||||||||||||||||||||||||||*стає||||||||||||||||||||||||||||||||||||
  • перетворити кількість |спинок у десяткові за зворотом перших кількох кроків. Таким чином ||||||||||||||||||||||||||||||||||||стає 36.

Вихід:

$ echo "04*3
4*3
40*3
42*32
150*20
1*3
3*1
0*3
3*0" | sed -f mult.sed
12
12
120
1344
3000
3
3
0
0
$

На жаль, вона не спрацьовує з вимогою часу - 200*1000займає 41 секунду на моєму VM Ubuntu, і час роботи емпірично, здається, підходить до площі кінцевого продукту.


1
Це майже алгоритмічно еквівалентно моїй видаленій відповіді JS за винятком перетворення на частину назад.
Оптимізатор

@Optimizer Погодився. Різниця полягає в тому, що ваше використовує те, length()що повертає число. У цьому використовується суто заміщення регулярних виразів без числових типів. Я думаю, що ваша відповідь потенційно є переможцем, хоча, якщо ви можете вилучити, length()- можливо, ви могли б зробити якусь подібну підстановку на регулярному вираженні?
Цифрова травма

1
Дуже приємно, але однохвилинне обмеження спеціально призначене для запобігання рішень, які працюють, перераховуючи відповідь. Я хотів би побачити повне рішення sed, хоча.
Натаніель

1
У мене є відповідь, яка працює у великій кількості (наприклад, більше, ніж адресний простір системи).
Toby Speight

@TobySpeight так, дуже добре. Я думаю, я, мабуть, вже відмовив у відповідь на ваші: :)
Digital Trauma

9

Пітон - 312 286 273

D={}
e=t=""
N=[e]
for c in"0123456789":D[c]=t;D[t]=c;t+="I";N+=N
B=lambda s:[D[c]for c in reversed(s)]
Y=B(input())+N
for a in B(input())+N:
 for c in a:
    s=[];o=e
    for a,b in zip(N,Y):i=a+b+o;o=t<=i and"I"or e;s+=i.replace(t,e),;N=s
 Y=[e]+Y
print e.join(B(N)).lstrip("0")

Якщо дозволено (багато) перших нулів, останні 12 символів не потрібні.

Це по суті виконує стандартне множення вручну. Цифри представлені у вигляді рядків повторних Is (як примітивні римські цифри). Числа представлені у вигляді списків цифр у зворотному порядку. Додавання однозначних цифр виконується шляхом кокатенації рядків та видалення десяти Iс, якщо необхідно.

Ось незворушена версія:

N = [""] # zero object: list with a lot of empty strings
D = {}   # dictionary for conversion from and to digits
i = ""   # iterates over digits
for c in "0123456789":
    D[c] = i  # map digit to Roman digit
    D[i] = c  # and vice versa
    i += "I"  # increments Roman digit
    N += N    # add leading zeros to zero

ten = "IIIIIIIIII" # Roman digit ten

# Conversion function
B = lambda s: [D[c] for c in reversed(s)]

def Add(x,y):
    Sum = []
    carryover = ""
    for a,b in zip(x,y):
        increment = a+b+carryover
        carryover = "I" if ten in increment else ""
        increment = increment.replace(ten,"") # take increment modulo ten
        Sum += [increment]
    return Sum

def M(x,y):
    Sum = N[:] # Initiate Sum as zero
    X = B(x)+N # Convert and add leading zeros
    Y = B(y)+N
    for a in X:
        for c in a:
            Sum = Add(Sum,p+Y)
        Y = [""] + Y # multiply Y by 10
    return "".join(B(Sum)).lstrip("0") # Convert back and to string, remove leading zeros.

M(input(),input())

1
Що це за чаклунство! Як це працює! Ого. Крім того, ось ще один гольф, який ви могли б зробити: def A(x,y):\n S=[];o=""-> def A(x,y,S=[],o=""):. Також, на жаль, ["","1"][t in i]це не дозволено; це використовувати bool для індексації, трактуючи його як число. Я думаю, що це t in i and"1"or""має працювати.
Джастін

@Quincunx: Визначення Sяк аргументу із замовчуванням не працювало б, оскільки це завжди був би той самий список навіть для різних викликів функції і, таким чином, не скидався до []. Ви мали рацію ["","1"][t in i], я це виправив. Я також додав пояснення.
Wrzlprmft

Це досить дивовижно. Зараз вона отримує зелену галочку. (Я відредагував питання, щоб уточнити, що провідні нулі у виході заборонені - вибачте!)
Натаніел

7

Рубін: 752 698

Це просто, щоб отримати відповідь там, щойно зроблено з цікавості. Відредаговано: зараз трохи гольфу.

$F='0123456789'
$G="#{$F}abcdefghij"
def x(a,b);p(a=~/[13579]$/?b:"",a==""?"":x(Hash[*%w(b0 5 b1 6 b2 7 b3 8 b4 9)].to_a.inject(a.tr($F,'0011223344').chars.zip(a.tr($F,'ababababab').chars).flatten.join("")){|n,q|k,v=q;n.gsub(k,v)}.gsub(/[ab]/,'').sub(/^0*/,''),p(b,b)));end
def p(a,b);j,k=["0#{a}","0#{b}"].map{|c|c.gsub(/./,'0')};c="#{k}#{a}".chars.zip("#{j}#{b}".chars).drop_while{|z|z==%w(0 0)}.map{|m|$G.sub(/#{m.map{|n|"122333444455555666666777777788888888999999999".chars.select{|c|c==n}}.flatten.map{|c|'.'}.join("")}/,"").chars.first}.flatten.join("");d=nil;
while c!=d
 d=c;c="0#{d}".gsub(/[0-9][a-j]/) {|m| m.tr($G,"123456789a#{$F}")}.sub(/^0/,'')
end;c;end
puts x(ARGV.shift,ARGV.shift)

Використання: я мав це у файлі під назвою peasant.rb:

$ time ruby peasant.rb 9999999999 9999999999
99999999980000000001

real    0m0.129s
user    0m0.096s
sys 0m0.027s

Пояснення: це селянське розмноження, тому я неодноразово наполовину & ​​подвоююсь. Половина виконується вдвічі цифрами та маркуванням залишків так: 1234 -> 0b1a1b2a; потім знайдіть і замініть на b: 06a17a; потім прибирання -> 617.

Додавання робиться так ... насамперед я прокладаю обидві рядки однакової довжини і роблю пари з цифр. Потім я додаю цифри, будуючи рядок, що має довжину кожної цифри і об'єднує; Я видаляю рядок такої довжини з початку "0123456789abcdefghij", а потім зберігаю першу таблицю. Так, наприклад, "9" + "9" -> "i". NB: Я уникаю фактично використовувати функції довжини тут, щоб уникнути цілих типів чисел; видалення префікса робиться замість регулярного вираження.

Тож тепер у мене є рядок, що містить суміш цифр і букв. Букви представляють цифри з переносною цифрою; Я додаю 0 до числа, а потім кілька разів замінюю візерунки з цифр-літер результатом перенесення до завершення додавання.


1
Дуже розумна відповідь, саме таку річ, яку я сподівався побачити!
Натаніел

1
Я справді сподіваюся, що хтось опублікує це з церковними цифрами!
bazzargh

Це було б круто, хоча я не впевнений, чи буде це працювати з вимогою ефективності - я думаю, що перетворення між рядками та церковними цифрами фактично передбачає підрахунок до 99999999980000000001.
Натаніел

7

Brainfuck (1328 байт)

Спочатку міркування:

  • Не впевнений, чи «мозковий ебан» є правильною відповіддю на це питання, оскільки я не впевнений, чи вважаєте ви значення комірок «числовими типами» чи ні. Я так не думаю, оскільки bf не знає типів, але це моя власна думка, будь ласка, виправте мене, якщо я помиляюся.
  • Необхідна реалізація, яка підтримує (майже) необмежені значення.
  • Це може бути занадто повільним, грунтуючись на впровадженні.

Я тестував програму лише зі своїм власним перекладачем, ви можете її знайти тут .

Вхідні дані повинні бути обома числами, розділеними одним пробілом ASCII.

Гольф:

,>++++++[<----->-]<--[>,>++++++[<----->-]<--]>>>+<<<<[>>++++[<<---->>-]<<[>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]>>>>>[<<<<<+>>>>>-]<[>++++++++++<-]>[<<+>>-]<<<<<[->+<]>[-<+>]<<]>>>>[-]<,[>,]>>>+<<<<[>>+++++++[<<------->>-]<<+[>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]>>>>>[<<<<<+>>>>>-]<[>++++++++++<-]>[<<+>>-]<<<<<[->+<]>[-<+>]<<]>>>>[-]<<<<<[>>[>+>+<<-]>>[<<+>>-]<<<<-]>>[-]>[<+>-]<[>>+>+<<<-]>>>[<<<+>>>-]<[[-]<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<-]>[<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<->>[-]]+>-]<-]<<+>]<[>>+<<-]>>[<<<[>+>+<<-]>>[<<+>>-]>-]<<[<<->>-]<[-]<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[>>]+[<<]>[>[>>]<+<[<<]>-]<<<<<<<<<<[>>+>+<<<-]>>>[<<<+>>>-]+[<+>-]<<<[-]>>[<<+>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+<<-]>>[<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<<->>>[-]]+>-]<-]<<<+>>]<[-]<<<<[-]>>>[<<<+>>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[<+>-]<]<[>+>+<<-]>>[<<+>>-]<[>+<[-]]+>[<[-]<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[[-]>>>>>>>>[>>]<[<[<<]<<<<<+>>>>>>>[>>]<-]<-<<[<<]<<<<<>++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<.[-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]+[<->-]<<<<<[-]>>>>[<<<<+>>>>-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]<[<+>-]<]<[-]]<[>>++++++[<++++++++>-]<.[-]<[-]]<[-]<[-]>>>>>>>>>>>>[>[-]>]<<[-<<]<<<<<<<<<<<<<<<<<[-]<[-]

Безголовки:

,
>++++++[<----->-]<--
[                                           # read input until space
    >,
    >++++++[<----->-]<--                    # decrease cell by 32 to check if it's a space
]
>>>+<<<<                                    # set multiplier to 1

[

    >>++++[<<---->>-]<<                     # decrease by 16 to get cell value of number

    [>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]        # multiply value by multiplier
    >>>>>[<<<<<+>>>>>-]                     # copy value back
    <[>++++++++++<-]>[<<+>>-]               # multiply multiplier by 10
    <<<<<                                   # go back to number

    [->+<]>[-<+>]                           # add value to next cell and move sum to previous cell

    <<                                      # go to next number
]

>>>>[-]<                                    # delete old multiplier

,[>,]                                       # read second number until end of input
>>>+<<<<                                    # set new multiplier

[

    >>+++++++[<<------->>-]<<+              # decrease by 48 to get cell value of number

    [>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]        # multiply value by multiplier
    >>>>>[<<<<<+>>>>>-]                     # copy value back
    <[>++++++++++<-]>[<<+>>-]               # multiply multiplier by 10
    <<<<<                                   # go back to number

    [->+<]>[-<+>]                           # add value to next cell and move sum to previous cell

    <<                                      # go to next number
]

>>>>[-]<<<<<                                # delete multiplier

[>>[>+>+<<-]>>[<<+>>-]<<<<-]>>[-]>          # multiply both values

# magical algorithm for printing cell value as number taken from Cedric Mamo's code from a previous question
[<+>-]<[>>+>+<<<-]>>>[<<<+>>>-]<[[-]<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<-]>[<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<->>[-]]+>-]<-]<<+>]<[>>+<<-]>>[<<<[>+>+<<-]>>[<<+>>-]>-]<<[<<->>-]<[-]<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[>>]+[<<]>[>[>>]<+<[<<]>-]<<<<<<<<<<[>>+>+<<<-]>>>[<<<+>>>-]+[<+>-]<<<[-]>>[<<+>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+<<-]>>[<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<<->>>[-]]+>-]<-]<<<+>>]<[-]<<<<[-]>>>[<<<+>>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[<+>-]<]<[>+>+<<-]>>[<<+>>-]<[>+<[-]]+>[<[-]<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[[-]>>>>>>>>[>>]<[<[<<]<<<<<+>>>>>>>[>>]<-]<-<<[<<]<<<<<>++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<.[-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]+[<->-]<<<<<[-]>>>>[<<<<+>>>>-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]<[<+>-]<]<[-]]<[>>++++++[<++++++++>-]<.[-]<[-]]<[-]<[-]>>>>>>>>>>>>[>[-]>]<<[-<<]<<<<<<<<<<<<<<<<<[-]<[-]

Я взяв код для виведення значення з цієї відповіді , дякую автору за це!

Програма може бути недійсною, але в будь-якому випадку я хотів би поділитися нею з вами ^^

Оновлення: Тепер Ви можете перевірити це (тільки для невеликих умножений) тут, завдяки @ Sp3000 в відповідь на цей конкурс і новий стек Snippets SE ,!

var NUM_CELLS = 30000;var ITERS_PER_SEC = 100000;var TIMEOUT_MILLISECS = 5000;function clear_output(){document.getElementById("output").value="";document.getElementById("stderr").innerHTML=""}function stop(){running=false;document.getElementById("run").disabled=false;document.getElementById("stop").disabled=true;document.getElementById("clear").disabled=false;document.getElementById("wrap").disabled=false;document.getElementById("timeout").disabled=false;document.getElementById("eof").disabled=false}function interrupt(){error(ERROR_INTERRUPT)}function error(e){document.getElementById("stderr").innerHTML=e;stop()}function run(){clear_output();document.getElementById("run").disabled=true;document.getElementById("stop").disabled=false;document.getElementById("clear").disabled=true;document.getElementById("wrap").disabled=true;document.getElementById("timeout").disabled=true;document.getElementById("eof").disabled=true;code=document.getElementById("code").value;input=document.getElementById("input").value;wrap=document.getElementById("wrap").value;timeout=document.getElementById("timeout").checked;eof=document.getElementById("eof").value;loop_stack=[];loop_map={};for(var e=0;e<code.length;++e){if(code[e]=="["){loop_stack.push(e)}else if(code[e]=="]"){if(loop_stack.length==0){error(ERROR_BRACKET);return}else{var t=loop_stack.pop();loop_map[t]=e;loop_map[e]=t}}}if(loop_stack.length>0){error(ERROR_BRACKET);return}running=true;start_time=Date.now();code_ptr=0;input_ptr=0;cell_ptr=Math.floor(NUM_CELLS/2);cells={};iterations=0;bf_iter(1)}function bf_iter(e){if(code_ptr>=code.length||!running){stop();return}var t=Date.now();for(var n=0;n<e;++n){if(cells[cell_ptr]==undefined){cells[cell_ptr]=0}switch(code[code_ptr]){case"+":if(wrap=="8"&&cells[cell_ptr]==255||wrap=="16"&&cells[cell_ptr]==65535||wrap=="32"&&cells[cell_ptr]==2147483647){cells[cell_ptr]=0}else{cells[cell_ptr]++}break;case"-":if(cells[cell_ptr]==0){if(wrap=="8"){cells[cell_ptr]=255}if(wrap=="16"){cells[cell_ptr]=65535}if(wrap=="32"){cells[cell_ptr]=2147483647}}else{cells[cell_ptr]--}break;case"<":cell_ptr--;break;case">":cell_ptr++;break;case".":document.getElementById("output").value+=String.fromCharCode(cells[cell_ptr]);break;case",":if(input_ptr>=input.length){if(eof!="nochange"){cells[cell_ptr]=parseInt(eof)}}else{cells[cell_ptr]=input.charCodeAt(input_ptr);input_ptr++}break;case"[":if(cells[cell_ptr]==0){code_ptr=loop_map[code_ptr]}break;case"]":if(cells[cell_ptr]!=0){code_ptr=loop_map[code_ptr]}break}code_ptr++;iterations++;if(timeout&&Date.now()-start_time>TIMEOUT_MILLISECS){error(ERROR_TIMEOUT);return}}setTimeout(function(){bf_iter(ITERS_PER_SEC*(Date.now()-t)/1e3)},0)}var ERROR_BRACKET="Mismatched brackets";var ERROR_TIMEOUT="Timeout";var ERROR_INTERRUPT="Interrupted by user";var code,input,wrap,timeout,eof,loop_stack,loop_map;var running,start_time,code_ptr,input_ptr,cell_ptr,cells,iterations
<div style="font-size:12px;font-family:Verdana, Geneva, sans-serif;"> <div style="float:left; width:50%;"> Code: <br> <textarea id="code" rows="4" style="overflow:scroll;overflow-x:hidden;width:90%;">,>++++++[<----->-]<--[>,>++++++[<----->-]<--]>>>+<<<<[>>++++[<<---->>-]<<[>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]>>>>>[<<<<<+>>>>>-]<[>++++++++++<-]>[<<+>>-]<<<<<[->+<]>[-<+>]<<]>>>>[-]<,[>,]>>>+<<<<[>>+++++++[<<------->>-]<<+[>>>>[>+>+<<-]>>[<<+>>-]<<<<<<-]>>>>>[<<<<<+>>>>>-]<[>++++++++++<-]>[<<+>>-]<<<<<[->+<]>[-<+>]<<]>>>>[-]<<<<<[>>[>+>+<<-]>>[<<+>>-]<<<<-]>>[-]>[<+>-]<[>>+>+<<<-]>>>[<<<+>>>-]<[[-]<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<-]>[<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<->>[-]]+>-]<-]<<+>]<[>>+<<-]>>[<<<[>+>+<<-]>>[<<+>>-]>-]<<[<<->>-]<[-]<[>>>>>>>>+<<<<<<<<-]>>>>>>>>>[>>]+[<<]>[>[>>]<+<[<<]>-]<<<<<<<<<<[>>+>+<<<-]>>>[<<<+>>>-]+[<+>-]<<<[-]>>[<<+>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]++++++++++<[>>+<<-]>>[<[>>+>+<<<-]>>>[<<<+>>>-]<[>+<<-[>>[-]>+<<<-]>>>[<<<+>>>-]<[<-[<<<->>>[-]]+>-]<-]<<<+>>]<[-]<<<<[-]>>>[<<<+>>>-]<<<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[<+>-]<]<[>+>+<<-]>>[<<+>>-]<[>+<[-]]+>[<[-]<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<[[-]>>>>>>>>[>>]<[<[<<]<<<<<+>>>>>>>[>>]<-]<-<<[<<]<<<<<>++++++++++++++++++++++++++++++++++++++++++++++++[<+>-]<.[-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]+[<->-]<<<<<[-]>>>>[<<<<+>>>>-]<<<<[>>>>+>+<<<<<-]>>>>>[<<<<<+>>>>>-]<[<+>-]<]<[-]]<[>>++++++[<++++++++>-]<.[-]<[-]]<[-]<[-]>>>>>>>>>>>>[>[-]>]<<[-<<]<<<<<<<<<<<<<<<<<[-]<[-]</textarea> <br>Input: <br> <textarea id="input" rows="2" style="overflow:scroll;overflow-x:hidden;width:90%;">7 6</textarea> <p> Wrap: <select id="wrap"> <option value="8">8-bit</option> <option value="16">16-bit</option> <option value="32" selected="selected">32-bit</option> </select> &nbsp; Timeout: <input id="timeout" type="checkbox"></input>&nbsp; EOF: <select id="eof"> <option value="nochange">Same</option> <option value="0" selected="selected">0</option> <option value="-1">-1</option> </select> </p> </div> <div style="float:left; width:50%;"> Output: <br> <textarea id="output" rows="6" style="overflow:scroll;width:90%;"></textarea> <p> <input id="run" type="button" value="Run" onclick="run()"></input> <input id="stop" type="button" value="Stop" onclick="interrupt()" disabled="true"></input> <input id="clear" type="button" value="Clear" onclick="clear_output()"></input> &nbsp; <span id="stderr" style="color:red"></span></p></div></div>


Я не знаю, чи це дійсно! Я здогадуюсь або все в Brainfuck чисельне, або нічого немає.
Натаніел

Мені подобається ця відповідь. Я останнім часом возився з bf. це наче проливає світло на те, що на машинному рівні все одно є лише жетонами. Важко сказати, чи дійсно це відповідає правилам чи ні.
Восьминіг

6

Пітона, 394 349 340 символів

D='0123456789'
R=reversed
U=lambda x:[R for y in D if y<x]
T=U(':')
def A(a,b,r='',c=[]):
 for x,y in map(None,R(a),R(b)):
    d=U(x)+U(y)+c;t=T;c=[R]
    if d<T:t=c=[]
    r=min(k for k in D if U(k)+t>=d)+r
 if c:r='1'+r
 return r
a,b=input()
m=''
while b:
 if list(b).pop()in'13579':m=A(m,a)
 b=list(A(b,A(b,A(b,A(b,b)))));b.pop();a=A(a,a)
print m

Бігайте так:

echo '"9999999999","9999999999"' | ./mulstr.py

Займає 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'?
Джастін

@Quincunx: Дякую Остання не працюватиме, оскільки на першій ітерації bє рядок, а не список.
Кіт Рендалл

Ви можете пропустити Mі написати повну програму; a,b=input() дозволено.
Джастін

1
b * 5/10 - приємний трюк.
bazzargh

Я просто наткнувся на reduce, який дозволяє nicen A(b,A(b,A(b,A(b,b))))до reduce(A,[b,b,b,b,b]). На жаль, це не впливає на кількість персонажів.
Wrzlprmft

5

JavaScript (E6) 375 395 411 449

Редагувати Golfed
Edit Виправлено помилку: відсутні очищення прапорця

Це можна зробити за допомогою просто маніпуляції символом протягом майже 0 разів.
У цій версії ви можете використовувати будь-які знаки замість цифр, якщо символ знаходиться у порядку зростання.

Примітки: використовуючи рядки, хешмап із рядковим ключем, масиви, що використовуються як список. Індексація відсутня, масиви проходять за допомогою "map" або повертаються за допомогою push & shift.
Усі "+" є об'єднанням рядків.

M=(x,y,S=a=>a.shift()||z,R=a=>[...a].reverse(),e=R('9876543210'),d=[...e])=>
  R(y)[T='map'](b=>
     R(x)[T](a=>(
       u=R[e[a+=b]+v],
       v=R[S[a]+(u<v?'1':z)],
       p[P](t=R[S(o)+u]),
       t<u?v=R[v+'1']:v
     ),o=p,p=[])
    +(v>z&&p[P](v),x+=v=z),
    d[T](a=>d[T](b=>e[P='push'](R[a+b]=S(e)))+e[P](S(e))),  
    d[T](a=>d[T](b=>e[d[T](c=>v=c<a?(u=R[u+b])<b?R[v+'1']:v:v,v=u=z='0'),S[a+b]=v,a+b]=u)),
    p=[v=z]
  )&&R(p).join(o)

Менше гольф (можливо, я додам пояснення завтра)

M=(x,y)=>(
  R=a=>[...a].reverse(),
  // Addition table s 
  s={},
  e=[...'9012345678'],
  [for(a of(d='0123456789'))for(b of(e.push(e.shift()),d))e.push(s[a+b]=c=e.shift())],
  // Multiplication table m,n
  m={},n={},
  [for(a of d)for(b of d)(
     [for(c of(z=u=v='0',d))
     c<a&&(t=s[u+b],t<u?v=s[v+'1']:v,u=t)
     ],m[a+b]=u,n[a+b]=v
  )],
  x=R(x),v=z,o=[],p=[],
  [for(b of R(y))(
     [for(a of x)(
       u=s[m[a+b]+v],v=s[n[a+b]+(u<v?'1':z)],
       p.push(t=s[(o.shift()||z)+u]),
       t<u?v=s[v+'1']:v
     )],
     v>z?p.push(v):o,o=p,p=[],x.unshift(v=z)
  )],
  R(o).join('')
)

Тест в консолі FireFox / FireBug

t0=-new Date
r=M('9999999999','9999999999')
t1=-new Date
console.log("Result",r, "time ms", t0-t1)

Вихідні дані

Result 99999999980000000001 time ms 14

Можливо, є незначна помилка - вихід із 9999999999справи повинен бути 99999999980000000001, ні99999999980000000081
Натаніел

:( збирається перевірити
edc65

Якщо ви використовуєте таблиці множення, як вам подолати той факт, що підсумовування не дозволено?
COTO

1
IS підсумовування дозволено з використанням хештелів (s у коді). Вих. s ['34 '] ->' 7 '. Просто символи, а не цифри. Може бути s ['cd'] -> 'g'
edc65

5

Haskell, 231 байт

Це визначає оператор №, який множить два рядкових подання натуральних чисел. Він працює, визначаючи елементарну операцію збільшення / зменшення на рядках, а потім використовує її для нарощування додавання та множення. Трохи додаткової магії дає кілька експоненціальних прискорень, які роблять все можливим ..

r=reverse
n="9876543210"
t=True
c&(x:y)|c==x=head y|t=c&y
m%[]="1";m%(c:s)|c==last m=head m:m%s|t=c&m:s
[]!y=y;x![]=x;(x:a)!('0':b)=x:a!b;x!y=(r n%x)!(n%y)
"0"?_="0";x?('0':y)|all(=='0')y="0"|t=('0':x)?y;x?y=x?(n%y)!x
x#y=r$r x?r y

Цей підхід досить швидкий, що навіть на ноутбуці 2008 року в неоптимізованому ghci REPL тестовий випадок займає лише частку секунди:

λ> :set +s
λ> let test = replicate 10 '9'
(0.00 secs, 0 bytes)
λ> test
"9999999999"
(0.00 secs, 1069784 bytes)
λ> test # test
"99999999980000000001"
(0.06 secs, 13451288 bytes)

Ось перевірка правильності всіх двозначних продуктів:

λ> and [ show (x * y) == (show x # show y) | x <- [0..100], y <- [0..100] ]
True

Схоже, у нас новий керівник! (Я не можу прочитати Haskell - чи може хтось самостійно підтвердити, що він відповідає специфікації?)
Nathaniel

1
Так, це ідеально кромулентний haskell, він відповідає специфікаціям і працює як рекламується. Хороша робота!
bazzargh

4

Bash + ImageMagick: 52

convert -size ${a}x${b} xc:red txt:-|grep -v g|wc -l

Очікує, що вхід буде в змінних оболонки aта b. Це не особливо розумно або ефективно, але це робить роботу. Це, мабуть, робилося і раніше.

Зауважте, що xпозначає розміри зображення; він не є арифметичним оператором у цьому контексті.

Я цього не перевіряв, але я готовий припустити, що для неекстремального введення він завершиться за одну хвилину. Я можу перевірити це завтра.

Якщо у вас є якісь кумедні справи з версіями ImageMagick, я використовую це: ImageMagick 6.7.7-10


Хороша спроба, але я впевнений, що це не спрацює за хвилину (або взагалі на будь-якій існуючій машині) для введення даних 9999999999та 9999999999.
Натаніел

4
Це також працює: dd if=/dev/zero bs=$a count=$b 2>&-|wc -c.
jimmy23013

1
9999999999x9999999999Зображення в форматі 8bit буде займати весь простір на жорсткому диску , який існує в даний час на Землі. Звичайно, png буде набагато меншим, якщо ви можете створити його, попередньо не створивши необроблене зображення. (Хоча я сильно підозрюю, що у вас виникнуть цілі проблеми із переповненням зображення такого розміру.) Але все-таки такий метод майже напевно припаде до лазівки виклику "речі-що-повернення-числові-результати-як-рядки".
Натаніель

1
Ви можете зберегти 2 байти, використовуючи $bзамість ${b}.
nyuszika7h

1
Крім того, ви можете зберегти 5 байт, використовуючи grep -vc gзамість grep -v g|wc -l.
nyuszika7h

2

Python 2 (доказ концепції)

Це рішення працює з використанням лише рядків і списків, а також невеликого регулярного вираження. Я вважаю, що цілком відповідає специфікації, за винятком того, що це не можливо зробити 9999999999x9999999999за хвилину. Хоча, даючи достатньо часу, це спрацює. Він може швидко помножити чотиризначні числа.

Оскільки це технічно недійсне, я ще не намагався повністю гольфувати його. Я зроблю це, якщо правила зміняться.

import re
D='123456789'
D=dict(zip('0'+D,D+'0'))

def toRlist(s):
    if s:t,h=re.match(r'(\d*)(\d)',s).groups();return[h,toRlist(t)]
    return''

def increment(r):
    if not r:return['1','']
    h,t=r
    return[D[h],increment(t)if h=='9'else t]

def toString(r):
    if not r:return''
    h,t=r
    return h+toString(t)

def listify(r,L):
    if not r:return
    h,t=r
    if h=='1':L.append('')
    if h=='2':L.extend(['',''])
    if h=='3':L.extend(['','',''])
    if h=='4':L.extend(['','','',''])
    if h=='5':L.extend(['','','','',''])
    if h=='6':L.extend(['','','','','',''])
    if h=='7':L.extend(['','','','','','',''])
    if h=='8':L.extend(['','','','','','','',''])
    if h=='9':L.extend(['','','','','','','','',''])
    listify(t,L);listify(t,L);listify(t,L);listify(t,L);listify(t,L)
    listify(t,L);listify(t,L);listify(t,L);listify(t,L);listify(t,L)

def add(r1,r2):
    L=[];listify(r2,L)
    for _ in L:r1=increment(r1)
    return r1

def multiply(a,b):
    total=''
    r=toRlist(a)
    L=[];listify(toRlist(b),L)
    for _ in L:total=r if total=='' else add(total,r)
    return''.join(reversed(toString(total)))

Приклади:

multiply('12','5') #returns the string 60

multiply('1869','1243') #returns the string 2323167

1
+1, оскільки він відповідає специфікації (крім вимог щодо ефективності), наскільки я можу сказати
Натаніел

2

Пітон 2 (555)

Я зазвичай не відповідав на власний виклик так швидко (або взагалі), але хотів довести, що це можна зробити. (На щастя, деякі інші відповіді зробили це перед цим, але я не міг не бажати закінчити це.) Є ще кілька гольфів, які можна було б зробити, але я вважаю, що це розумно. Він обробляє 9999999999x9999999999корпус менше ніж 0,03 на моїй машині.

d="123456789";I=dict(zip('0'+d,d+'0'))
def r(x):return reversed(x)
def s(x):return''.join(x)
def i(x):
    try:
        h=I[x.next()]
        if h!='0':h+=s(x)
        else:h+=i(x)
        return h
    except:return'1'
def b(x,y):
    for c in'0'+d:
        if c==y:break
        x=iter(i(x))
    return x
def a(x,y):
    z=''
    for c in y:
        x=b(x,c)
        try:z+=x.next()
        except:z+='0'
    return z+s(x)
def n(x,y):
    z='0'
    for c in'0'+d:
        if c==y:break
        z=a(iter(z),x)
    return z
def o(x,y):
    x=s(x)
    l='';z=''
    for c in y:
        z=a(iter(z),l+s(n(x,c)))
        l+='0'
    return z
def m(x,y):
    return s(r(o(r(x),r(y))))

Приклад використання: 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), хоча це може суттєво змінити швидкість вашої програми.
Джастін

@Quincunx дякую! Я можу побачити ще кілька покращень, а також цього ранку. (Здебільшого вкладаючи цикли, а не визначаючи функції.) Я внесу ці зміни, якщо з’являться ще більш конкурентоспроможні відповіді, що здається ймовірним - на даний момент вони поставлять мене на лідерство, що здається трохи несправедливим, оскільки це було моїм питанням, і я ' мені довелося більше думати про це.
Натаніел

2

JavaScript: 3710 3604 байт

  • Використовуючи таблиці пошуку рядків з одноцифровим множенням та додайте з переносом
  • Множення проводиться на цифру x цифру замість цифри x рядок.

Гольф:

var M={
'00':'0','01':'0','02':'0','03':'0','04':'0','05':'0','06':'0','07':'0','08':'0','09':'0',
'10':'0','11':'1','12':'2','13':'3','14':'4','15':'5','16':'6','17':'7','18':'8','19':'9',
'20':'0','21':'2','22':'4','23':'6','24':'8','25':'10','26':'12','27':'14','28':'16','29':'18',
'30':'0','31':'3','32':'6','33':'9','34':'12','35':'15','36':'28','37':'21','38':'24','39':'27',
'40':'0','41':'4','42':'8','43':'12','44':'16','45':'20','46':'24','47':'28','48':'32','49':'36',
'50':'0','51':'5','52':'10','53':'15','54':'20','55':'25','56':'30','57':'35','58':'40','59':'45',
'60':'0','61':'6','62':'12','63':'18','64':'24','65':'30','66':'36','67':'42','68':'48','69':'54',
'70':'0','71':'7','72':'14','73':'21','74':'28','75':'35','76':'42','77':'49','78':'56','79':'63',
'80':'0','81':'8','82':'16','83':'24','84':'32','85':'40','86':'48','87':'56','88':'64','89':'72',
'90':'0','91':'9','92':'18','93':'27','94':'36','95':'45','96':'54','97':'63','98':'72','99':'81'
};
var A={
'000':'0','001':'1','002':'2','003':'3','004':'4','005':'5','006':'6','007':'7','008':'8','009':'9',
'010':'1','011':'2','012':'3','013':'4','014':'5','015':'6','016':'7','017':'8','018':'9','019':'10',
'020':'2','021':'3','022':'4','023':'5','024':'6','025':'7','026':'8','027':'9','028':'10','029':'11',
'030':'3','031':'4','032':'5','033':'6','034':'7','035':'8','036':'9','037':'10','038':'11','039':'12',
'040':'4','041':'5','042':'6','043':'7','044':'8','045':'9','046':'10','047':'11','048':'12','049':'13',
'050':'5','051':'6','052':'7','053':'8','054':'9','055':'10','056':'11','057':'12','058':'13','059':'14',
'060':'6','061':'7','062':'8','063':'9','064':'10','065':'11','066':'12','067':'13','068':'14','069':'15',
'070':'7','071':'8','072':'9','073':'10','074':'11','075':'12','076':'13','077':'14','078':'15','079':'16',
'080':'8','081':'9','082':'10','083':'11','084':'12','085':'13','086':'14','087':'15','088':'16','089':'17',
'090':'9','091':'10','092':'11','093':'12','094':'13','095':'14','096':'15','097':'16','098':'17','099':'18',
'100':'1','101':'2','102':'3','103':'4','104':'5','105':'6','106':'7','107':'8','108':'9','109':'10',
'110':'2','111':'3','112':'4','113':'5','114':'6','115':'7','116':'8','117':'9','118':'10','119':'11',
'120':'3','121':'4','122':'5','123':'6','124':'7','125':'8','126':'9','127':'10','128':'11','129':'12',
'130':'4','131':'5','132':'6','133':'7','134':'8','135':'9','136':'10','137':'11','138':'12','139':'13',
'140':'5','141':'6','142':'7','143':'8','144':'9','145':'10','146':'11','147':'12','148':'13','149':'14',
'150':'6','151':'7','152':'8','153':'9','154':'10','155':'11','156':'12','157':'13','158':'14','159':'15',
'160':'7','161':'8','162':'9','163':'10','164':'11','165':'12','166':'13','167':'14','168':'15','169':'16',
'170':'8','171':'9','172':'10','173':'11','174':'12','175':'13','176':'14','177':'15','178':'16','179':'17',
'180':'9','181':'10','182':'11','183':'12','184':'13','185':'14','186':'15','187':'16','188':'17','189':'18',
'190':'10','191':'11','192':'12','193':'13','194':'14','195':'15','196':'16','197':'17','198':'18','199':'19'
} 
Array.prototype.e=function(){return(''+this)==='';}
String.prototype.s=function(){return this.split('').reverse();}
function B(a,b,c) {
var r='',s='';
a=a.s();
b=b.s();
while (!a.e()||!b.e()||c!=='0') {
x=a.e()?'0':a.shift();
y=b.e()?'0':b.shift();
s=A[c+x+y];
s=s.s();
r=s.shift()+r;
c=s.e()?'0':'1';
}
return r;
}
function m(a,b) {
var s='0',m='';
b.split('').reverse().forEach(function(e){
var z=m;
a.split('').reverse().forEach(function(f){s=B(s,M[e+f]+z,'0');z+='0';});
m+='0';
});
return s;
}

Невикористані тестами:

var mul = {
'00':'0','01':'0','02':'0','03':'0','04':'0','05':'0','06':'0','07':'0','08':'0','09':'0',
'10':'0','11':'1','12':'2','13':'3','14':'4','15':'5','16':'6','17':'7','18':'8','19':'9',
'20':'0','21':'2','22':'4','23':'6','24':'8','25':'10','26':'12','27':'14','28':'16','29':'18',
'30':'0','31':'3','32':'6','33':'9','34':'12','35':'15','36':'28','37':'21','38':'24','39':'27',
'40':'0','41':'4','42':'8','43':'12','44':'16','45':'20','46':'24','47':'28','48':'32','49':'36',
'50':'0','51':'5','52':'10','53':'15','54':'20','55':'25','56':'30','57':'35','58':'40','59':'45',
'60':'0','61':'6','62':'12','63':'18','64':'24','65':'30','66':'36','67':'42','68':'48','69':'54',
'70':'0','71':'7','72':'14','73':'21','74':'28','75':'35','76':'42','77':'49','78':'56','79':'63',
'80':'0','81':'8','82':'16','83':'24','84':'32','85':'40','86':'48','87':'56','88':'64','89':'72',
'90':'0','91':'9','92':'18','93':'27','94':'36','95':'45','96':'54','97':'63','98':'72','99':'81'
};

var adc = {
'000':'0','001':'1','002':'2','003':'3','004':'4','005':'5','006':'6','007':'7','008':'8','009':'9',
'010':'1','011':'2','012':'3','013':'4','014':'5','015':'6','016':'7','017':'8','018':'9','019':'10',
'020':'2','021':'3','022':'4','023':'5','024':'6','025':'7','026':'8','027':'9','028':'10','029':'11',
'030':'3','031':'4','032':'5','033':'6','034':'7','035':'8','036':'9','037':'10','038':'11','039':'12',
'040':'4','041':'5','042':'6','043':'7','044':'8','045':'9','046':'10','047':'11','048':'12','049':'13',
'050':'5','051':'6','052':'7','053':'8','054':'9','055':'10','056':'11','057':'12','058':'13','059':'14',
'060':'6','061':'7','062':'8','063':'9','064':'10','065':'11','066':'12','067':'13','068':'14','069':'15',
'070':'7','071':'8','072':'9','073':'10','074':'11','075':'12','076':'13','077':'14','078':'15','079':'16',
'080':'8','081':'9','082':'10','083':'11','084':'12','085':'13','086':'14','087':'15','088':'16','089':'17',
'090':'9','091':'10','092':'11','093':'12','094':'13','095':'14','096':'15','097':'16','098':'17','099':'18',
'100':'1','101':'2','102':'3','103':'4','104':'5','105':'6','106':'7','107':'8','108':'9','109':'10',
'110':'2','111':'3','112':'4','113':'5','114':'6','115':'7','116':'8','117':'9','118':'10','119':'11',
'120':'3','121':'4','122':'5','123':'6','124':'7','125':'8','126':'9','127':'10','128':'11','129':'12',
'130':'4','131':'5','132':'6','133':'7','134':'8','135':'9','136':'10','137':'11','138':'12','139':'13',
'140':'5','141':'6','142':'7','143':'8','144':'9','145':'10','146':'11','147':'12','148':'13','149':'14',
'150':'6','151':'7','152':'8','153':'9','154':'10','155':'11','156':'12','157':'13','158':'14','159':'15',
'160':'7','161':'8','162':'9','163':'10','164':'11','165':'12','166':'13','167':'14','168':'15','169':'16',
'170':'8','171':'9','172':'10','173':'11','174':'12','175':'13','176':'14','177':'15','178':'16','179':'17',
'180':'9','181':'10','182':'11','183':'12','184':'13','185':'14','186':'15','187':'16','188':'17','189':'18',
'190':'10','191':'11','192':'12','193':'13','194':'14','195':'15','196':'16','197':'17','198':'18','199':'19'
} 

Array.prototype.isEmpty = function() {
  return (''+this) === '';
}

function add(a, b, c) {
  var r = '', s = '';
  a = a.split("").reverse();
  b = b.split("").reverse();
  while (!a.isEmpty() || !b.isEmpty() || c !== '0') {
    x = a.isEmpty() ? '0' : a.shift();
    y = b.isEmpty() ? '0' : b.shift();
    s = adc[c + x + y];
    s = s.split("").reverse();
    r = (s.shift()) + r;
    c = (s.isEmpty()) ? '0' : '1';
  }
  return r;
}

function mult(a, b) {
  var s = '0';
  var m = '';
  b.split('').reverse().forEach(function(e) {
    var z = m;
    a.split('').reverse().forEach(function(f) {
      s = add(s, mul[e + f] + z, '0');
      z = z + '0';
    });
    m = m + '0';
  } );
  return s;
}

function test(a, b) {
  var t0 = (new Date()).getTime();
  var r = mult(a,b);
  var t1 = (new Date()).getTime();
  var e = t1 - t0;
  console.log('mult ' + a + ' * ' + b + ' = ' + r + " (" + e + " ms)");
}

test('12345', '42');
test('9999999999', '9999999999');

Це виводи:

mult 12345 * 42 = 518490 (3 ms) 
mult 9999999999 * 9999999999 = 99999999980000000001 (47 ms) 

2

Haskell 507 496

Це працює для довільно великих цілих чисел. Я визначаю спеціальні подання для натуральних чисел від 0 до 18 (найбільше натуральне число, що дорівнює сумі двох цифр), і визначаю малокоординатне множення в перерахунку на множення цифр * число, яке я визначаю через число + додавання числа , яку я визначаю через додавання цифри + цифр. У мене є функція скорочення, яка розширює 10--18 значень на їх цифрове розкладання. Потім він просто читає і повертає два рядки, перекладається на спеціальні прив'язки, множує та переводить назад, зворотно змінюючи, щоб отримати правильний результат.

Редагувати 2

Я врятував декілька символів, створивши короткі локальні псевдоніми для команд з декількома символами, якими я користуюся не один раз, а також видаляючи пробіли та дужки, а також замінюючи (- )парами, $коли це можливо.

data S=Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R deriving(Enum, Ord, Eq)
p Z=id
p x=succ.p(pred x)
s Z=id
s x=pred.s(pred x)
z=s J
r[]=[]
r(x:y)|x<J=x:r y
r(x:[])=z x:[A]
r(x:y)=z x:(r$p A a:b)where(a:b)=r y
a x y=r$w(r x)(r y)
m Z _=[]
m _[]=[]
m x y=r$a y(m(pred x)y)
t[]_=[Z]
t _[]=[Z]
t(x:z)y=r$a(m x y)(Z:r(t z y))
i '0'=Z
i x=succ.i.pred$x
b Z='0'
b x=succ.b.pred$x
w[]y=y
w x[]=x
w(x:c)(y:d)=p x y:(w c d)
o=map
v=reverse
f=(o i).v
g=v.o b
main=getLine>>=putStrLn.(\[x,y]->g$t(f x)(f y)).words

Для довідки, S - власний цілочисельний тип даних, pє "плюс" (додавання цифри + цифра), sвіднімається (для зменшення), rзменшується (розширюється на цифрове розкладання), aдодавання (число + додавання числа), mє множення (розряд * множення чисел), tє рази (число * множення числа), iє 'інтерпретація' (перетворення рядка в список S), b'повернення' (список від S до рядка), а f і g - просто скорочення для гольфу цілей. Я не використовував цифри, навіть неявно; Найближче до мене було використання наступників та попередників, які є набагато вищими математичними поняттями, ніж додавання та множення натуральних чисел.

Редагувати

Забув включити профіль часу.

> time echo "9999999999 9999999999" | runhaskell multnonum.hs
99999999980000000001

real    0m0.246s
user    0m0.228s
sys     0m0.012s

Тільки на добрий захід:

> time echo "99999999980000000001 99999999980000000001" | runhaskell multnonum.hs
9999999996000000000599999999960000000001

real    0m0.244s
user    0m0.224s
sys     0m0.016s

Давайте божевільно!

> time echo "9999999996000000000599999999960000000001 9999999996000000000599999999960000000001" | runhaskell multnonum.hs
99999999920000000027999999994400000000699999999944000000002799999999920000000001

real    0m0.433s
user    0m0.424s
sys     0m0.004s

підтвердження


1

Пітон 2 - 1165, 712, 668 664

I,T,V,N,X,J=raw_input,dict,reversed,None,zip,''.join
D='0123456789'
z,o='01'
A,B=I(),I()
r=i=""
K=map(J,X('666622222222911111551111555884444447773333333','678945672389954132987698765898967457989837654'))
P=T(X(K,map(J,X('344501110011800000440000332673322124652202211','628480244668154132507698505422648609367491852'))))
S=T(X(K,'cdef678945abi65243ed87a9cbaghcdab89egfcb6a987'))
for d in D:P[z+d]=z;S[z+d]=d
def Z(A,B,R=r):
 for a,b in V(map(N,V(z+A),V(z+B))):c=(a or z)+(b or z);s=S[min(c)+max(c)];R=Z(R,o)+T(X('abcdefghi',D))[s]if s>"?"else R+s
 return R
for a in V(A):
 j=""
 for b in V(B):r=Z(r,P[min(a+b)+max(a+b)]+i+j).lstrip(z);j+=z
 i+=z
print r if r else z

Зауважте, що я не використовую логічне індексування на зразок Z = [X, Y][N == "0"], тому що це можна інтерпретувати як булеве значення, яке додається до числового індексу.

Безголовки:

A = raw_input()
B = raw_input()

P = {'00':'00','01':'00','02':'00','03':'00','04':'00','05':'00','06':'00','07':'00','08':'00','09':'00',
     '10':'00','11':'01','12':'02','13':'03','14':'04','15':'05','16':'06','17':'07','18':'08','19':'09',
     '20':'00','21':'02','22':'04','23':'06','24':'08','25':'10','26':'12','27':'14','28':'16','29':'18',
     '30':'00','31':'03','32':'06','33':'09','34':'12','35':'15','36':'28','37':'21','38':'24','39':'27',
     '40':'00','41':'04','42':'08','43':'12','44':'16','45':'20','46':'24','47':'28','48':'32','49':'36',
     '50':'00','51':'05','52':'10','53':'15','54':'20','55':'25','56':'30','57':'35','58':'40','59':'45',
     '60':'00','61':'06','62':'12','63':'18','64':'24','65':'30','66':'36','67':'42','68':'48','69':'54',
     '70':'00','71':'07','72':'14','73':'21','74':'28','75':'35','76':'42','77':'49','78':'56','79':'63',
     '80':'00','81':'08','82':'16','83':'24','84':'32','85':'40','86':'48','87':'56','88':'64','89':'72',
     '90':'00','91':'09','92':'18','93':'27','94':'36','95':'45','96':'54','97':'63','98':'72','99':'81',
     }
S = {'00':'0','01':'1','02':'2','03':'3','04':'4','05':'5','06':'6','07':'7','08':'8','09':'9',
     '10':'1','11':'2','12':'3','13':'4','14':'5','15':'6','16':'7','17':'8','18':'9','19':'a',
     '20':'2','21':'3','22':'4','23':'5','24':'6','25':'7','26':'8','27':'9','28':'a','29':'b',
     '30':'3','31':'4','32':'5','33':'6','34':'7','35':'8','36':'9','37':'a','38':'b','39':'c',
     '40':'4','41':'5','42':'6','43':'7','44':'8','45':'9','46':'a','47':'b','48':'c','49':'d',
     '50':'5','51':'6','52':'7','53':'8','54':'9','55':'a','56':'b','57':'c','58':'d','59':'e',
     '60':'6','61':'7','62':'8','63':'9','64':'a','65':'b','66':'c','67':'d','68':'e','69':'f',
     '70':'7','71':'8','72':'9','73':'a','74':'b','75':'c','76':'d','77':'e','78':'f','79':'g',
     '80':'8','81':'9','82':'a','83':'b','84':'c','85':'d','86':'e','87':'f','88':'g','89':'h',
     '90':'9','91':'a','92':'b','93':'c','94':'d','95':'e','96':'f','97':'g','98':'h','99':'i',
     }
L = {'a':'0','b':'1','c':'2','d':'3','e':'4','f':'5','g':'6','h':'7','i':'8'}

def strSum(A, B):
    R = ""
    for a, b in reversed(map(None, reversed("0" + A), reversed("0" + B))):
        if a == None: a = '0'
        if b == None: b = '0'
        s = S[a + b]
        if s.isdigit():
            R += s
        else:
            R = strSum(R, "1") + L[s]
    return R

i = ""
r = "0"
for a in reversed(A):
    j = ""
    for b in reversed(B):
        p = P[a + b] + i + j
        r = strSum(r, p)
        j += "0"
    i += "0"

r = r.lstrip("0")
if r == "":
    r = "0"

print r

Я б сказав, що використання функцій min () та max () не слід допускати, оскільки вони порівнюють фактичні цілі значення, чи не так?
WorldSEnder

@WorldSEnder: Я б сказав, що вони порівнюють персонажів, що дозволено в цьому виклику. ("Дозволено лексикографічне порівняння знаків.")
Фалько

1

Скала, 470 символів

( стандартні шкали, але їх можна замінити, =>якщо ми підраховуємо байти)

def p(a: String,b: String)={type D=List[Char]
val d="0123456789".toList
def v(s: String)=s.toList.map{c⇒d.takeWhile(c.!=)}
def u(l:D, a:D):(Char,D)=l match {
case _::_::_::_::_::_::_::_::_::_::m⇒u(m,'a'::a)
case _⇒(('a'::l).zip(d).last._2,a)}
val o=(("", List[Char]())/:v(a).tails.toList.init.map{l⇒(v(b) map {_.flatMap(_⇒l.head)})++l.tail.map(_⇒Nil) reverse}.reduce(_.zipAll(_, Nil, Nil).map{t⇒t._1++t._2}))({(t,e)⇒val s=u(t._2++e,Nil);(s._1+t._1,s._2)})
u(o._2, Nil)._1+o._1}

Тут ми емулюємо цифри, використовуючи довжину списків, обережно не використовуючи жодних числових операцій - лише складки, карти, блискавки тощо. Число - це список цих цифр (порядок стратегічно перевернутий на півдорозі обчислення); ми множимо окремі цифри з flatMapі наші рядки разом reduce. uми обробляємо перенесення носія (шляхом прямої відповідності списку> 10 елементів і повторення) та перетворення цифр назад в символи, і ми використовуємо a /:для того, щоб пройти свій шлях через стек з цим. Необхідний приклад завершується менш ніж за секунду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.