Умножение на молнии


20

Вступление

Давайте определим новую арифметическую операцию, которую я называю умножением молнии . Для умножения двух неотрицательных чисел на молнию вы добавляете начальные нули, чтобы привести в соответствие длины, умножаете соответствующие цифры на 10 оснований, добавляете к результатам ведущие нули, чтобы получить двузначные числа, объединяете их и, наконец, отбрасываете ведущие нули.

Вот пример с A = 1276 и B = 933024 :

1. Add leading zeros
 A = 001276
 B = 933024

2. Multiply digit-wise
 A = 0  0  1  2  7  6
 B = 9  9  3  0  2  4
 ->  0  0  3  0 14 24

3. Pad to 2 digits
 -> 00 00 03 00 14 24

4. Concatenate
 -> 000003001424

5. Drop leading zeros
 -> 3001424

Операция распространяется на все целые числа с обычными правилами знака: положительное время отрицательное отрицательное, отрицательное время отрицательное положительное и так далее.

Задание

Ваши входные данные представляют собой два целых числа, а ваши выходные данные - их умножение на молнии. Вы должны быть в состоянии обрабатывать произвольно большие входные данные. Ввод и / или вывод могут быть в строковом формате (и действительно должны быть, если ваш язык не поддерживает произвольно большие целые числа). Обратите внимание, что -0это недопустимый ввод или вывод.

Правила и оценки

Вы можете написать полную программу или функцию, и побеждает меньшее количество байтов.

Контрольные примеры

0 0 -> 0
302 40 -> 0
302 -40 -> 0
-4352 448 -> -122016
0 6623 -> 0
0 -6623 -> 0
20643 -56721 -> -1000420803
63196 21220 -> 1203021800
1276 933024 -> 3001424
-1276 933024 -> -3001424
-1276 -933024 -> 3001424
5007204555 350073039 -> 12001545
-612137119 -8088606033 -> 816060042000327
3389903661 -6619166963 -> -18180881090018543603
-23082746128560880381 1116941217 -> -8050600723200060807
-668336881543038127783364011867 896431401738330915057436190556 -> -485448120906320001351224000900090235004021121824000900403042
402878826066336701417493206805490000415 312487283677673237790517973105761463808 -> 120004325656161618004242182118140007280900200921180018080025285400000000320040

Ответы:


8

Желе , 11 10 байт

ƓDUz0P€Uḅ³

Попробуйте онлайн!

Я не мог получить это до 10 байтов сам, но @ Pietu1998 указал мне на атом, который я пропустил, это дало это 10-байтовое решение. Необычно для Jelly, этот получает данные из стандартного ввода (в форме 1276,933024), а не из командной строки (это позволяет использовать ³команду, которая возвращает аргумент командной строки, по умолчанию 100).

Объяснение:

ƓDUz0P€Uḅ³
Ɠ           read standard input
 D          convert to base 10
  U         reverse elements
   z0       transpose, padding the end with zeroes
     P€     take the product of each (€) inner list
       U    reverse elements back
        b³  convert from base 100

Использование базы 100 - это простой способ реализовать метод «заполнить до 2 цифр, а затем преобразовать в базу 10». Единственная другая тонкость здесь - это задний ход; мы хотим заполнить нулями в начале числа, но zкомандные вставки Jelly в конце, поэтому изменение списков означает, что zзаполнение будет корректным.


3
Вы можете заменить b⁵на, Dчтобы получить 10 байтов. : P
PurkkaKoodari

4

Python 2, 99 байт

a,b=input();o=0;p=1-2*(a*b<0);a,b=abs(a),abs(b)
while a:o+=a%10*(b%10)*p;p*=100;a/=10;b/=10
print o

Многие байты предназначены для учета знака в случае отрицательного ввода. В Python n%dвсегда неотрицательно, если dположительно 1 . На мой взгляд, это, как правило, желательно, но здесь это кажется неудобным: удаление вызовов absнарушит приведенный выше код. Тем временем pотслеживает «значение места» (единицы, сотни и т. Д.), А также запоминает желаемый знак вывода.

