Multiplicação de zíper


20

Introdução

Vamos definir uma nova operação aritmética, que chamo de multiplicação de zíper . Para multiplicar por zíper dois números inteiros não negativos, adicione zeros à esquerda para fazer coincidir os comprimentos, multiplique os dígitos da base 10 correspondentes dos números, adicione zeros à esquerda aos resultados para obter números de 2 dígitos, concatená-los e, finalmente, soltar zeros à esquerda.

Aqui está um exemplo com A = 1276 e 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

A operação é estendida a todos os números inteiros com as regras usuais de sinal: tempos positivos negativos são negativos, tempos negativos negativos são positivos e assim por diante.

A tarefa

Suas entradas são dois números inteiros e sua saída é a multiplicação de zíper. Você deve poder manipular entradas arbitrariamente grandes. A entrada e / ou a saída podem estar no formato de string (e de fato devem estar, se o seu idioma não suportar números inteiros arbitrariamente grandes). Observe que -0não é uma entrada ou saída válida.

Regras e pontuação

Você pode escrever um programa completo ou uma função, e a menor contagem de bytes vence.

Casos de teste

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

Respostas:


8

Geléia , 11 10 bytes

ƓDUz0P€Uḅ³

Experimente online!

Eu não conseguia baixar isso para 10 bytes sozinho, mas o @ Pietu1998 me indicou um átomo que eu havia perdido, dando essa solução de 10 bytes. Invulgarmente para o Jelly, este recebe entrada da entrada padrão (no formulário 1276,933024), não da linha de comando (isso permite o uso do ³comando, que retorna o argumento da linha de comando, com o padrão 100).

Explicação:

Ɠ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

O uso da base 100 é uma maneira simples de implementar a técnica "almofada para 2 dígitos e depois converter para a base 10". A única outra coisa sutil aqui é a inversão; queremos preencher com zeros no início do número, mas os zcomandos de Jelly no final, portanto, inverter as listas significa que zo preenchimento será correto.


3
Você pode substituir b⁵por Dpara obter os 10 bytes. : P
PurkkaKoodari

4

Python 2, 99 bytes

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

Muitos bytes existem para contabilizar o sinal em caso de entrada negativa. Em Python,n%d sempre é não negativo se dfor positivo 1 . Na minha opinião, isso geralmente é desejável, mas aqui parece inconveniente: remover as chamadas para absquebraria o código acima. Enquanto isso, pmantém o controle do "valor de posição" (uns, centenas, etc.) e também se lembra do sinal desejado da saída.

O código é basicamente simétrico aeb exceto na whilecondição: continuamos até azero e terminamos nesse momento. É claro que se bfor zero primeiro, acabaremos adicionando zeros por um tempo até que aseja zero também.


1 Por exemplo, (-33)%10retorna 7e o quociente inteiro de (-33)/10é -4. Isso está correto porque (-4)*10 + 7 = -33. No entanto, o produto (-33)com zíper de 33deve terminar em3*3 = 09 vez de 7*3 = 21.


3

JavaScript (ES6), 44 bytes

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

Convenientemente, isso funciona automaticamente para números negativos.


@Jakube Eu estou sempre fazendo isso, embora pelo menos eu tenha incluído o f=na contagem de bytes. Além disso, |0é porque eu preciso de divisão inteira, não sei como você acha que está obtendo a resposta certa sem ela.
Neil

Ah, isso faz sentido. Agora também recebo respostas erradas ao remover |0. Talvez a reatribuição da nova função para f não funcionou e eu ainda testei a versão antiga |0.
Jakube 9/12

2

C, 77 bytes

-2 bytes para remover chaves redundantes ( *é associativo).

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, ... é usado para preenchimento. Enquanto aou bnão for zero, continue multiplicando o último dígito %10com te acumule. Em seguida, apague o último dígito de ae b( /=10) e desloque-ot 2 dígitos ( *=100).

Ungolfed e uso:

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

Sugerir em for(r=0;a|b;t*=100)r+=a%10*t*(b%10),a/=10,b/=10vez der=0;while(a|b)r+=t*(a%10)*(b%10),a/=10,b/=10,t*=100
ceilingcat

1

Na verdade , 23 19 bytes

A entrada é tomada como duas cadeias. Além disso, aparentemente, tentar converter da base 100, como ais523 faz em sua resposta Jelly, não funciona tão bem na verdade. Também teria economizado 9 bytes se funcionasse: / Sugestões de golfe são bem-vindas! Experimente online!

Edit: -4 bytes, alterando a forma como o resultado é incorporado em um novo número.

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 Bytes

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

Ungolfed:

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

onde% significa que a produção anterior produz

