Reißverschluss-Multiplikation

20

Einführung

Definieren wir eine neue Rechenoperation, die ich als Zipper-Multiplikation bezeichne . Um zwei nichtnegative Ganzzahlen mit dem Reißverschluss zu multiplizieren, fügen Sie führende Nullen hinzu, damit die Längen übereinstimmen, multiplizieren Sie die entsprechenden 10-stelligen Ziffern der Zahlen, fügen Sie führende Nullen zu den Ergebnissen hinzu, um zweistellige Zahlen zu erhalten, verketten Sie sie und lassen Sie schließlich führende Nullen fallen.

Hier ist ein Beispiel mit A = 1276 und 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

Die Operation wird auf alle Ganzzahlen mit den üblichen Vorzeichenregeln ausgedehnt: positive Zeiten sind negativ, negative Zeiten sind positiv und so weiter.

Die Aufgabe

Ihre Eingaben sind zwei Ganzzahlen, und Ihre Ausgabe ist ihre Reißverschluss-Multiplikation. Sie sollten mit beliebig großen Eingaben umgehen können. Die Eingabe und / oder Ausgabe kann im Zeichenfolgenformat erfolgen (und muss auch erfolgen, wenn Ihre Sprache keine willkürlich großen Ganzzahlen unterstützt). Beachten Sie, dass dies -0keine gültige Eingabe oder Ausgabe ist.

Regeln und Wertung

Sie können ein vollständiges Programm oder eine Funktion schreiben, und die niedrigste Byteanzahl gewinnt.

Testfälle

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
quelle

Antworten:

8

Jelly , 11 bis 10 Bytes

ƓDUz0P€Uḅ³

Probieren Sie es online!

Ich konnte das allein nicht auf 10 Bytes reduzieren, aber @ Pietu1998 zeigte mir ein Atom, das ich verpasst hatte, was zu dieser 10-Byte-Lösung führte. Ungewöhnlich für Jelly ist, dass diese Eingabe von der Standardeingabe (im Formular 1276,933024) und nicht von der Befehlszeile stammt (dies ermöglicht die Verwendung des ³Befehls, der das Befehlszeilenargument mit dem Standardwert 100 zurückgibt).

Erläuterung:

Ɠ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

Die Verwendung der Basis 100 ist eine einfache Möglichkeit, das "Pad auf 2 Ziffern umzustellen und dann auf die Basis 10 umzustellen". Das einzige andere subtile Ding hier ist das Umkehren; Wir möchten am Anfang der Zahl mit Nullen auffüllen, aber Jellys zBefehl wird am Ende aufgefüllt. Wenn Sie also die Listen umkehren, zwird die Auffüllung korrekt ausgeführt.


quelle
3
Sie können ersetzen b⁵mit Dbekommen die 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

Viele der Bytes sind dazu da, das Vorzeichen bei negativer Eingabe zu berücksichtigen. n%dIst in Python immer nicht negativ, wenn dpositiv 1 ist . Meiner Meinung nach ist dies im Allgemeinen wünschenswert, aber hier scheint es unpraktisch: Das Entfernen der Aufrufe von abswürde den obigen Code beschädigen. In der Zwischenzeit wird pder "Stellenwert" (Einsen, Hunderten usw.) protokolliert und das gewünschte Vorzeichen der Ausgabe gespeichert.

Der Code ist im Grunde genommen symmetrisch aund babgesehen von der whileBedingung: Wir fahren fort, bis aNull ist, und enden zu diesem Zeitpunkt. Wenn natürlich bzuerst Null ist, werden wir für eine Weile Nullen hinzufügen, bis auch aNull ist.


1 Gibt beispielsweise (-33)%10zurück 7und der ganzzahlige Quotient von (-33)/10ist -4. Das ist richtig, weil (-4)*10 + 7 = -33. Das Reißverschlussprodukt von (-33)with 33muss jedoch 3*3 = 09eher als enden 7*3 = 21.

mathmandan
quelle
3

JavaScript (ES6), 44 Byte

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

