Nhân dây kéo


20

Giới thiệu

Chúng ta hãy xác định một hoạt động số học mới, mà tôi gọi là phép nhân dây kéo . Để khóa kéo nhân hai số nguyên không âm, bạn thêm các số 0 đứng đầu để làm cho độ dài khớp với nhau, nhân các chữ số cơ bản tương ứng của 10 số, thêm các số 0 đứng đầu vào kết quả để có được các số có 2 chữ số, nối chúng và cuối cùng thả các số 0 đứng đầu.

Đây là một ví dụ với A = 1276B = 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

Hoạt động được mở rộng cho tất cả các số nguyên với các quy tắc ký hiệu thông thường: lần dương dương là âm, lần âm âm là dương và cứ thế.

Nhiệm vụ

Đầu vào của bạn là hai số nguyên và đầu ra của bạn là phép nhân dây kéo của chúng. Bạn sẽ có thể xử lý các đầu vào lớn tùy ý. Đầu vào và / hoặc đầu ra có thể ở định dạng chuỗi (và thực tế phải là, nếu ngôn ngữ của bạn không hỗ trợ các số nguyên lớn tùy ý). Lưu ý rằng đó -0không phải là một đầu vào hoặc đầu ra hợp lệ.

Quy tắc và tính điểm

Bạn có thể viết một chương trình đầy đủ hoặc một hàm và số byte thấp nhất sẽ thắng.

Các trường hợp thử nghiệm

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

Câu trả lời:


8

Thạch , 11 10 byte

ƓDUz0P€Uḅ³

Hãy thử trực tuyến!

Tôi không thể tự mình giảm xuống còn 10 byte, nhưng @ Pietu1998 đã chỉ cho tôi một nguyên tử mà tôi đã bỏ lỡ, điều này mang lại giải pháp 10 byte này. Bất thường đối với Jelly, cái này lấy đầu vào từ đầu vào tiêu chuẩn (ở dạng 1276,933024), không phải từ dòng lệnh (điều này cho phép sử dụng ³lệnh, trả về đối số dòng lệnh, mặc định là 100).

Giải trình:

Ɠ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

Việc sử dụng cơ sở 100 là một cách đơn giản để thực hiện kỹ thuật "pad thành 2 chữ số, sau đó chuyển đổi sang cơ sở 10". Điều duy nhất tinh tế khác ở đây là sự đảo ngược; chúng tôi muốn đệm với số 0 ở đầu số, nhưng phần zđệm lệnh của Jelly ở cuối, vì vậy đảo ngược danh sách có nghĩa là zsẽ đệm chính xác.


3
Bạn có thể thay thế b⁵bằng Dđể có được 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

Có rất nhiều byte ở đó để tính đến dấu hiệu trong trường hợp đầu vào âm. Trong Python, n%dluôn luôn không âm nếu dlà dương 1 . Theo tôi điều này nói chung là mong muốn, nhưng ở đây có vẻ bất tiện: loại bỏ các cuộc gọi abssẽ phá vỡ mã trên. Trong khi đó ptheo dõi "giá trị địa điểm" (những cái, hàng trăm, v.v.) và cũng nhớ dấu hiệu mong muốn của đầu ra.

Mã về cơ bản là đối xứng trong abngoại trừ trong whileđiều kiện: chúng ta tiếp tục cho đến khi abằng 0 và chấm dứt tại thời điểm đó. Tất nhiên, nếu bbằng 0 trước, thì cuối cùng chúng ta sẽ thêm số không cho đến khi abằng không.


1 Ví dụ: (-33)%10trả về 7và thương số nguyên (-33)/10-4. Điều này đúng bởi vì (-4)*10 + 7 = -33. Tuy nhiên, sản phẩm dây kéo của (-33)với 33phải kết thúc bằng 3*3 = 09hơn 7*3 = 21.


3

JavaScript (ES6), 44 byte

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

Thuận tiện điều này tự động làm việc cho số âm.