{{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 bytes

Não é mais a resposta mais longa (obrigado, Racket) e, na verdade, mais curta que a solução Python (um tratamento raro)! Uma função anônima que recebe dois números inteiros como entrada.

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

Aqui está como isso funciona.

A multiplicação do zíper envolve a divisão dos números de entrada em seus dígitos constituintes. Tomamos o valor absoluto do número e executamos o módulo para potências descendentes de 10:

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

Então, aqui estamos pegando um número x,, e aplicando o módulo com outros 99 números ( 10^99através 10^1). R repete implicitamente x99 vezes, retornando um vetor (lista) com 99 elementos. ( x %% 10^99,x %% 10^98 , x %% 10^97, Etc.)

Nós usamos 10^99através10^1 . Uma implementação mais eficiente usaria o valor do número de dígitos no número mais longo (verifique o histórico de edição desta postagem; as versões anteriores fizeram isso), mas simplesmente usando99..1 usar menos bytes.

Pois x = 1276isso nos dá

1276 1276 1276 ... 1276 276 76 6

Em seguida, usamos a divisão inteira por potências decrescentes de 10 para arredondar os números:

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

Isso gera

0 0 0 ... 1 2 7 6

que é exatamente a representação que queremos. No código, acabamos querendo usar 10^(98:0)novamente mais tarde, então atribuímos a uma variável:

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

(O agrupamento de uma expressão entre parênteses em R geralmente avalia a expressão (nesse caso, atribuindo o valor de 10^(98:0)a e) e também retorna a saída da expressão, permitindo incorporar atribuições de variáveis ​​em outros cálculos.)

Em seguida, realizamos a multiplicação em pares dos dígitos na entrada. A saída é preenchida com dois dígitos e concatenada. O preenchimento com dois dígitos e a concatenação é equivalente a multiplicar cada número por 10^n, onde nestá a distância da borda direita e depois somar todos os números.

 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

Notavelmente, porque a multiplicação é comutativa, podemos realizar a multiplicação por 10^n diante nós multiplicar A por B . Portanto, tomamos nosso cálculo anterior e multiplicamos por 10^(98:0):

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

que é equivalente a

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

Depois de aplicar esta para A , teríamos então quero repetir esta operação inteira em B . Mas isso requer bytes preciosos, por isso definimos uma função e precisamos escrevê-la apenas uma vez:

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

Realizamos nosso truque de incorporar parênteses para nos permitir definir e aplicar uma função ao mesmo tempo, para chamar essa função em A e B e multiplicá-las. (Poderíamos defini-lo em uma linha separada, mas, como eventualmente colocaremos tudo isso em uma função anônima, se tivermos mais de uma linha de código, tudo precisará ser envolvido em chaves, o que custa um valor valioso bytes.)

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

E pegamos a soma de tudo isso, e estamos quase terminando:

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

A única coisa a considerar agora é o sinal da entrada. Queremos seguir regras regulares de multiplicação; portanto, se um e apenas um de A e B for negativo, a saída será negativa. Usamos a função signque retorna 1quando recebe um número positivo e -1recebe um número negativo, para gerar um coeficiente que multiplicamos todo o cálculo por:

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

Finalmente, tudo está envolvido em uma função anônima que recebe ae bcomo entrada:

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

Remova o espaço em branco e são 86 bytes.


Seria ótimo se você pudesse fornecer uma versão explicada e não-gasta para o benefício de todos.
rnso

Atualizei a postagem com uma explicação.
rturnbull

Bom trabalho. Método muito inteligente usado.
rnso

1

Python 3 , 92 bytes , 119 bytes

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

Experimente online!

A correção para manipular números negativos custa 29 bytes: /


Boa resposta! Eu acho que você pode substituir a lstrippeça envolvendo tudo dentro int()e retornando um número.
ArBo

Você está certo. Então tive vontade de manter uma interface consistente. Tomando strings como argumentos em vez de int, e retornar um int parece estranho para mim;) Eu esperava alterar o loop for zip + para uma chamada de mapa, mas isso não funcionaria: /
movatica

Eu não me preocuparia muito com a consistência no código de golfe, mas depende de você :). O mapeamento geralmente não é muito bom em Python, se você precisar criar um lambda extra para fazer isso.
ArBo

Esta função parece falhar para entradas negativas
ArBo

Você está certo: / A correção é bastante cara, talvez exista mais potencial para jogar golfe.
movatica


0

PHP, 84 bytes

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

um pouco mais com concatenação de strings (86 bytes):

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

0

Raquete 325 bytes

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

Teste:

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

Saída:

3001424
0
0
1203021800
-1000420803

0

PowerShell , 153 151 bytes

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+$)'

Experimente online!

Menos golfe:

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 5 -MList::Util=min , 140 bytes

@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

Experimente online!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.