Multiplication à glissière

20

introduction

Définissons une nouvelle opération arithmétique, que j'appelle la multiplication à glissière . Pour zipper multiplier deux entiers non négatifs, vous ajoutez des zéros de tête pour faire correspondre les longueurs, multipliez les 10 chiffres de base correspondants des nombres, ajoutez des zéros de tête aux résultats pour obtenir des nombres à 2 chiffres, concaténez-les et enfin supprimez les zéros de tête.

Voici un exemple avec A = 1276 et 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

L'opération est étendue à tous les entiers avec les règles de signe habituelles: les temps positifs négatifs sont négatifs, les temps négatifs négatifs sont positifs et ainsi de suite.

La tâche

Vos entrées sont deux entiers, et votre sortie est leur multiplication à glissière. Vous devriez pouvoir gérer des entrées arbitrairement grandes. L'entrée et / ou la sortie peuvent être au format chaîne (et doivent l'être, si votre langue ne prend pas en charge des entiers arbitrairement grands). Notez que ce -0n'est pas une entrée ou une sortie valide.

Règles et notation

Vous pouvez écrire un programme complet ou une fonction, et le nombre d'octets le plus bas l'emporte.

Cas de test

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
la source

Réponses:

8

Gelée , 11 10 octets

ƓDUz0P€Uḅ³

Essayez-le en ligne!

Je ne pouvais pas descendre cela à 10 octets par moi-même, mais @ Pietu1998 m'a montré un atome que j'avais manqué, ce qui donne cette solution à 10 octets. Exceptionnellement pour Jelly, celui-ci prend l'entrée de l'entrée standard (dans le formulaire 1276,933024), pas de la ligne de commande (cela permet l'utilisation de la³ commande, qui retourne l'argument de la ligne de commande, par défaut à 100).

Explication:

Ɠ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

L'utilisation de la base 100 est un moyen simple de mettre en œuvre la technique du "pad à 2 chiffres, puis de la convertir en base 10". La seule autre chose subtile ici est l'inversion; nous voulons remplir avec des zéros au début du numéro, mais les zcommandes de Jelly à la fin, donc inverser les listes signifie que cela zremplira correctement.


la source
3
Vous pouvez remplacer b⁵par Dpour obtenir les 10 octets. : P
PurkkaKoodari
4

Python 2, 99 octets

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

Beaucoup d'octets sont là pour tenir compte du signe en cas d'entrée négative. En Python, n%dest toujours non négatif si dest positif 1 . À mon avis, cela est généralement souhaitable, mais ici cela semble gênant: supprimer les appels à abscasserait le code ci-dessus. Pendant ce temps, pgarde une trace de la «valeur de position» (un, des centaines, etc.) et se souvient également du signe souhaité de la sortie.

Le code est fondamentalement symétrique dans aet bsauf dans la whilecondition: nous continuons jusqu'à ce que asoit zéro, et nous terminons à ce moment. Bien sûr, si bzéro est d'abord, nous finirons par ajouter des zéros pendant un certain temps jusqu'à ce que azéro soit également.


1 Par exemple, (-33)%10renvoie 7et le quotient entier de (-33)/10est -4. C'est correct parce que (-4)*10 + 7 = -33. Cependant, le produit de fermeture éclair de (-33)avec 33doit se terminer par 3*3 = 09plutôt que 7*3 = 21.

mathmandan
la source
3

JavaScript (ES6), 44 octets

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

Idéalement, cela fonctionne automatiquement pour les nombres négatifs.

Neil
la source
@Jakube Je fais toujours ça, bien qu'au moins j'aie inclus le f=dans le nombre d'octets. De plus, |0c'est parce que j'ai besoin d'une division entière, je ne sais pas comment vous pensez que vous obtenez la bonne réponse sans elle.
Neil
Ah, ça a du sens. Maintenant, je reçois également de mauvaises réponses lors de la suppression |0. Peut-être que la réaffectation de la nouvelle fonction à f n'a pas fonctionné et j'ai quand même testé l'ancienne version avec |0.
Jakube
2

C, 77 octets

-2 octets pour supprimer les accolades redondantes ( *est associatif).

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, ... est utilisé pour le rembourrage. Tant que aou bn'est pas nul, multipliez le dernier chiffre %10avec tet accumulez. Effacez ensuite le dernier chiffre de aet b( /=10) et décalez tde 2 chiffres (*=100 ).

Non golfé et utilisation:

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
la source
Suggérer à la for(r=0;a|b;t*=100)r+=a%10*t*(b%10),a/=10,b/=10place der=0;while(a|b)r+=t*(a%10)*(b%10),a/=10,b/=10,t*=100
plafondcat
1

En fait , 23 19 octets

L'entrée est considérée comme deux chaînes. De plus, essayer de convertir à partir de la base 100, comme le fait ais523 dans sa réponse Jelly, ne fonctionne pas si bien dans Actually. Aurait économisé 9 octets aussi si cela avait fonctionné: / Suggestions de golf bienvenues! Essayez-le en ligne!

Modifier: -4 octets de changer la façon dont le résultat est construit dans un nouveau nombre.

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.
Sherlock9
la source
1

Mathematica 66 octets

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

Non golfé:

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

où% signifie le rendement précédent