Praktischerweise funktioniert dies automatisch für negative Zahlen.

Neil
quelle
@Jakube mache ich immer so, obwohl ich das zumindest f=in die Byteanzahl miteinbezogen habe . Das liegt auch daran, |0dass ich eine Ganzzahldivision benötige. Ich weiß nicht, wie Sie denken, dass Sie ohne diese die richtige Antwort erhalten.
Neil
Ah, das macht Sinn. Jetzt bekomme ich auch falsche Antworten beim Entfernen |0. Vielleicht hat die Neuzuweisung der neuen Funktion zu f nicht funktioniert und ich habe die alte Version trotzdem mit getestet |0.
Jakube
2

C 77 Bytes

-2 Bytes zum Entfernen redundanter Klammern ( *assoziativ).

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, ... wird zum Auffüllen verwendet. Solange aoder bnicht Null ist, multiplizieren Sie die letzte Ziffer %10mit tund akkumulieren Sie. Löschen Sie dann die letzte Ziffer von aund b( /=10) und verschieben Sie sie tum 2 Ziffern ( *=100).

Ungolfed und Nutzung:

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
quelle
Schlagen Sie for(r=0;a|b;t*=100)r+=a%10*t*(b%10),a/=10,b/=10stattdessen vorr=0;while(a|b)r+=t*(a%10)*(b%10),a/=10,b/=10,t*=100
ceilingcat
1

Eigentlich , 23 19 Bytes

Die Eingabe erfolgt als zwei Zeichenfolgen. Offensichtlich funktioniert der Versuch, von der Basis 100 zu konvertieren, wie es ais523 in seiner Jelly-Antwort tut, in Actually nicht so gut. Hätte auch 9 Bytes gespart, wenn es geklappt hätte: / Golfvorschläge erwünscht! Probieren Sie es online!

Edit: -4 Bytes von der Änderung, wie das Ergebnis in eine neue Zahl aufgebaut wird.

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
quelle
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@%

Dabei bedeutet% die vorherigen Produktionserträge