Код в основном симметричен в aи bза исключением whileусловия: мы продолжаем идти до тех пор, пока aне достигнем нуля, и завершаем в это время. Конечно, если bсначала ноль, то мы в конечном итоге добавим нули на некоторое время, пока также не aбудет ноль.


1 Например, (-33)%10возвращает 7, а целочисленное отношение (-33)/10является -4. Это правильно, потому что (-4)*10 + 7 = -33. Тем не менее, молния продукт (-33)с 33должен закончиться , 3*3 = 09а не 7*3 = 21.


3

JavaScript (ES6), 44 байта

f=(x,y)=>x&&f(x/10|0,y/10|0)*100+x%10*(y%10)

Удобно, это автоматически работает для отрицательных чисел.


@Jakube Я всегда так делаю, хотя, по крайней мере, я включил f=в число байтов. Кроме того, |0потому что мне нужно целочисленное деление, я не знаю, как вы думаете, вы получите правильный ответ без него.
Нил

Ах, это имеет смысл. Теперь я тоже получаю неправильные ответы при удалении |0. Возможно, переназначение новой функции для f не сработало, и я все еще тестировал старую версию с |0.
Якуб

2

C 77 байт

-2 байта для удаления лишних скобок ( *является ассоциативным).

r,t;f(a,b){t=1;r=0;while(a|b)r+=t*(a%10)*(b%10),a/=10,b/=10,t*=100;return r;}

t= 1,100,10000, ... используется для заполнения. Пока ноль aили bнет, продолжайте умножать последнюю цифру %10на tи накапливать. Затем уменьшите последнюю цифру aи b( /=10) и сдвиньте на t2 цифры ( *=100).

Ungolfed и использование:

r,t;
f(a,b){
 t=1;
 r=0;
 while(a|b)
  r+=t*(a%10)*(b%10),
  a/=10,
  b/=10,
  t*=100;
 return r;
}

main(){
 printf("%d\n", f(1276,933024));
}

Предлагаю for(r=0;a|b;t*=100)r+=a%10*t*(b%10),a/=10,b/=10вместоr=0;while(a|b)r+=t*(a%10)*(b%10),a/=10,b/=10,t*=100
roofcat

1

На самом деле , 23 19 байтов

Ввод принимается в виде двух строк. Кроме того, очевидно, что попытка выполнить конвертацию из базы 100, как это делает ais523 в ответе Jelly, на самом деле не очень хорошо работает. Сэкономил бы 9 байтов тоже, если бы это работало: / Гольф предложения приветствуются! Попробуйте онлайн!

Изменить: -4 байта от изменения того, как результат встроен в новый номер.

k`♂≈R`M┬ñ`iτ╤@π*`MΣ

Ungolfing

          Implicit input a and b.
k         Wrap a and b into a list.
`...`M    Map over the list of strings.
  ♂≈        Convert each digit to its own int.
  R         Reverse for later.
┬         Transpose to get pairs of digits from a and b.
ñ         enumerate(transpose) to get all of the indices as well.
`...`M    Map over the transpose.
  i         Flatten (index, pair) onto the stack.
  τ╤        Push 10**(2*index) == 100**index to the stack.
  @π        Swap and get the product of the pair of integers.
  *         Multiply the product by 100**index.
Σ         Sum everything into one number.
          Implicit return.

1

Mathematica 66 байт