@Jakube Tôi luôn luôn làm điều đó, mặc dù ít nhất tôi đã bao gồm f=số byte. Ngoài ra, |0vì tôi cần phân chia số nguyên, tôi không biết bạn nghĩ bạn đang trả lời đúng như thế nào nếu không có nó.
Neil

Ah, điều đó có ý nghĩa. Bây giờ tôi cũng nhận được câu trả lời sai khi gỡ bỏ |0. Có thể việc gán lại chức năng mới cho f không hoạt động và tôi vẫn thử nghiệm phiên bản cũ với |0.
Jakube

2

C, 77 byte

-2 byte để loại bỏ niềng răng dự phòng ( *là kết hợp).

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.100, ... được sử dụng để đệm. Chừng nào ahoặc bkhông bằng 0, hãy nhân số cuối cùng %10với tvà tích lũy. Sau đó xóa chữ số cuối cùng của ab( /=10) và dịch chuyển t2 chữ số ( *=100).

Ungolfed và cách sử dụng:

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

Gợi ý for(r=0;a|b;t*=100)r+=a%10*t*(b%10),a/=10,b/=10thay vìr=0;while(a|b)r+=t*(a%10)*(b%10),a/=10,b/=10,t*=100
trần mèo

1

Trên thực tế , 23 19 byte

Đầu vào được lấy dưới dạng hai chuỗi. Ngoài ra, rõ ràng là cố gắng chuyển đổi từ cơ sở 100, như ais523 thực hiện trong câu trả lời Jelly của họ, thực tế không hoạt động tốt như vậy. Cũng sẽ lưu được 9 byte nếu nó hoạt động: / Đề nghị chơi gôn chào mừng! Hãy thử trực tuyến!

Chỉnh sửa: -4 byte từ việc thay đổi cách kết quả được tạo thành một số mới.

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

Toán học 66 byte

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

Ung dung:

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

Trong đó% có nghĩa là sản lượng đầu ra trước đó

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

Không còn là câu trả lời dài nhất (cảm ơn, Vợt), và trên thực tế ngắn hơn giải pháp Python (một điều trị hiếm gặp)! Một hàm ẩn danh có hai số nguyên làm đầu vào.

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

Đây là cách nó hoạt động.

Phép nhân dây kéo liên quan đến việc chia các số đầu vào thành các chữ số cấu thành của chúng. Chúng tôi lấy giá trị tuyệt đối của số và thực hiện modulo để giảm dần 10:

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

Vì vậy, ở đây chúng tôi lấy một số xvà áp dụng modulo với 99 số khác ( 10^99thông qua 10^1). R ngầm lặp lại x99 lần, trả về một vectơ (danh sách) với 99 phần tử. (x %% 10^99 , x %% 10^98, x %% 10^97, Vv)

Chúng tôi sử dụng 10^99 thông qua 10^1. Việc triển khai hiệu quả hơn sẽ sử dụng giá trị số chữ số trong số dài nhất (kiểm tra lịch sử chỉnh sửa của bài đăng này; các phiên bản trước đã làm điều này), nhưng chỉ cần 99..1sử dụng ít byte hơn.

x = 1276điều này cho chúng ta

1276 1276 1276 ... 1276 276 76 6

Tiếp theo, chúng tôi sử dụng phép chia số nguyên bằng cách giảm 10 lũy thừa để làm tròn các số:

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

Sản lượng này

0 0 0 ... 1 2 7 6

đó chính xác là đại diện mà chúng ta muốn. Trong mã, cuối cùng chúng tôi muốn sử dụng 10^(98:0)lại, vì vậy chúng tôi gán nó cho một biến:

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

(Bao bì một biểu thức trong ngoặc đơn trong R thường đánh giá biểu thức (trong trường hợp này, gán giá trị của 10^(98:0)để e), và sau đó cũng trả về kết quả của biểu thức, cho phép chúng tôi tập biến nhúng trong tính toán khác.)

