การคูณซิป


20

บทนำ

ให้มีกำหนดดำเนินการเกี่ยวกับคณิตศาสตร์ใหม่ซึ่งผมเรียกคูณซิป หากต้องการซิปคูณจำนวนเต็มสองค่าที่ไม่ใช่ค่าลบคุณจะต้องเพิ่มศูนย์นำหน้าเพื่อทำการจับคู่ความยาวคูณตัวเลขฐาน 10 หลักที่สอดคล้องกันเพิ่มศูนย์นำหน้าไปยังผลลัพธ์เพื่อรับตัวเลข 2 หลักต่อกันและวางศูนย์นำหน้า

นี่คือตัวอย่างที่มีA = 1276และ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

การดำเนินการถูกขยายเป็นจำนวนเต็มทั้งหมดโดยมีกฎการลงชื่อปกติ: บวกครั้งเป็นลบเป็นลบ, ลบครั้งลบเป็นบวก

งาน

อินพุตของคุณเป็นจำนวนเต็มสองจำนวนและผลลัพธ์ของคุณคือการคูณซิปของพวกเขา คุณควรจะสามารถจัดการกับอินพุตขนาดใหญ่ได้ อินพุตและ / หรือเอาต์พุตสามารถอยู่ในรูปแบบสตริง (และแน่นอนว่าหากภาษาของคุณไม่รองรับจำนวนเต็มขนาดใหญ่โดยพลการ) โปรดทราบว่า-0ไม่ใช่อินพุตหรือเอาต์พุตที่ถูกต้อง

กฎและการให้คะแนน

คุณสามารถเขียนโปรแกรมเต็มรูปแบบหรือฟังก์ชั่นและนับไบต์ที่ต่ำที่สุดชนะ

กรณีทดสอบ

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

คำตอบ:


8

เจลลี่ , 11 10 ไบต์

ƓDUz0P€Uḅ³

ลองออนไลน์!

ฉันไม่สามารถทำได้ถึง 10 ไบต์ด้วยตัวเอง แต่ @ Pietu1998 ชี้ให้ฉันไปที่อะตอมที่ฉันพลาดไปการทำเช่นนี้ให้โซลูชันขนาด 10 ไบต์ ผิดปกติสำหรับเจลลี่อันนี้รับอินพุตจากอินพุตมาตรฐาน (ในรูปแบบ1276,933024) ไม่ใช่จากบรรทัดคำสั่ง (นี่เป็นการเปิดใช้งานการใช้³คำสั่งซึ่งจะส่งกลับอาร์กิวเมนต์บรรทัดคำสั่งเริ่มต้นที่ 100)

คำอธิบาย:

Ɠ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

การใช้ฐาน 100 เป็นวิธีที่ง่ายในการใช้เทคนิค "pad ถึง 2 หลักจากนั้นแปลงเป็นฐาน 10" สิ่งที่ลึกซึ้งอื่น ๆ ที่นี่คือการย้อนกลับ; เราต้องการปัดด้วยเลขศูนย์ที่จุดเริ่มต้นของตัวเลข แต่zแผ่นคำสั่งของวุ้นที่ท้ายดังนั้นการย้อนกลับรายการหมายความว่าzจะแผ่นอย่างถูกต้อง


3
คุณสามารถแทนที่b⁵ด้วยDเพื่อรับ 10 ไบต์ : P
PurkkaKoodari

4

Python 2, 99 ไบต์

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

ไบต์จำนวนมากมีไว้สำหรับการลงชื่อเข้าใช้ในกรณีที่อินพุตลบ ธn%dอยู่เสมอไม่ใช่เชิงลบถ้าdเป็นบวก1 ในความคิดของฉันนี้เป็นที่พึงปรารถนาโดยทั่วไป แต่ที่นี่ดูเหมือนไม่สะดวก: การลบสายเพื่อabsทำลายรหัสข้างต้น ในขณะเดียวกันpติดตาม "ค่าสถานที่" (คนหลายร้อย ฯลฯ ) และยังจดจำสัญญาณที่ต้องการของการส่งออก

รหัสนั้นมีความสมมาตรaและbยกเว้นในwhileเงื่อนไข: เราจะดำเนินต่อไปจนกระทั่งaเป็นศูนย์และยุติในเวลานั้น แน่นอนถ้าbเป็นศูนย์ก่อนจากนั้นเราจะสิ้นสุดการเพิ่มศูนย์ในขณะที่จนกว่าaจะเป็นศูนย์เช่นกัน


1ตัวอย่างเช่น(-33)%10ผลตอบแทน7และความฉลาดทางจำนวนเต็มของมี(-33)/10 เพราะนี่คือการที่ถูกต้อง-4 (-4)*10 + 7 = -33อย่างไรก็ตามผลิตภัณฑ์ซิป(-33)กับ33ต้องจบในมากกว่า3*3 = 097*3 = 21


3

JavaScript (ES6), 44 ไบต์

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

สะดวกนี้จะทำงานโดยอัตโนมัติสำหรับตัวเลขลบ