i=IntegerDigits;p=PadLeft;FromDigits@Flatten@p[i/@Times@@p[i/@#]]&

Ungolfed:

IntegerDigits/@{1276,933024}
PadLeft[%]
Times@@%
IntegerDigits/@%
PadLeft[%]
Flatten@%
FromDigits@%

где% означает предыдущий выход

{{1,2,7,6},{9,3,3,0,2,4}}
{{0,0,1,2,7,6},{9,3,3,0,2,4}}
{0,0,3,0,14,24}
{{0},{0},{3},{0},{1,4},{2,4}}
{{0,0},{0,0},{0,3},{0,0},{1,4},{2,4}}
{0,0,0,0,0,3,0,0,1,4,2,4}
3001424

1

R 182 110 107 86 байт

Больше не самый длинный ответ (спасибо, Ракетка), и фактически короче, чем решение Python (редкое удовольствие)! Анонимная функция, которая принимает два целых числа в качестве входных данных.

function(a,b)sum((s=function(x)abs(x)%%10^(99:1)%/%(e=10^(98:0))*e)(a)*s(b))*sign(a*b)

Вот как это работает.

Умножение на молнии включает в себя разбиение входных чисел на составляющие их цифры. Мы берем абсолютное значение числа и выполняем по модулю для убывающих степеней 10:

abs(x) %% 10^(99:1)

Итак, здесь мы берем одно число xи применяем по модулю 99 других чисел ( 10^99через 10^1). R неявно повторяется x99 раз, возвращая вектор (список) с 99 элементами. ( x %% 10^99, x %% 10^98, x %% 10^97И т.д.)

Мы используем до 10^99конца 10^1. Более эффективная реализация будет использовать значение числа цифр в самом длинном числе (проверьте историю редактирования этого поста; предыдущие версии делали это), но просто взятие 99..1использует меньше байтов.

Ибо x = 1276это дает нам

1276 1276 1276 ... 1276 276 76 6

Далее мы используем целочисленное деление на убывающие степени 10, чтобы округлить числа:

abs(x) %% 10^(99:1) %/% 10^(98:0)

Это дает

0 0 0 ... 1 2 7 6

это именно то представление, которое мы хотим. В коде мы хотим 10^(98:0)снова использовать его позже, поэтому мы присваиваем его переменной:

abs(x) %% 10^(99:1) %/% (e = 10^(98:0))

(Заключение выражения в круглые скобки в R обычно оценивает выражение (в этом случае присваивая значение 10^(98:0)to e), а затем также возвращает вывод выражения, позволяя нам встраивать присваивания переменных в другие вычисления.)

Далее мы выполняем попарное умножение цифр на входе. Выходные данные затем дополняются до двух цифр и объединяются. Заполнение до двух цифр и объединение эквивалентны умножению каждого числа на 10^n, где nрасстояние от правого края, а затем суммированию всех чисел.

 A = 0         0         1         2         7         6
 B = 9         9         3         0         2         4
 ->  0         0         3         0        14        24
 -> 00        00        03        00        14        24
 ->  0*10^6 +  0*10^5 +  3*10^4 +  0*10^3 + 14*10^2 + 24*10^1
 =  000003001424

В частности, потому , что умножение коммутативно, мы можем выполнить умножение , 10^n прежде чем мы умножаем A по B . Итак, мы берем наш предыдущий расчет и умножаем на 10^(98:0):

abs(x) %% 10^(99:1) %/% 10^(98:0) * 10^(98:0)

что эквивалентно

abs(x) %% 10^(99:1) %/% (e = 10^(98:0)) * e

После применения этого к А , мы бы тогда хотим повторить всю эту операцию B . Но это занимает драгоценные байты, поэтому мы определяем функцию, поэтому нам нужно написать ее только один раз:

s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e

Мы делаем трюк с встраиванием в скобки, чтобы позволить нам одновременно определять и применять функцию, вызывать эту функцию для A и B и умножать их вместе. (Мы могли бы определить это в отдельной строке, но поскольку в конечном итоге мы собираемся поместить все это в анонимную функцию, если у нас более одной строки кода, все должно быть заключено в фигурные скобки, что стоит ценно байт.)

(s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e)(a) * s(b)

И мы берем сумму всего этого, и мы почти закончили:

sum((s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e)(a) * s(b))

Единственное, что нужно учесть - это знак ввода. Мы хотим следовать обычным правилам умножения, поэтому, если один и только один из A и B отрицателен, результат будет отрицательным. Мы используем функцию, signкоторая возвращает, 1когда дано положительное число, а -1когда дано отрицательное число, чтобы вывести коэффициент, который мы умножаем во всех наших вычислениях на:

sum((s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e)(a) * s(b)) * sign(a * b)

Наконец, все это обернуто в анонимную функцию, которая принимает aи в bкачестве входных данных:

function(a, b) sum((s = function(x) abs(x) %% 10^(99:1) %/% (e=10^(98:0)) * e)(a) * s(b)) * sign(a * b)

Удалите пробелы, и это 86 байтов.


Было бы здорово, если бы вы могли предоставить неоправданную, объясненную версию для всеобщего блага.
rnso

Я обновил пост с объяснением.
rturnbull

Прекрасная работа. Очень умный метод используется.
rnso

1

Python 3 , 92 байта , 119 байтов

lambda m,n:(1-(n*m<0)*2)*int(''.join([f"{int(a)*int(b):02}"for a,b in zip(str(abs(n))[::-1],str(abs(m))[::-1])][::-1]))

Попробуйте онлайн!

Исправление для обработки отрицательных чисел стоимостью 29 байт: /


Хороший ответ! Я думаю, что вы можете заменить lstripчасть, обернув все внутри int()и вернув число.
Арбо

Ты прав. Тогда я почувствовал, что мне нужен постоянный интерфейс. Принимая строки в качестве аргументов вместо int, затем возвращая int выглядит для меня странно;) Я скорее надеялся изменить цикл zip + for для вызова карты, но это не сработало бы: /
movatica

Я бы не слишком беспокоился о последовательности в коде гольф, но это зависит от вас :). Картография в Python обычно не очень удачна, если вам понадобится дополнительная лямбда для этого.
АрБо

