Moltiplicazione con cerniera


20

introduzione

Definiamo una nuova operazione aritmetica, che chiamo moltiplicazione con cerniera . Per zippare moltiplicando due numeri interi non negativi, aggiungi gli zeri iniziali per far corrispondere le lunghezze, moltiplica le corrispondenti cifre di base 10 dei numeri, aggiungi gli zeri iniziali ai risultati per ottenere numeri di 2 cifre, concatenarli e infine rilasciare zeri iniziali.

Ecco un esempio con 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

L'operazione è estesa a tutti i numeri interi con le consuete regole dei segni: i tempi positivi negativi sono negativi, i tempi negativi negativi sono positivi e così via.

L'obiettivo

I tuoi input sono due numeri interi e il tuo output è la loro moltiplicazione con cerniera. Dovresti essere in grado di gestire input arbitrariamente grandi. L'input e / o l'output possono essere in formato stringa (e in effetti devono esserlo, se la tua lingua non supporta numeri interi arbitrariamente grandi). Si noti che -0non è un input o output valido.

Regole e punteggio

È possibile scrivere un programma completo o una funzione e vince il conteggio dei byte più basso.

Casi 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

Risposte:


8

Gelatina , 11 10 byte

ƓDUz0P€Uḅ³

Provalo online!

Non sono riuscito a ottenere questo da solo fino a 10 byte, ma @ Pietu1998 mi ha indicato un atomo che mi mancava, questo dando questa soluzione da 10 byte. Insolitamente per Jelly, questo prende input dall'input standard (nel modulo 1276,933024), non dalla riga di comando (questo abilita l'uso del ³comando, che restituisce l'argomento della riga di comando, per impostazione predefinita su 100).

Spiegazione:

Ɠ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'uso della base 100 è un modo semplice per implementare la tecnica "pad a 2 cifre, quindi convertirla in base 10". L'unica altra cosa sottile qui è l'inversione; vogliamo riempire con zero all'inizio del numero, ma i zcomandi di Jelly alla fine, quindi invertire gli elenchi significa che zandrà a buon fine.


3
È possibile sostituire b⁵con Dper ottenere i 10 byte. : P
PurkkaKoodari,

4

Python 2, 99 byte

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

Molti byte sono lì per tenere conto del segno in caso di input negativo. In Python, n%dè sempre non negativo se dè positivo 1 . A mio avviso ciò è generalmente auspicabile, ma qui sembra scomodo: rimuovere le chiamate per absinfrangere il codice sopra. Nel frattempo ptiene traccia del "valore del luogo" (uno, centinaia, ecc.) E ricorda anche il segno desiderato dell'output.

Il codice è sostanzialmente simmetrico ae btranne nella whilecondizione: continuiamo fino a quando aè zero e terminiamo in quel momento. Ovviamente se bè prima zero, poi finiremo per aggiungere degli zeri per un po 'fino a quando anche azero è zero.


1 Ad esempio, (-33)%10restituisce 7e il quoziente intero di (-33)/10è -4. Questo è corretto perché (-4)*10 + 7 = -33. Tuttavia, il prodotto (-33)con cerniera di with 33deve terminare 3*3 = 09anziché 7*3 = 21.


3

JavaScript (ES6), 44 byte

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

Convenientemente funziona automaticamente con numeri negativi.


@Jakube Lo faccio sempre, anche se almeno ho incluso il f=conteggio dei byte. Inoltre, |0è perché ho bisogno di una divisione intera, non so come pensi di ottenere la risposta giusta senza di essa.
Neil,

Ah, ha senso. Ora ricevo anche risposte errate durante la rimozione |0. Forse la riassegnazione della nuova funzione a f non ha funzionato e ho ancora testato la vecchia versione con |0.
Jakube,

2

C, 77 byte

-2 byte per la rimozione di parentesi graffe ridondanti ( *è associativa).

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, ... viene utilizzato per l'imbottitura. Finché aob non è zero mastio multiplicating l'ultima cifra %10con te si accumulano. Quindi cancellare l'ultima cifra di ae b( /=10) e spostarsi tdi 2 cifre ( *=100).

Ungolfed e utilizzo:

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

Suggerisci for(r=0;a|b;t*=100)r+=a%10*t*(b%10),a/=10,b/=10invece dir=0;while(a|b)r+=t*(a%10)*(b%10),a/=10,b/=10,t*=100
ceilingcat

1

In realtà , 23 19 byte

L'input viene preso come due stringhe. Inoltre, apparentemente tentare di convertire dalla base 100, come fa ais523 nella loro risposta Jelly, non funziona così bene in realtà. Avrebbe salvato anche 9 byte se funzionasse: / Suggerimenti per il golf sono benvenuti! Provalo online!

Modifica: -4 byte dalla modifica della modalità di creazione del risultato in un nuovo numero.

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 byte

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

Ungolfed:

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

dove% indica i rendimenti di output precedenti

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