@ Jakube ฉันมักจะทำอย่างนั้นแม้ว่าอย่างน้อยฉันก็รวมf=จำนวนไบต์ นอกจากนี้ยัง|0เป็นเพราะฉันต้องการการหารจำนวนเต็มฉันไม่รู้ว่าคุณคิดว่าคุณจะได้รับคำตอบที่ถูกต้องได้อย่างไร
Neil

อ่านั่นสมเหตุสมผลแล้ว ตอนนี้ฉันยังได้รับคำตอบที่ผิดเมื่อนำออก|0ด้วย |0อาจจะกำหนดใหม่ของฟังก์ชั่นใหม่ที่จะฉไม่ได้ทำงานและฉันยังคงทดสอบรุ่นเก่าด้วย
Jakube

2

C, 77 ไบต์

-2 ไบต์สำหรับการลบเครื่องหมายวงเล็บซ้ำซ้อน ( *เป็นส่วนเชื่อมโยง)

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, ... ใช้สำหรับการแพ็ดดิง ตราบใดที่aหรือbไม่เป็นศูนย์ให้คูณตัวเลขสุดท้าย%10ด้วยtและสะสม จากนั้นทำการลบล้างตัวเลขสุดท้ายของaและb( /=10) และเลื่อนเป็นt2 หลัก ( *=100)

Ungolfed และการใช้งาน:

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

แนะนำfor(r=0;a|b;t*=100)r+=a%10*t*(b%10),a/=10,b/=10แทนr=0;while(a|b)r+=t*(a%10)*(b%10),a/=10,b/=10,t*=100
ceilingcat

1

อันที่จริง , 23 19 ไบต์

อินพุตถูกใช้เป็นสองสตริง เห็นได้ชัดว่าการพยายามแปลงจากฐาน 100 เช่นเดียวกับ ais523 ในคำตอบ Jelly ของพวกเขาไม่ได้ผลดีใน Actually จะช่วยให้ประหยัดได้ 9 ไบต์ด้วยหากทำงาน: / ยินดีต้อนรับคำแนะนำการเล่นกอล์ฟ! ลองออนไลน์!

แก้ไข: -4 ไบต์จากการเปลี่ยนวิธีสร้างผลลัพธ์เป็นตัวเลขใหม่

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 Bytes

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

Ungolfed:

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

โดยที่% หมายถึงผลผลิตก่อนหน้า