Эта функция не работает для отрицательных входов
АрБо,

Вы правы: / Исправление довольно дорогое, возможно, есть больше возможностей для игры в гольф.
моватика


0

PHP, 84 байта

for(list(,$a,$b)=$argv,$f=1;$a>=1;$a/=10,$b/=10,$f*=100)$r+=$a%10*($b%10)*$f;echo$r;

немного длиннее с конкатенацией строк (86 байт):

for(list(,$a,$b)=$argv;$a>=1;$a/=10,$b/=10)$r=sprintf("%02d$r",$a%10*($b%10));echo+$r;

0

Ракетка 325 байт

(let*((g string-append)(q quotient/remainder)(l(let p((a(abs a))(b(abs b))(ol'()))(define-values(x y)(q a 10))
(define-values(j k)(q b 10))(if(not(= 0 x j))(p x j(cons(* y k)ol))(cons(* y k)ol)))))(*(string->number
(apply g(map(λ(x)(let((s(number->string x)))(if(= 2(string-length s)) s (g "0" s))))l)))(if(<(* a b)0)-1 1)))

Ungolfed:

(define (f a b)
  (let* ((sa string-append)
         (q quotient/remainder)
         (ll (let loop ((a (abs a))
                        (b (abs b))
                        (ol '()))
               (define-values (x y) (q a 10))
               (define-values (j k) (q b 10))
               (if (not(= 0 x j))
                   (loop x j (cons (* y k) ol))
                   (cons (* y k) ol)))))
    (*(string->number (apply sa
                             (map (λ (x)
                                    (let ((s (number->string x)))
                                      (if (= 2 (string-length s))
                                          s
                                          (sa "0" s))))
                                  ll)))
      (if (< (* a b) 0) -1 1))))

Тестирование:

(f 1276 933024)
(f 302 40)
(f 0 6623)
(f 63196 21220)
(f 20643 -56721)

Выход:

3001424
0
0
1203021800
-1000420803

0

PowerShell , 153 151 байт

param($a,$b)do{$x,$y=$a[--$i],$b[$i]|%{if($_-eq45){$s+=$_;$_=0}$_}
$r=(+"$x"*"$y"|% t*g "00")+$r}while($x+$y)$s+$r-replace'(?<!\d)0+(?=\d)|--|-(?=0+$)'

Попробуйте онлайн!

Менее гольф:

param($a,$b)
do{
    $x,$y=$a[--$i],$b[$i]|%{
        if($_-eq45){                                # [char]45 is '-'
            $signs+=$_
            $_=0
        }
        $_                                          # a digit or $null
    }
    $res=(+"$x"*"$y"|% toString "00")+$res          # "00" is the custom format to get 2-digit number
}
while($x+$y)
$signs+$res-replace'(?<!\d)0+(?=\d)|--|-(?=0+$)'    # cleanup and return

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.