Non è più la risposta più lunga (grazie, Racket), e in effetti più corta della soluzione Python (un piacere raro)! Una funzione anonima che accetta due numeri interi come input.

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

Ecco come funziona.

La moltiplicazione della cerniera comporta la divisione dei numeri di input nelle loro cifre costitutive. Prendiamo il valore assoluto del numero ed eseguiamo il modulo per poteri decrescenti di 10:

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

Quindi qui prendiamo un numero xe applichiamo il modulo con altri 99 numeri ( 10^99attraverso 10^1). R ripete implicitamente x99 volte, restituendo un vettore (elenco) con 99 elementi. ( x %% 10^99, x %% 10^98, x %% 10^97, Etc.)

Usiamo 10^99attraverso10^1 . Un'implementazione più efficiente userebbe il valore del numero di cifre nel numero più lungo (controlla la cronologia delle modifiche di questo post; le versioni precedenti hanno fatto questo), ma prendendo semplicemente 99..1usa meno byte.

Per x = 1276questo ci dà

1276 1276 1276 ... 1276 276 76 6

Quindi, usiamo la divisione intera decrescendo i poteri di 10 per arrotondare i numeri:

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

Questo cede

0 0 0 ... 1 2 7 6

che è esattamente la rappresentazione che vogliamo. Nel codice, finiamo per voler 10^(98:0)riutilizzarlo più tardi, quindi lo assegniamo a una variabile:

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

(Avvolgere un'espressione tra parentesi in R generalmente valuta l'espressione (in questo caso, assegnando il valore di 10^(98:0)a e), e quindi restituisce anche l'output dell'espressione, permettendoci di incorporare assegnazioni di variabili all'interno di altri calcoli.)

Successivamente, eseguiamo la moltiplicazione a coppie delle cifre nell'input. L'output viene quindi riempito con due cifre e concatenato. Il riempimento a due cifre e la concatenazione equivalgono a moltiplicare ciascun numero per 10^n, dov'è nla distanza dal bordo destro e quindi sommare tutti i numeri.

 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

In particolare, poiché la moltiplicazione è commutativa, possiamo eseguire la moltiplicazione per 10^n prima che moltiplicare A per B . Quindi, prendiamo il nostro calcolo precedente e moltiplichiamo per 10^(98:0):

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

che equivale a

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

Dopo l'applicazione di questo per A , avremmo poi si desidera ripetere tutta questa operazione su B . Ma questo richiede byte preziosi, quindi definiamo una funzione in modo da scriverla solo una volta:

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

Facciamo il nostro trucco tra parentesi per consentirci di definire e applicare una funzione allo stesso tempo, di chiamare questa funzione su A e B e moltiplicarli insieme. (Avremmo potuto definirlo su una riga separata, ma poiché alla fine metteremo tutto questo in una funzione anonima, se abbiamo più di una riga di codice, allora tutto deve essere racchiuso tra parentesi graffe, il che costa prezioso byte).

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

E prendiamo la somma di tutto questo, e abbiamo quasi finito:

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

L'unica cosa da considerare ora è il segno dell'input. Vogliamo seguire le normali regole di moltiplicazione, quindi se uno e solo uno di A e B è negativo, l'output è negativo. Usiamo la funzione signche restituisce 1quando viene dato un numero positivo e -1quando viene dato un numero negativo, per produrre un coefficiente che moltiplichiamo il nostro intero calcolo per:

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

Infine, il tutto è racchiuso in una funzione anonima che accetta ae bcome input:

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

Rimuovere lo spazio bianco ed è 86 byte.


Sarebbe bello se tu potessi fornire una versione spiegata non golfata a beneficio di tutti.
anche il

Ho aggiornato il post con una spiegazione.
rturnbull,

Ottimo lavoro. Metodo molto intelligente usato.
anche il

1

Python 3 , 92 byte , 119 byte

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

Provalo online!

La correzione per la gestione di numeri negativi costava 29 byte: /


Bella risposta! Penso che puoi sostituire la lstripparte avvolgendo tutto all'interno int()e restituendo un numero.
ArBo

Hai ragione. Poi ho avuto la sensazione di mantenere un'interfaccia coerente. Prendere stringhe come argomenti anziché int, quindi restituire un int sembra strano per me;)
Speravo

Non mi preoccuperei troppo della coerenza nel code golf, ma dipende da te :). La mappatura di solito non è molto da golf in Python se dovessi fare un lambda in più per farlo.
ArBo

Questa funzione sembra non riuscire per gli ingressi negativi
ArBo

Hai ragione: / La correzione è piuttosto costosa, forse c'è più potenziale per giocare a golf.
movatica


0

PHP, 84 byte

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

leggermente più lungo con concatenazione di stringhe (86 byte):

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

0

Racchetta 325 byte

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

test:

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

Produzione:

3001424
0
0
1203021800
-1000420803

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

Provalo online!

Meno 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

0

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

@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

Provalo online!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.