{{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 ไบต์

ไม่มีคำตอบที่ยาวที่สุดอีกต่อไป (ขอบคุณ, แร็กเก็ต) และในความเป็นจริงสั้นกว่าโซลูชัน Python (หายาก)! ฟังก์ชันที่ไม่ระบุตัวตนที่รับจำนวนเต็มสองจำนวนเป็นอินพุต

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

นี่คือวิธีการทำงาน

การคูณของซิปเกี่ยวข้องกับการแยกหมายเลขอินพุตเป็นตัวเลขที่เป็นส่วนประกอบเราใช้ค่าสัมบูรณ์ของตัวเลขและดำเนินการโมดูโลเพื่อลดพลังของ 10:

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

ดังนั้นที่นี่เรารับหมายเลขหนึ่งxและใช้โมดูโลกับอีก 99 หมายเลข ( 10^99ผ่าน10^1) R ทำซ้ำโดยปริยายx99 ครั้งส่งคืนเวกเตอร์ (รายการ) ด้วยองค์ประกอบ 99 รายการ ( x %% 10^99, x %% 10^98, x %% 10^97ฯลฯ )

เราใช้ผ่าน10^99 10^1การนำไปใช้ที่มีประสิทธิภาพมากขึ้นจะใช้ค่าจำนวนหลักในจำนวนที่ยาวที่สุด (ตรวจสอบประวัติการแก้ไขของโพสต์นี้เวอร์ชันก่อนหน้านี้ทำสิ่งนี้) แต่ใช้เพียง99..1จำนวนไบต์ที่น้อยลง

สำหรับx = 1276สิ่งนี้ทำให้เรา

1276 1276 1276 ... 1276 276 76 6

ต่อไปเราใช้การหารด้วยจำนวนเต็มโดยลดหลั่นอำนาจ 10 เพื่อปัดเศษตัวเลข:

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

อัตราผลตอบแทนนี้

0 0 0 ... 1 2 7 6

ซึ่งเป็นตัวแทนที่เราต้องการ ในรหัสเราท้ายต้องการที่จะใช้10^(98:0)อีกครั้งในภายหลังดังนั้นเราจึงกำหนดให้ตัวแปร:

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

(การห่อนิพจน์ในวงเล็บใน R โดยทั่วไปประเมินนิพจน์ (ในกรณีนี้การกำหนดค่าของ10^(98:0)ถึงe) แล้วส่งกลับผลลัพธ์ของนิพจน์ทำให้เราสามารถฝังการกำหนดตัวแปรภายในการคำนวณอื่น ๆ ได้)

ต่อไปเราจะทำการคูณตัวเลขในอินพุต จากนั้นเอาต์พุตจะถูกเพิ่มเป็นสองหลักและต่อกัน การขยายไปยังสองหลักและการต่อเชื่อมนั้นเทียบเท่ากับการคูณแต่ละตัวเลขโดย10^nที่nระยะทางจากขอบด้านขวาจากนั้นรวมตัวเลขทั้งหมด

 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

โดยเฉพาะอย่างยิ่งเพราะการคูณคือการสลับที่เราสามารถดำเนินการคูณโดย10^n ก่อนที่เราคูณโดยB ดังนั้นเราทำการคำนวณก่อนหน้าของเราและคูณด้วย:10^(98:0)

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

ซึ่งเทียบเท่ากับ

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

หลังจากใช้นี้เพื่อเราก็อยากที่จะทำซ้ำนี้การดำเนินการทั้งหมดในB แต่นั่นต้องใช้ไบต์ที่มีค่าดังนั้นเราจึงกำหนดฟังก์ชั่นดังนั้นเราจึงต้องเขียนเพียงครั้งเดียว:

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

เราใช้เคล็ดลับการฝังในวงเล็บเพื่อให้เราสามารถกำหนดและใช้ฟังก์ชั่นในเวลาเดียวกันเพื่อเรียกใช้ฟังก์ชั่นนี้กับAและBและคูณพวกมันเข้าด้วยกัน (เราอาจกำหนดไว้ในบรรทัดที่แยกต่างหาก แต่เพราะในที่สุดเราจะใส่สิ่งนี้ลงในฟังก์ชั่นนิรนามหากเรามีโค้ดมากกว่าหนึ่งบรรทัดดังนั้นทุกอย่างต้องถูกห่อด้วยเครื่องหมายปีกกาซึ่งมีค่า ไบต์.)

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

และเรานำผลรวมทั้งหมดนี้มาใช้จนเกือบเสร็จแล้ว:

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

สิ่งเดียวที่ต้องพิจารณาตอนนี้คือสัญลักษณ์ของอินพุต เราต้องการที่จะปฏิบัติตามกฎการคูณปกติดังนั้นหากหนึ่งและเพียงหนึ่งเดียวของAและBเป็นลบออกเป็นลบ เราใช้ฟังก์ชั่นsignที่ส่งกลับ1เมื่อได้รับจำนวนบวกและ-1เมื่อได้รับจำนวนลบเพื่อส่งออกสัมประสิทธิ์ที่เราคูณการคำนวณทั้งหมดของเราโดย:

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

ในที่สุดสิ่งทั้งหมดจะถูกรวมไว้ในฟังก์ชั่นที่ไม่ระบุชื่อที่ใช้aและbเป็นข้อมูลเข้า:

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

ลบช่องว่างออกและมีขนาด 86 ไบต์


มันจะดีมากถ้าคุณสามารถจัดเตรียมเวอร์ชั่นที่ไม่ได้อธิบายและเป็นประโยชน์สำหรับทุกคน
rnso

ฉันได้อัปเดตโพสต์พร้อมคำอธิบายแล้ว
rturnbull

เยี่ยมมาก ใช้วิธีการที่ฉลาดมาก
rnso

1

Python 3 , 92 ไบต์ , 119 ไบต์

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

ลองออนไลน์!

แก้ไขสำหรับการจัดการตัวเลขติดลบราคา 29 ไบต์: /


คำตอบที่ดี! ฉันคิดว่าคุณสามารถแทนที่lstripส่วนได้โดยห่อทุกอย่างไว้ด้านในint()และส่งคืนตัวเลข
ArBo

คุณถูก. จากนั้นฉันก็รู้สึกอยากจะรักษาอินเตอร์เฟซที่สอดคล้องกัน การรับสตริงเป็นอาร์กิวเมนต์แทนที่จะเป็น int จากนั้นส่งคืน int ให้ดูแปลกสำหรับฉัน;) ฉันหวังว่าจะเปลี่ยน zip + สำหรับลูปสำหรับการเรียกใช้แผนที่ แต่นั่นก็ไม่ได้ผล: /
movatica

ฉันจะไม่กังวลมากเกินไปเกี่ยวกับความมั่นคงในการเขียนโค้ด แต่ขึ้นอยู่กับคุณ :) การทำแผนที่มักจะไม่ค่อยเล่นกอล์ฟใน Python ถ้าคุณต้องการสร้างแลมบ์ดาเสริมให้ทำ
ArBo

ฟังก์ชั่นนี้ดูเหมือนจะล้มเหลวสำหรับอินพุตลบ
ArBo

คุณพูดถูก: / การแก้ไขค่อนข้างแพงอาจจะมีโอกาสมากขึ้นที่จะตีมันลง
movatica


0

PHP, 84 ไบต์

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

อีกต่อไปเล็กน้อยกับการต่อสตริง (86 ไบต์):

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

0

แร็กเก็ต 325 ไบต์

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

การทดสอบ:

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

เอาท์พุท:

3001424
0
0
1203021800
-1000420803

0

PowerShell , 153 151 ไบต์

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

ลองออนไลน์!

หักกอล์ฟ:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.