拉链乘法


20

介绍

让我们定义一个新的算术运算,我称之为拉链乘法。要用拉链将两个非负整数相乘,请添加前导零以使长度匹配,将数字的相应前十个数字相乘,在结果中添加前导零以得到2位数字,将它们连接起来,最后删除前导零。

这是A = 1276B = 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

Answers:


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

使用base 100是实现“填充两位数,然后转换为base 10”技术的简单方法。唯一的其他微妙的事情就是倒车。我们希望在数字的开头填充零,但在Jelly的z命令z填充末尾,因此反转列表意味着可以正确填充。


3
您可以替换b⁵使用D,以获得10个字节。:P
PurkkaKoodari '16

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跟踪“位置值”(一个,数百个等),并记住输出的期望符号。

该代码是在基本对称ab除了在while条件:我们继续下去,直到a为零,而在那个时候终止。当然,如果b首先为零,那么我们将在一段时间内添加零,直到a也为零。


1例如,(-33)%10返回7,并且的整数商(-33)/10-4。这是正确的,因为(-4)*10 + 7 = -33。但是,(-33)with 的拉链产品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,...用于填充。只要ab不为零保持multiplicating最后一位%10t和积累。然后删除ab/=10)的最后一位,并移位t两位(*=100)。

脱胶和用法:

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
ceilingcat

1

事实上23 19个字节

输入被视为两个字符串。另外,显然,像ais523在Jelly答案中所做的那样,尝试从基数100转换,在实际上中效果不佳。如果可以的话,也可以节省9个字节:/欢迎打高尔夫!在线尝试!

编辑: -4字节,用于更改将结果构建为新数字的方式。

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

开球

          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/@#]]&

取消高尔夫:

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字节

不再是最长的答案(感谢,Racket),实际上比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^9910^1)求模。R隐式重复x99次,返回包含99个元素的向量(列表)。(x %% 10^99x %% 10^98x %% 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 AB相乘之前执行乘。因此,我们采用前面的计算并乘以10^(98:0)

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

相当于

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

我们执行了“嵌入括号”技巧,以允许我们同时定义和应用一个函数,以便在AB上调用此函数并将它们相乘。(我们可以在单独的行上定义它,但是由于我们最终将所有这些都放到一个匿名函数中,因此,如果我们有多行代码,则所有内容都需要用大括号括起来,这很有价值。个字节。)

(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))

现在唯一要考虑的是输入的符号。我们要遵循常规的乘法规则,因此,如果AB中只有一个为负,则输出为负。我们使用在给定正数和给定负数时sign返回的函数来输出一个系数,将整个计算结果乘以:1-1

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

最后,整个东西被包装到一个匿名函数中,该函数接受ab作为输入:

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()并返回数字来替换零件。
ArBo

你是对的。然后,我想保持一致的界面。以字符串而不是int作为参数,然后返回int对我来说看起来很奇怪;)我宁愿希望更改map调用的zip + for循环,但这不起作用:/
movatica

我不会太担心代码高尔夫球的一致性,但这取决于您:)。如果您需要额外的lambda来完成映射,则在Python中通常不是很容易理解。
ArBo

对于负输入,此功能似乎失败
ArBo

您是对的:/修理费用很高,也许打高尔夫球的潜力更大。
movatica


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)))

取消高尔夫:

(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

PowerShell153151字节

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

0

Perl -MList::Util=min 5,140个字节

@a=<>=~/\S/g;@F=<>=~/\S/g;$q=1+min$#a,$#F;say+('-'x("@a@F"=~y/-//%2).sprintf'%02d'x$q,map$F[$_]*$a[$_],-$q..-1)=~s/^-?\K0+//r=~s/^-0*$//r||0

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.