{{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
la source
1

R, 182 110 107 86 bytes

Ce n'est plus la réponse la plus longue (merci, Racket), et en fait plus courte que la solution Python (un plaisir rare)! Une fonction anonyme qui prend deux entiers en entrée.

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

Voici comment ça fonctionne.

La multiplication de la fermeture à glissière consiste à diviser les nombres entrés en leurs chiffres constitutifs.Nous prenons la valeur absolue du nombre et effectuons le modulo pour des puissances décroissantes de 10:

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

Donc, ici, nous prenons un nombre xet appliquons modulo avec 99 autres nombres (à 10^99travers 10^1). R se répète implicitement x99 fois, renvoyant un vecteur (liste) avec 99 éléments. ( x %% 10^99, x %% 10^98, x %% 10^97, Etc.)

Nous utilisons à 10^99travers 10^1. Une implémentation plus efficace utiliserait la valeur du nombre de chiffres dans le nombre le plus long (vérifiez l'historique des modifications de ce message; les versions précédentes l'ont fait), mais simplement en 99..1utilisant moins d'octets.

Car x = 1276cela nous donne

1276 1276 1276 ... 1276 276 76 6

Ensuite, nous utilisons la division entière par des puissances décroissantes de 10 pour arrondir les nombres:

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

Cela donne

0 0 0 ... 1 2 7 6

qui est exactement la représentation que nous voulons. Dans le code, on finit par vouloir réutiliser 10^(98:0)plus tard, donc on l'assigne à une variable:

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

(L'encapsulation d'une expression entre parenthèses dans R évalue généralement l'expression (dans ce cas, attribue la valeur de 10^(98:0)à e), puis renvoie également la sortie de l'expression, ce qui nous permet d'incorporer des affectations de variables dans d'autres calculs.)

Ensuite, nous effectuons une multiplication par paire des chiffres dans l'entrée. La sortie est ensuite complétée à deux chiffres et concaténée. Le remplissage à deux chiffres et la concaténation équivaut à multiplier chaque nombre par 10^n, où nest la distance à partir du bord droit, puis à additionner tous les nombres.

 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

Notamment parce que la multiplication est commutative, nous pouvons effectuer la multiplication par 10^n avant nous multiplier A par B . Donc, nous prenons notre calcul précédent et multiplions par 10^(98:0):

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

ce qui équivaut à

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

Après avoir appliqué ce à A , nous voulons alors répéter cette opération tout sur B . Mais cela prend des octets précieux, nous définissons donc une fonction, nous n'avons donc à l'écrire qu'une seule fois:

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

Nous faisons notre astuce d'intégration entre parenthèses pour nous permettre de définir et d'appliquer une fonction en même temps, d'appeler cette fonction sur A et B et de les multiplier ensemble. (Nous aurions pu le définir sur une ligne distincte, mais parce que nous allons finalement mettre tout cela dans une fonction anonyme, si nous avons plus d'une ligne de code, tout doit être entouré d'accolades, ce qui coûte cher octets.)

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

Et nous prenons la somme de tout cela, et nous avons presque terminé:

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

La seule chose à considérer maintenant est le signe de l'entrée. Nous voulons suivre des règles de multiplication régulières, donc si un et un seul de A et B est négatif, la sortie est négative. Nous utilisons la fonction signqui retourne 1quand on lui donne un nombre positif et -1quand on lui donne un nombre négatif, pour produire un coefficient que nous multiplions tout notre calcul par:

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

Enfin, le tout est enveloppé dans une fonction anonyme qui prend aet bcomme entrée:

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

Supprimez l'espace et c'est 86 octets.

rturnbull
la source
Ce sera génial si vous pouviez fournir une version expliquée et non golfée pour le bénéfice de tous.
rnso
J'ai mis à jour le message avec une explication.
rturnbull
Bon travail. Méthode très intelligente utilisée.
rnso
1

Python 3 , 92 octets , 119 octets

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

Essayez-le en ligne!

Correctif pour la gestion des nombres négatifs coûte 29 octets: /

movatica
la source
Bonne réponse! Je pense que vous pouvez remplacer la lstrippièce en enveloppant tout à l'intérieur int()et en renvoyant un numéro.
ArBo
Tu as raison. Ensuite, j'ai eu envie de garder une interface cohérente. Prendre des chaînes comme arguments au lieu de int, puis retourner un int me semble bizarre;) J'espérais plutôt changer le zip + pour la boucle pour un appel de carte, mais cela ne fonctionnerait pas: /
movatica
Je ne m'inquiéterais pas trop de la cohérence du code golf, mais c'est à vous de choisir :). La cartographie n'est généralement pas très golfique en Python si vous avez besoin de faire un lambda supplémentaire pour le faire.
ArBo
Cette fonction semble échouer pour les entrées négatives
ArBo
Vous avez raison: / Le correctif est assez cher, il y a peut-être plus de potentiel pour le jouer.
movatica
0

PHP, 84 octets

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

légèrement plus long avec concaténation de chaînes (86 octets):

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

Raquette 325 octets

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

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

Essai:

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

Production:

3001424
0
0
1203021800
-1000420803
rnso
la source
0

PowerShell , 153 151 octets

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

Essayez-le en ligne!

Moins golfé:

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
la source
0

Perl 5 -MList::Util=min , 140 octets

@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

Essayez-le en ligne!

Xcali
la source