Tiếp theo, chúng tôi thực hiện phép nhân cặp số của các chữ số trong đầu vào. Đầu ra sau đó được đệm thành hai chữ số và nối. Việc đệm thành hai chữ số và ghép nối tương đương với nhân mỗi số với 10^n, trong đón là khoảng cách từ cạnh phải, và sau đó tổng hợp tất cả các số.

 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

Đáng chú ý, bởi vì nhân là giao hoán, chúng ta có thể thực hiện các phép nhân bởi 10^n trước khi chúng tôi nhân Một bằng B . Vì vậy, chúng tôi thực hiện tính toán trước đó của chúng tôi và nhân với 10^(98:0):

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

tương đương với

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

Sau khi áp dụng này để Một , sau đó chúng tôi sẽ muốn lặp lại toàn bộ thao tác này trên B . Nhưng điều đó cần các byte quý giá, vì vậy chúng tôi xác định một hàm vì vậy chúng tôi chỉ phải viết nó một lần:

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

Chúng tôi thực hiện thủ thuật nhúng dấu ngoặc đơn để cho phép chúng tôi xác định và áp dụng một hàm cùng một lúc, để gọi hàm này trên AB và nhân chúng với nhau. (Chúng ta có thể đã định nghĩa nó trên một dòng riêng biệt, nhưng vì cuối cùng chúng ta sẽ đưa tất cả những thứ này vào một hàm ẩn danh, nếu chúng ta có nhiều hơn một dòng mã thì mọi thứ cần phải được bọc trong các dấu ngoặc nhọn, có giá trị byte.)

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

Và chúng tôi lấy tổng của tất cả những điều này, và chúng tôi sắp hoàn thành:

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

Điều duy nhất cần xem xét bây giờ là dấu hiệu của đầu vào. Chúng tôi muốn tuân theo các quy tắc nhân thông thường, vì vậy nếu một và chỉ một trong AB là âm, thì đầu ra là âm. Chúng tôi sử dụng hàm signtrả về 1khi được cho một số dương và -1khi được cho một số âm, để đưa ra một hệ số mà chúng tôi nhân toàn bộ phép tính của chúng tôi bằng cách:

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

Cuối cùng, toàn bộ điều được gói vào một hàm ẩn danh nhận ablàm đầu vào:

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

Xóa khoảng trắng và nó là 86 byte.


Sẽ thật tuyệt nếu bạn có thể cung cấp một phiên bản không được giải thích, vì lợi ích của mọi người.
rnso

Tôi đã cập nhật bài viết với một lời giải thích.
rturnbull

Lam tôt lăm. Phương pháp rất thông minh được sử dụng.
rnso

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

Hãy thử trực tuyến!

Khắc phục để xử lý số âm có giá 29 byte: /


Câu trả lời tốt đẹp! Tôi nghĩ bạn có thể thay thế lstripmột phần bằng cách gói mọi thứ bên trong int()và trả lại một số.
ArBo

Bạn đúng. Sau đó, tôi cảm thấy như giữ một giao diện nhất quán. Lấy các chuỗi làm đối số thay vì int, sau đó trả về một int có vẻ kỳ lạ đối với tôi;) Tôi hy vọng sẽ thay đổi zip + cho vòng lặp cho một cuộc gọi bản đồ, nhưng điều đó sẽ không hoạt động: /
Movatica

Tôi sẽ không lo lắng quá nhiều về tính nhất quán trong môn đánh gôn, nhưng điều đó tùy thuộc vào bạn :). Ánh xạ thường không quá phức tạp trong Python nếu bạn cần tạo thêm lambda để làm điều đó.
ArBo

Chức năng này dường như không thành công cho các đầu vào tiêu cực
ArBo

Bạn nói đúng: / Cách khắc phục khá tốn kém, có thể có nhiều tiềm năng hơn để chơi 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;

dài hơn một chút với nối chuỗi (86 byte):

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

0

Vợt 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)))

Ung dung:

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

Kiểm tra:

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

Đầu ra:

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

Hãy thử trực tuyến!

Ít chơi gôn hơn:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.