{{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
quelle
1

R 182 110 107 86 Bytes

Nicht mehr die längste Antwort (danke, Racket) und tatsächlich kürzer als die Python-Lösung (eine seltene Belohnung)! Eine anonyme Funktion, die zwei Ganzzahlen als Eingabe verwendet.

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

So funktioniert das.

Bei der Zipper-Multiplikation werden die eingegebenen Zahlen in ihre konstituierenden Ziffern aufgeteilt. Wir nehmen den absoluten Wert der Zahl und führen modulo für absteigende Potenzen von 10 aus:

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

Also nehmen wir hier eine Zahl xund wenden modulo mit 99 anderen Zahlen ( 10^99bis 10^1) an. R wiederholt sich implizit x99 Mal und gibt einen Vektor (Liste) mit 99 Elementen zurück. ( x %% 10^99, x %% 10^98, x %% 10^97, Etc.)

Wir nutzen 10^99durch 10^1. Eine effizientere Implementierung würde den Wert der Anzahl der Ziffern in der längsten Zahl verwenden (überprüfen Sie den Bearbeitungsverlauf dieses Beitrags; frühere Versionen haben dies getan), benötigt jedoch einfach 99..1weniger Bytes.

Dafür x = 1276gibt uns

1276 1276 1276 ... 1276 276 76 6

Als nächstes verwenden wir die Ganzzahldivision durch absteigende Zehnerpotenzen, um die Zahlen abzurunden:

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

Dies ergibt

0 0 0 ... 1 2 7 6

Das ist genau die Darstellung, die wir wollen. Im Code möchten 10^(98:0)wir ihn später wieder verwenden und weisen ihn einer Variablen zu:

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

(Das Umschließen eines Ausdrucks in Klammern in R wertet den Ausdruck im Allgemeinen aus (in diesem Fall wird der Wert von 10^(98:0)bis zugewiesen e) und gibt dann auch die Ausgabe des Ausdrucks zurück, sodass wir die Variablenzuweisungen in andere Berechnungen einbetten können.)

Als nächstes führen wir eine paarweise Multiplikation der Ziffern in der Eingabe durch. Die Ausgabe wird dann auf zwei Ziffern aufgefüllt und verkettet. Das Auffüllen auf zwei Ziffern und Verketten entspricht dem Multiplizieren jeder Zahl mit 10^n, wobei nder Abstand von der rechten Kante ist, und anschließendes Summieren aller Zahlen.

 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

Da die Multiplikation kommutativ ist, können wir die Multiplikation mit ausführen, 10^n bevor wir A mit B multiplizieren . Also nehmen wir unsere frühere Rechnung und multiplizieren mit 10^(98:0):

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

das ist äquivalent zu

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

Nachdem wir dies auf A angewendet haben, möchten wir diese ganze Operation auf B wiederholen . Da dies jedoch kostbare Bytes erfordert, definieren wir eine Funktion, sodass wir sie nur einmal schreiben müssen:

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

Wir machen unseren Einbetten-in-Klammern-Trick, damit wir eine Funktion gleichzeitig definieren und anwenden können, um diese Funktion für A und B aufzurufen und sie miteinander zu multiplizieren. (Wir hätten es in einer separaten Zeile definieren können, aber weil wir dies alles irgendwann in eine anonyme Funktion umwandeln werden, muss alles in geschweifte Klammern gesetzt werden, was wertvoll ist Bytes.)

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

Und wir nehmen die Summe von all dem und wir sind fast fertig:

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

Das einzige, was jetzt zu berücksichtigen ist, ist das Vorzeichen der Eingabe. Wir wollen regulären Multiplikationsregeln folgen. Wenn also nur eine von A und B negativ ist, ist die Ausgabe negativ. Wir verwenden die Funktion, signdie 1bei einer positiven Zahl und -1bei einer negativen Zahl zurückgibt , um einen Koeffizienten auszugeben, mit dem wir unsere gesamte Berechnung multiplizieren:

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

Schließlich wird das Ganze in eine anonyme Funktion eingewickelt, der nimmt aund bals Eingang:

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

Entfernen Sie das Leerzeichen und es ist 86 Bytes.

rturnbull
quelle
Es wäre großartig, wenn Sie eine ungolfederte, erklärte Version zum Nutzen aller zur Verfügung stellen könnten.
RNSO
Ich habe den Beitrag mit einer Erklärung aktualisiert.
Rturnbull
Gut gemacht. Sehr clevere Methode angewendet.
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]))

Probieren Sie es online!

Korrektur für den Umgang mit negativen Zahlen kostet 29 Bytes: /

movatica
quelle
Gute Antwort! Ich denke, Sie können das lstripTeil ersetzen, indem Sie alles einpacken int()und eine Zahl zurückgeben.
ArBo
Du hast recht. Dann hatte ich Lust auf eine einheitliche Oberfläche. Wenn ich Strings als Argumente anstelle von int nehme und dann ein int zurückgebe, sieht das komisch aus;) Ich hatte eher gehofft, die zip + for-Schleife für einen Kartenaufruf zu ändern, aber das würde nicht funktionieren: /
movatica
Ich würde mir nicht allzu viele Sorgen um die Konsistenz beim Code-Golf machen, aber es liegt an Ihnen :). Das Mappen ist in Python normalerweise nicht besonders hilfreich, wenn Sie dafür ein zusätzliches Lambda benötigen.
ArBo
Diese Funktion scheint bei negativen Eingängen nicht zu funktionieren
ArBo
Sie haben Recht: / Das Update ist ziemlich teuer, vielleicht gibt es mehr Potenzial, es herunterzuspielen.
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;

etwas länger mit String-Verkettung (86 Bytes):

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

Schläger 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))))

Testen:

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

Ausgabe:

3001424
0
0
1203021800
-1000420803
rnso
quelle
0

PowerShell , 153 151 Byte

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

Probieren Sie es online!

Weniger golfen:

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

Probieren Sie es online!

Xcali
quelle