Multiplicación de cremallera

20

Introducción

Definamos una nueva operación aritmética, que llamo multiplicación de cremallera . Para que la cremallera multiplique dos enteros no negativos, agrega ceros a la izquierda para hacer que las longitudes coincidan, multiplique los dígitos de base 10 correspondientes de los números, agregue ceros a los resultados para obtener números de 2 dígitos, concatenelos y finalmente suelte los ceros a la izquierda.

Aquí hay un ejemplo con A = 1276 y 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

La operación se extiende a todos los enteros con las reglas de signos habituales: los tiempos positivos negativos son negativos, los tiempos negativos negativos son positivos y así sucesivamente.

La tarea

Sus entradas son dos enteros, y su salida es su multiplicación de cremallera. Debería poder manejar entradas arbitrariamente grandes. La entrada y / o salida puede estar en formato de cadena (y de hecho debe estarlo, si su idioma no admite enteros arbitrariamente grandes). Tenga en cuenta que -0no es una entrada o salida válida.

Reglas y puntaje

Puede escribir un programa completo o una función, y gana el conteo de bytes más bajo.

Casos de prueba

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
Zgarb
fuente

Respuestas:

8

Jalea , 11 10 bytes

ƓDUz0P€Uḅ³

Pruébalo en línea!

No pude reducir esto a 10 bytes por mí mismo, pero @ Pietu1998 me señaló un átomo que había perdido, lo que me dio esta solución de 10 bytes. Inusualmente para Jelly, este toma la entrada de la entrada estándar (en el formulario 1276,933024), no de la línea de comando (esto permite el uso del ³comando, que devuelve el argumento de la línea de comando, por defecto a 100).

Explicación:

Ɠ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

El uso de la base 100 es una forma sencilla de implementar la "almohadilla de 2 dígitos" y luego convertirla en la técnica de base 10. La única otra cosa sutil aquí es la inversión; queremos rellenar con ceros al comienzo del número, pero el zcomando de Jelly zse rellena al final, por lo que invertir las listas significa que se rellenará correctamente.


fuente
3
Puede reemplazar b⁵con Dpara obtener los 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

Muchos de los bytes están ahí para dar cuenta del signo en caso de entrada negativa. En Python, n%dsiempre es no negativo si des positivo 1 . En mi opinión, esto es generalmente deseable, pero aquí parece inconveniente: eliminar las llamadas a absrompería el código anterior. Mientras tanto, prealiza un seguimiento del "valor posicional" (unos, cientos, etc.) y también recuerda el signo deseado de la salida.

El código es básicamente simétrico en ay bexcepto en la whilecondición: continuamos hasta que aes cero y terminamos en ese momento. Por supuesto, si bes cero primero, entonces terminaremos agregando ceros por un tiempo hasta que también asea ​​cero.


1 Por ejemplo, (-33)%10devuelve 7, y el cociente entero de (-33)/10is -4. Esto es correcto porque (-4)*10 + 7 = -33. Sin embargo, el producto de la cremallera de (-33)with 33debe terminar en 3*3 = 09lugar de 7*3 = 21.

Mathmandan
fuente
3

JavaScript (ES6), 44 bytes

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

Convenientemente, esto funciona automáticamente para números negativos.

Neil
fuente
@Jakube Siempre estoy haciendo eso, aunque al menos incluí el f=en el conteo de bytes. Además, |0es porque necesito una división entera, no sé cómo crees que estás obteniendo la respuesta correcta sin ella.
Neil
Ah, eso tiene sentido. Ahora también obtengo respuestas incorrectas al eliminar |0. Tal vez la reasignación de la nueva función a f no funcionó y todavía probé la versión anterior con |0.
Jakube
2

C, 77 bytes

-2 bytes para eliminar llaves redundantes ( *es asociativo).

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, ... se usa para relleno. Mientras ao bno sea cero, sigue multiplicando el último dígito %10con ty acumula. Luego, elimine el último dígito de ay b( /=10) y cambie t2 dígitos ( *=100).

Sin golf y 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));
}
Karl Napf
fuente
Sugerir en for(r=0;a|b;t*=100)r+=a%10*t*(b%10),a/=10,b/=10lugar der=0;while(a|b)r+=t*(a%10)*(b%10),a/=10,b/=10,t*=100
ceilingcat
1

En realidad , 23 19 bytes

La entrada se toma como dos cadenas. Además, aparentemente intentar convertir desde la base 100, como ais523 hace en su respuesta Jelly, no funciona tan bien en realidad. Hubiera ahorrado 9 bytes también si hubiera funcionado: / ¡Se aceptan sugerencias de golf! Pruébalo en línea!

Editar: -4 bytes desde cambiar la forma en que el resultado se construye en un nuevo número.

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

No golfista

          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.
Sherlock9
fuente
1

Mathematica 66 Bytes

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

Sin golf:

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

donde% significa los rendimientos de producción anteriores

{{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
Kelly Lowder
fuente
1

R, 182 , 110, 107, 86 bytes

¡Ya no es la respuesta más larga (gracias, Racket), y de hecho es más corta que la solución Python (un regalo raro)! Una función anónima que toma dos enteros 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)

Así es como funciona.

La multiplicación de la cremallera implica dividir los números de entrada en sus dígitos constituyentes. Tomamos el valor absoluto del número y realizamos el módulo para potencias descendentes de 10:

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

Así que aquí estamos tomando un número, xy aplicando módulo con otros 99 números (a 10^99través 10^1). R repite implícitamente x99 veces, devolviendo un vector (lista) con 99 elementos. ( x %% 10^99, x %% 10^98, x %% 10^97, Etc.)

Usamos a 10^99través de 10^1. Una implementación más eficiente usaría el valor del número de dígitos en el número más largo (verifique el historial de edición de esta publicación; las versiones anteriores lo hicieron), pero simplemente toma 99..1menos bytes.

Por x = 1276esto nos da

1276 1276 1276 ... 1276 276 76 6

A continuación, usamos la división de enteros mediante poderes descendentes de 10 para redondear los números:

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

Esto produce

0 0 0 ... 1 2 7 6

cuál es exactamente la representación que queremos. En el código, terminamos queriendo usar 10^(98:0)nuevamente más tarde, por lo que lo asignamos a una variable:

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

(Ajustar una expresión entre paréntesis en R generalmente evalúa la expresión (en este caso, asignando el valor de 10^(98:0)to e), y luego también devuelve el resultado de la expresión, lo que nos permite incrustar asignaciones variables dentro de otros cálculos).

A continuación, realizamos la multiplicación por pares de los dígitos en la entrada. La salida se rellena luego con dos dígitos y se concatena. El relleno de dos dígitos y la concatenación es equivalente a multiplicar cada número por 10^n, donde nestá la distancia desde el borde derecho, y luego sumar todos los 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

En particular, ya que la multiplicación es conmutativa, podemos realizar la multiplicación por 10^n delante de multiplicamos A por B . Entonces, tomamos nuestro cálculo anterior y lo multiplicamos por 10^(98:0):

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

que es equivalente a

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

Después de aplicar esto a A , tendríamos entonces querrá repetir toda esta operación en B . Pero eso requiere bytes preciosos, por lo que definimos una función para que solo tengamos que escribirla una vez:

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

Hacemos nuestro truco de incrustación entre paréntesis para permitirnos definir y aplicar una función al mismo tiempo, llamar a esta función en A y B y multiplicarlas. (Podríamos haberlo definido en una línea separada, pero debido a que eventualmente pondremos todo esto en una función anónima, si tenemos más de una línea de código, entonces todo debe estar envuelto en llaves, lo que cuesta valioso bytes)

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

Y tomamos la suma de todo esto, y casi hemos terminado:

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

Lo único a considerar ahora es el signo de la entrada. Queremos seguir reglas de multiplicación regulares, por lo que si uno y solo uno de A y B es negativo, la salida es negativa. Usamos la función signque regresa 1cuando se le da un número positivo y -1cuando se le da un número negativo, para generar un coeficiente que multiplicamos todo nuestro cálculo por:

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

Finalmente, todo está envuelto en una función anónima que toma ay 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)

Elimina el espacio en blanco y son 86 bytes.

rturnbull
fuente
Sería genial si pudieras proporcionar una versión explicada y sin golf para beneficio de todos.
rnso
He actualizado la publicación con una explicación.
rturnbull
Gran trabajo. Método muy inteligente utilizado.
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]))

Pruébalo en línea!

La solución para manejar números negativos cuesta 29 bytes: /

movatica
fuente
¡Buena respuesta! Creo que puede reemplazar la lstripparte envolviendo todo dentro int()y devolviendo un número.
ArBo
Tienes razón. Entonces tuve ganas de mantener una interfaz consistente. Tomar cadenas como argumentos en lugar de int, luego devolver un int me parece extraño;) Prefiero cambiar el zip + for loop para una llamada de mapa, pero eso no funcionaría: /
movatica
No me preocuparía demasiado por la consistencia en el código de golf, pero depende de usted :). El mapeo generalmente no es muy complejo en Python si necesita hacer una lambda adicional para hacerlo.
ArBo
Esta función parece fallar para entradas negativas
ArBo
Tienes razón: / La solución es bastante cara, tal vez hay más potencial para jugar golf.
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;

ligeramente más largo con concatenación de cadenas (86 bytes):

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

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

Sin golf:

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

Pruebas:

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

Salida:

3001424
0
0
1203021800
-1000420803
rnso
fuente
0

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

Pruébalo en línea!

Menos golfizado:

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
mazzy
fuente
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

Pruébalo en línea!

Xcali
fuente