Ước chung lớn nhất


40

Nhiệm vụ của bạn là tính toán ước số chung lớn nhất (GCD) của hai số nguyên đã cho trong càng ít byte mã càng tốt.

Bạn có thể viết chương trình hoặc hàm, lấy đầu vào và trả về đầu ra thông qua bất kỳ phương thức tiêu chuẩn nào được chấp nhận của chúng tôi (bao gồm STDIN / STDOUT, tham số hàm / giá trị trả về, đối số dòng lệnh, v.v.).

Đầu vào sẽ là hai số nguyên không âm. Bạn sẽ có thể xử lý toàn bộ phạm vi được hỗ trợ bởi loại số nguyên mặc định của ngôn ngữ hoặc phạm vi [0,255], tùy theo giá trị nào lớn hơn. Bạn được đảm bảo rằng ít nhất một trong những đầu vào sẽ khác không.

Bạn không được phép sử dụng các phần tử tích hợp tính toán GCD hoặc LCM (bội số chung nhỏ nhất).

Luật tiêu chuẩn được áp dụng.

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

0 2     => 2
6 0     => 6
30 42   => 6
15 14   => 1
7 7     => 7
69 25   => 1
21 12   => 3
169 123 => 1
20 142  => 2
101 202 => 101

1
Nếu chúng ta cho phép asm có đầu vào trong bất kỳ thanh ghi nào thuận tiện và kết quả là bất kỳ reg nào đều thuận tiện, chúng ta chắc chắn nên cho phép các hàm hoặc thậm chí các đoạn mã (chỉ là phần thân hàm). Làm cho câu trả lời của tôi trở thành một hàm hoàn chỉnh sẽ thêm khoảng 4B với quy ước gọi đăng ký như vectơ 32 bit của MS (một xchg eax, một Mov và ret) hoặc nhiều hơn với quy ước gọi stack.
Peter Cordes

@PeterCordes Xin lỗi, tôi nên đã được cụ thể hơn. Bạn hoàn toàn có thể chỉ cần viết mã gấu cần thiết nhưng nếu bạn thật tử tế khi đưa vào một cách để chạy mã đã nói thì sẽ rất tuyệt.
Mike Shlanta

Vì vậy, chỉ đếm mã gcd, nhưng cung cấp mã xung quanh để mọi người có thể xác minh / thử nghiệm / cải thiện? BTW, các trường hợp thử nghiệm của bạn bằng 0 là một trong hai đầu vào phá vỡ các câu trả lời mã máy x86 của chúng tôi. div bằng không làm tăng ngoại lệ phần cứng. Trên Linux, quy trình của bạn được a SIGFPE.
Peter Cordes

3
@CodesInChaos Giới hạn bộ nhớ và thời gian thường bị bỏ qua miễn là bản thân thuật toán có thể xử lý tất cả các đầu vào. Quy tắc này chỉ nhằm tránh mọi người mã hóa các giới hạn tùy ý cho các vòng lặp giới hạn thuật toán một cách giả tạo trong phạm vi đầu vào nhỏ hơn. Tôi không thấy làm thế nào bất biến đi vào điều này?
Martin Ender

1
gcd (0, n) không phải là lỗi n
RosLuP

Câu trả lời:


37

Võng mạc , 16

^(.+)\1* \1+$
$1

Điều này hoàn toàn không sử dụng thuật toán của Euclid - thay vào đó, nó tìm thấy GCD bằng cách sử dụng các nhóm khớp regex.

Hãy thử trực tuyến. - Ví dụ này tính GCD (8,12).

Nhập dưới dạng 2 số nguyên cách nhau. Lưu ý rằng I / O là đơn nhất. Nếu điều đó không được chấp nhận, thì chúng ta có thể làm điều này:

Võng mạc, 30

\d+
$*
^(.+)\1* \1+$
$1
1+
$.&

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

Như @ MartinBüttner chỉ ra, điều này sụp đổ với số lượng lớn (nói chung là trường hợp cho bất cứ điều gì đơn phương). Tối thiểu, một đầu vào của INT_MAX sẽ yêu cầu phân bổ chuỗi 2GB.


2
Tôi muốn bình chọn cho điều này nhiều hơn
MickyT

Nên ổn với phạm vi số bây giờ. Tôi đã thay đổi thông số kỹ thuật (với sự cho phép của OP) để chỉ yêu cầu phạm vi số tự nhiên của ngôn ngữ (hoặc [0,255] nếu đó là nhiều hơn). Tuy nhiên, bạn sẽ phải hỗ trợ các số 0, mặc dù tôi nghĩ việc thay đổi +s thành *s nên làm. Và bạn có thể rút ngắn đáng kể giai đoạn cuối của mã dài bằng cách giảm nó xuống 1.
Martin Ender

2
Để tham khảo trong tương lai, tôi chỉ tìm thấy một giải pháp 16 byte thay thế hoạt động cho số lượng đầu vào tùy ý (bao gồm một) để nó có thể hữu ích hơn trong các bối cảnh khác: retina.tryitonline.net/ trộm
Martin Ender

1
Chỉ cần lưu ý rằng cả giải pháp của bạn và giải pháp của tôi ở trên đều không cần ^, bởi vì trận đấu không thể thất bại từ vị trí bắt đầu.
Martin Ender

28

Mã máy i386 (x86-32), 8 byte (9B đối với dấu không dấu)

+ 1B nếu chúng ta cần xử lý b = 0đầu vào.

mã máy amd64 (x86-64), 9 byte (10B cho dấu không dấu hoặc 14B 13B cho số nguyên 64b được ký hoặc không dấu)

10 9B đối với dấu không dấu trên amd64, ngắt với đầu vào = 0


Đầu vào là các số nguyên có chữ ký 32 bit khác không eaxecx. Đầu ra trong eax.

## 32bit code, signed integers:  eax, ecx
08048420 <gcd0>:
 8048420:       99                      cdq               ; shorter than xor edx,edx
 8048421:       f7 f9                   idiv   ecx
 8048423:       92                      xchg   edx,eax    ; there's a one-byte encoding for xchg eax,r32.  So this is shorter but slower than a mov
 8048424:       91                      xchg   ecx,eax    ; eax = divisor(from ecx), ecx = remainder(from edx), edx = quotient(from eax) which we discard
    ; loop entry point if we need to handle ecx = 0
 8048425:       41                      inc    ecx        ; saves 1B vs. test/jnz in 32bit mode
 8048426:       e2 f8                   loop   8048420 <gcd0>
08048428 <gcd0_end>:
 ; 8B total
 ; result in eax: gcd(a,0) = a

Cấu trúc vòng lặp này không thành công trong trường hợp thử nghiệm ecx = 0. ( divgây ra sự thực thi #DEphần cứng khi chia cho số 0. (Trên Linux, kernel cung cấp một SIGFPE(ngoại lệ dấu phẩy động)). Nếu điểm vào vòng lặp ở ngay trước inc, chúng tôi sẽ tránh được vấn đề. Phiên bản x86-64 có thể xử lý nó miễn phí, xem bên dưới.

Câu trả lời của Mike Shlanta là điểm khởi đầu cho việc này . Vòng lặp của tôi thực hiện tương tự như vòng lặp của anh ấy, nhưng đối với các số nguyên đã ký vì cdqmột vòng lặp ngắn hơn xor edx,edx. Và có, nó hoạt động chính xác với một hoặc cả hai đầu vào âm. Phiên bản của Mike sẽ chạy nhanh hơn và chiếm ít không gian hơn trong bộ đệm uop ( xchglà 3 uops trên CPU Intel và looprất chậm trên hầu hết các CPU ), nhưng phiên bản này chiến thắng ở kích thước mã máy.

Lúc đầu tôi không để ý rằng câu hỏi yêu cầu 32 bit không dấu . Quay trở lại xor edx,edxthay vì cdqsẽ tốn một byte. divcó cùng kích thước idivvà mọi thứ khác có thể giữ nguyên ( xchgđể di chuyển dữ liệu và inc/loopvẫn hoạt động.)

Điều thú vị là, đối với kích thước toán hạng 64 bit ( raxrcx), các phiên bản đã ký và không dấu có cùng kích thước. Phiên bản đã ký cần tiền tố REX cho cqo(2B), nhưng phiên bản chưa ký vẫn có thể sử dụng 2B xor edx,edx.

Trong mã 64 bit, inc ecxlà 2B: byte đơn inc r32dec r32opcodes được tái sử dụng làm tiền tố REX. inc/loopkhông lưu bất kỳ kích thước mã nào trong chế độ 64 bit, vì vậy bạn cũng có thể test/jnz. Hoạt động trên số nguyên 64 bit thêm một byte cho mỗi lệnh trong tiền tố REX, ngoại trừ loophoặc jnz. Phần còn lại có thể có tất cả các số 0 ở mức thấp 32b (ví dụ gcd((2^32), (2^32 + 1))), vì vậy chúng tôi cần kiểm tra toàn bộ RCx và không thể lưu một byte bằng test ecx,ecx. Tuy nhiên, tốc độ chậm hơn jrcxzchỉ là 2B và chúng ta có thể đặt nó ở đầu vòng lặp để xử lý ecx=0mục nhập :

## 64bit code, unsigned 64 integers:  rax, rcx
0000000000400630 <gcd_u64>:
  400630:       e3 0b                   jrcxz  40063d <gcd_u64_end>   ; handles rcx=0 on input, and smaller than test rcx,rcx/jnz
  400632:       31 d2                   xor    edx,edx                ; same length as cqo
  400634:       48 f7 f1                div    rcx                      ; REX prefixes needed on three insns
  400637:       48 92                   xchg   rdx,rax
  400639:       48 91                   xchg   rcx,rax
  40063b:       eb f3                   jmp    400630 <gcd_u64>
000000000040063d <gcd_u64_end>:
## 0xD = 13 bytes of code
## result in rax: gcd(a,0) = a

Chương trình thử nghiệm đầy đủ có thể chạy bao gồm cả mainchạy printf("...", gcd(atoi(argv[1]), atoi(argv[2])) ); nguồn và đầu ra asm trên Godbolt Compiler Explorer , cho các phiên bản 32 và 64b. Đã thử nghiệm và làm việc cho 32bit ( -m32), 64bit ( -m64) và x32 ABI ( -mx32) .

Cũng bao gồm: một phiên bản chỉ sử dụng phép trừ lặp đi lặp lại , là 9B cho dấu không dấu, ngay cả đối với chế độ x86-64 và có thể lấy một trong các đầu vào của nó trong một thanh ghi tùy ý. Tuy nhiên, nó không thể xử lý đầu vào là 0 trên mục nhập (nó phát hiện khi subtạo ra số 0, mà x - 0 không bao giờ thực hiện).

GNU C nguồn asm nội tuyến cho phiên bản 32 bit (biên dịch với gcc -m32 -masm=intel)

int gcd(int a, int b) {
    asm (// ".intel_syntax noprefix\n"
        // "jmp  .Lentry%=\n" // Uncomment to handle div-by-zero, by entering the loop in the middle.  Better: `jecxz / jmp` loop structure like the 64b version
        ".p2align 4\n"                  // align to make size-counting easier
         "gcd0:   cdq\n\t"              // sign extend eax into edx:eax.  One byte shorter than xor edx,edx
         "        idiv    ecx\n"
         "        xchg    eax, edx\n"   // there's a one-byte encoding for xchg eax,r32.  So this is shorter but slower than a mov
         "        xchg    eax, ecx\n"   // eax = divisor(ecx), ecx = remainder(edx), edx = garbage that we will clear later
         ".Lentry%=:\n"
         "        inc     ecx\n"        // saves 1B vs. test/jnz in 32bit mode, none in 64b mode
         "        loop    gcd0\n"
        "gcd0_end:\n"
         : /* outputs */  "+a" (a), "+c"(b)
         : /* inputs */   // given as read-write outputs
         : /* clobbers */ "edx"
        );
    return a;
}

Thông thường tôi sẽ viết toàn bộ một hàm bằng asm, nhưng mã asm GNU C dường như là cách tốt nhất để bao gồm một đoạn mã có thể có / đầu ra trong bất kỳ chế độ nào chúng ta chọn. Như bạn có thể thấy, cú pháp asm nội tuyến của GNU C làm cho asm trở nên xấu xí và ồn ào. Đó cũng là một cách thực sự khó khăn để học asm .

Nó thực sự sẽ biên dịch và hoạt động trong .att_syntax noprefixchế độ, bởi vì tất cả các insns được sử dụng là đơn / không có toán hạng hoặc xchg. Không thực sự là một quan sát hữu ích.


2
@MikeShlanta: Cảm ơn. Nếu bạn thích tối ưu hóa asm, hãy xem một số câu trả lời của tôi trên stackoverflow. :)
Peter Cordes

2
@MikeShlanta: Tôi đã tìm thấy một cách sử dụng cho jrcxztất cả trong phiên bản uint64_t :). Ngoài ra, không nhận thấy rằng bạn đã chỉ định không dấu, vì vậy tôi cũng bao gồm số byte cho điều đó.
Peter Cordes

Tại sao bạn không thể sử dụng jecxztrong phiên bản 32 bit cho cùng một hiệu ứng?
Cody Grey

1
@CodyGray: inc/looplà 3 byte trong phiên bản 32 bit, nhưng 4B ở phiên bản 64 bit. Điều đó có nghĩa là chỉ trong phiên bản 64 bit, nó không tốn thêm byte để sử dụng jrcxzjmpthay vào đó inc / loop.
Peter Cordes

Bạn không thể chỉ vào giữa như là mục?
l4m2

14

Lục giác , 17 byte

?'?>}!@<\=%)>{\.(

Mở ra:

  ? ' ?
 > } ! @
< \ = % )
 > { \ .
  ( . .

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

Lắp nó vào chiều dài 3 bên là một làn gió. Việc tắt hai byte cuối cùng không phải là ... Tôi cũng không tin nó là tối ưu, nhưng tôi chắc rằng tôi nghĩ nó gần.

Giải trình

Một triển khai thuật toán Euclide khác.

Chương trình sử dụng ba cạnh bộ nhớ, mà tôi sẽ gọi A , BC , với con trỏ bộ nhớ (MP) bắt đầu như được hiển thị:

nhập mô tả hình ảnh ở đây

Dưới đây là sơ đồ dòng điều khiển:

nhập mô tả hình ảnh ở đây

Luồng điều khiển bắt đầu trên đường dẫn màu xám với một bit tuyến tính ngắn cho đầu vào:

?    Read first integer into memory edge A.
'    Move MP backwards onto edge B.
?    Read second integer into B.

Lưu ý rằng mã bây giờ bao quanh các cạnh đến <góc bên trái. Điều này <hoạt động như một chi nhánh. Nếu cạnh hiện tại bằng 0 (tức là thuật toán Euclide chấm dứt), IP bị lệch về bên trái và đi theo đường dẫn màu đỏ. Mặt khác, một phép lặp của thuật toán Euclide được tính trên đường dẫn màu xanh lá cây.

Trước tiên chúng ta sẽ xem xét con đường xanh. Lưu ý rằng >\tất cả hoạt động như các gương đơn giản làm lệch hướng con trỏ lệnh. Cũng lưu ý rằng luồng điều khiển quấn quanh các cạnh ba lần, một lần từ dưới lên trên, một lần từ góc phải đến hàng dưới cùng và cuối cùng từ góc dưới bên phải sang góc trái để kiểm tra lại điều kiện. Cũng lưu ý rằng .không có op-op.

Điều đó để lại mã tuyến tính sau cho một lần lặp duy nhất:

{    Move MP forward onto edge C.
'}   Move to A and back to C. Taken together this is a no-op.
=    Reverse the direction of the MP so that it now points at A and B. 
%    Compute A % B and store it in C.
)(   Increment, decrement. Taken together this is a no-op, but it's
     necessary to ensure that IP wraps to the bottom row instead of
     the top row.

Bây giờ chúng tôi trở lại nơi chúng tôi bắt đầu, ngoại trừ ba cạnh đã thay đổi vai trò theo chu kỳ ( C ban đầu giờ đây đóng vai trò của BB ban đầu là vai trò của A ...). Trong thực tế, chúng tôi đã sắp xếp lại các đầu vào ABvới B, và A % B, tương ứng.

Một khi A % B(trên cạnh C ) là số không, GCD có thể được tìm thấy trên mép B . Một lần nữa, >chỉ làm chệch hướng IP, vì vậy trên đường dẫn màu đỏ, chúng tôi thực hiện:

}    Move MP to edge B.
!    Print its value as an integer.
@    Terminate the program.

9

Mã máy x86 32 bit nhỏ, 14 byte, 14 byte

Được tạo bằng nasm -f bin

d231 f3f7 d889 d389 db85 f475

    gcd0:   xor     edx,edx
            div     ebx
            mov     eax,ebx
            mov     ebx,edx
            test    ebx,ebx
            jnz     gcd0

4
Tôi đã giảm xuống còn 8 byte bằng cách sử dụng cdqvà ký tên idiv, và một byte xchg eax, r32thay vì mov. Đối với mã 32 bit: inc/loopthay vì test/jnz(tôi không thể thấy cách sử dụng jecxzvà không có jecxnz). Tôi đã đăng phiên bản cuối cùng của mình dưới dạng một câu trả lời mới vì tôi nghĩ những thay đổi này đủ lớn để biện minh cho nó.
Peter Cordes

9

T-SQL, 153 169 byte

Ai đó đề cập đến ngôn ngữ tồi tệ nhất cho golf?

CREATE FUNCTION G(@ INT,@B INT)RETURNS TABLE RETURN WITH R AS(SELECT 1D,0R UNION ALL SELECT D+1,@%(D+1)+@B%(D+1)FROM R WHERE D<@ and D<@b)SELECT MAX(D)D FROM R WHERE 0=R

Tạo một hàm có giá trị bảng sử dụng truy vấn đệ quy để tìm ra các ước số chung. Sau đó, nó trả về mức tối đa . Bây giờ sử dụng thuật toán euclide để xác định GCD xuất phát từ câu trả lời của tôi ở đây .

Ví dụ sử dụng

SELECT * 
FROM (VALUES
        (15,45),
        (45,15),
        (99,7),
        (4,38)
    ) TestSet(A, B)
    CROSS APPLY (SELECT * FROM G(A,B))GCD

A           B           D
----------- ----------- -----------
15          45          15
45          15          15
99          7           1
4           38          2

(4 row(s) affected)

1
Chúa Giêsu đó là dài dòng.
Cyoce

9

Thạch, 7 byte

ṛß%ðḷṛ?

Thực hiện đệ quy của thuật toán Euclide. Hãy thử trực tuyến!

Nếu không được tích hợp sẵn, g(1 byte, GCD tích hợp) sẽ đạt được điểm cao hơn.

Làm thế nào nó hoạt động

ṛß%ðḷṛ?  Main link. Arguments: a, b

   ð     Convert the chain to the left into a link; start a new, dyadic chain.
 ß       Recursively call the main link...
ṛ %        with b and a % b as arguments.
     ṛ?  If the right argument (b) is non-zero, execute the link.
    ḷ    Else, yield the left argument (a).

Điều đó gần như cảm thấy như gian lận haha, tôi có thể phải xác định rằng câu trả lời không thể sử dụng butlins ...
Mike Shlanta

13
Nếu bạn quyết định làm như vậy, bạn nên làm điều đó một cách nhanh chóng. Nó hiện sẽ vô hiệu ba trong số các câu trả lời.
Dennis

Lưu ý rằng độ dài được chỉ định của anh ta tính bằng byte - các ký tự đó chủ yếu là> 1 byte trong UTF8.
vỏ não

8
@cortices Có, tất cả các cuộc thi golf mã được ghi theo byte theo mặc định. Tuy nhiên, Jelly không sử dụng UTF-8, mà là một trang mã tùy chỉnh mã hóa từng trong số 256 ký tự mà nó hiểu là một byte đơn.
Dennis

@Dennis ah, thông minh.
vỏ não

7

Haskell, 19 byte

a#0=a
a#b=b#rem a b

Ví dụ sử dụng: 45 # 35-> 5.

Euclid, một lần nữa.

PS: tất nhiên cũng có tích hợp sẵn gcd.


bạn nên giải thích thủ thuật đảo ngược thứ tự đầu vào để tránh kiểm tra có điều kiện
tự hào

@proudhaskeller: lừa gì? Mọi người đều sử dụng thuật toán này, tức là dừng 0hoặc tiếp tục với mô-đun.
nimi

Nevrmind, tất cả mọi người đang sử dụng mánh khóe
tự hào

Điều này, ít chơi gôn, gần như chính xác những gì trongPrelude
Michael Klein

6

Trăn 3, 31

Đã lưu 3 byte nhờ Sp3000.

g=lambda a,b:b and g(b,a%b)or a

3
Trong Python 3.5+:from math import*;gcd
Sp3000

@ Sp3000 Nice, tôi không biết họ đã chuyển nó sang toán học.
Morgan Thrapp

1
Trong khi bạn đang ở đó:g=lambda a,b:b and g(b,a%b)or a
Sp3000

@ Sp3000 Cảm ơn! Tôi vừa hoàn thành một giải pháp đệ quy, nhưng điều đó thậm chí còn tốt hơn những gì tôi có.
Morgan Thrapp

Các bản dựng sẵn cho GCD và LCM không được phép, vì vậy giải pháp thứ 2 sẽ không hợp lệ.
mbomb007

6

MATL , 11 9 byte

Không ai có vẻ đã sử dụng vũ lực cho đến nay, vì vậy nó ở đây.

ts:\a~f0)

Đầu vào là một mảng cột có hai số (sử dụng ;làm dấu phân cách).

Hãy thử trực tuyến! hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình

t     % Take input [a;b] implicitly. Duplicate
s     % Sum. Gives a+b
:     % Array [1,2,...,a+b]
\     % Modulo operation with broadcast. Gives a 2×(a+b) array
a~    % 1×(a+b) array that contains true if the two modulo operations gave 0
f0)   % Index of last true value. Implicitly display

5

C, 38 byte

g(x,y){while(x^=y^=x^=y%=x);return y;}

1
Bạn cần bao gồm định nghĩa của hàm trong bytecount của bạn.
Rɪᴋᴇʀ

1
@Riker xin lỗi vì điều đó, tôi thêm định nghĩa và cập nhật số đếm
Cách Chen

Bạn có thể lưu hai byte bằng cách đặt tên hàm gthay vì gcd.
Steadybox

@Steadybox ok, vâng, lần đầu tiên tham gia cộng đồng này :)
Cách Chen

1
Chào mừng đến với PPCG!
Rɪᴋᴇʀ

4

C, 28 byte

Một hàm khá đơn giản thực hiện thuật toán của Euclid. Có lẽ người ta có thể nhận được ngắn hơn bằng cách sử dụng một thuật toán thay thế.

g(a,b){return b?g(b,a%b):a;}

Nếu một người viết một ít bao bọc chính

int main(int argc, char **argv)
{
  printf("gcd(%d, %d) = %d\n", atoi(argv[1]), atoi(argv[2]), g(atoi(argv[1]), atoi(argv[2])));
}

sau đó người ta có thể kiểm tra một vài giá trị:

$ ./gcd 6 21
gcd (6, 21) = 3
$ ./gcd 21 6
gcd (21, 6) = 3
$ ./gcd 6 8
gcd (6, 8) = 2
$ ./gcd 1 1
gcd (1, 1) = 1
$ ./gcd 6 16
gcd (6, 16) = 2
$ ./gcd 27 244
gcd (27, 244) = 1

4

Mê cung , 18 byte

?}
:
)"%{!
( =
}:{

Chấm dứt với một lỗi, nhưng thông báo lỗi đi đến STDERR.

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

Điều này chưa cảm thấy khá tối ưu, nhưng tôi không thấy cách nào để nén vòng lặp dưới 3x3 vào thời điểm này.

Giải trình

Điều này sử dụng thuật toán Euclide.

Đầu tiên, có một bit tuyến tính để đọc đầu vào và đi vào vòng lặp chính. Con trỏ lệnh (IP) bắt đầu ở góc trên cùng bên trái, đi về hướng đông.

?    Read first integer from STDIN and push onto main stack.
}    Move the integer over to the auxiliary stack.
     The IP now hits a dead end so it turns around.
?    Read the second integer.
     The IP hits a corner and follows the bend, so it goes south.
:    Duplicate the second integer.
)    Increment.
     The IP is now at a junction. The top of the stack is guaranteed to be
     positive, so the IP turns left, to go east.
"    No-op.
%    Modulo. Since `n % (n+1) == n`, we end up with the second input on the stack.

Bây giờ chúng ta nhập một loại vòng lặp while-do để tính toán thuật toán Euclide. Phần trên cùng của ngăn xếp chứa ab(trên đầu số lượng vô hạn ẩn, nhưng chúng ta sẽ không cần chúng). Chúng tôi sẽ đại diện cho các ngăn xếp cạnh nhau, phát triển về phía nhau:

    Main     Auxiliary
[ ... 0 a  |  b 0 ... ]

Vòng lặp chấm dứt một lần abằng không. Lặp lại vòng lặp hoạt động như sau:

=    Swap a and b.           [ ... 0 b  |  a 0 ... ]
{    Pull a from aux.        [ ... 0 b a  |  0 ... ]
:    Duplicate.              [ ... 0 b a a  |  0 ... ]
}    Move a to aux.          [ ... 0 b a  |  a 0 ... ]
()   Increment, decrement, together a no-op.
%    Modulo.                 [ ... 0 (b%a)  |  a 0 ... ]

Bạn có thể thấy, chúng tôi đã thay thế abvới b%aatương ứng.

Cuối cùng, một khi b%alà 0, IP tiếp tục di chuyển về phía đông và thực thi:

{    Pull the non-zero value, i.e. the GCD, over from aux.
!    Print it.
     The IP hits a dead end and turns around.
{    Pull a zero from aux.
%    Attempt modulo. This fails due to division by 0 and the program terminates.

4

Julia, 21 15 byte

a\b=a>0?b%a\a:b

Thực hiện đệ quy của thuật toán Euclide. Hãy thử trực tuyến!

Nếu không được tích hợp sẵn, gcd(3 byte, GCD tích hợp) sẽ đạt được điểm cao hơn.

Làm thế nào nó hoạt động

a\b=             Redefine the binary operator \ as follows:
    a>0?     :       If a > 0:
        b%a\a        Resursively apply \ to b%a and a. Return the result.
              b      Else, return b.

4

Hình khối , 10 12 byte

?v%uII/;O@

Hãy thử nó ở đây

Điều này kết thúc vào khối như sau:

    ? v
    % u
I I / ; O @ . .
. . . . . . . .
    . .
    . .

Sử dụng phương pháp Euclide.

IIHai số được lấy từ STDIN và đưa vào ngăn xếp
/Flow được phản ánh lên
%Mod Top of Stack. Phần còn lại bên trái trên cùng của ngăn xếp
?Nếu Tosh 0 thì tiếp tục, nếu không thì phải
vNếu không 0 thì chuyển hướng xuống và uquay lại hai lần vào mod
/Nếu 0 đi xung quanh khối lập phương để phản xạ
;thả Tosh, Oxuất ra Tosh và @kết thúc


Tôi vừa viết lên một câu trả lời Cubix 12 byte, sau đó bắt đầu cuộn qua các câu trả lời để xem liệu tôi có cần xử lý cả hai không 0,xx,0... sau đó tôi đã xem qua điều này. Đẹp quá
Sản phẩm ETH


3

Batch Windows, 76 byte

Hàm đệ quy. Gọi nó như GCD a bvới tên tập tin gcd.

:g
if %2 equ 0 (set f=%1
goto d)
set/a r=%1 %% %2
call :g %2 %r%
:d
echo %f%

3

MATL, 7 byte

pG1$Zm/

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

Giải trình

Vì chúng ta không thể sử dụng rõ ràng hàm GCD dựng sẵn ( Zdtrong MATL), tôi đã khai thác thực tế là bội số chung nhỏ nhất avà nhân bvới mẫu số chung lớn nhất abbằng với sản phẩm của ab.

p       % Grab the input implicitly and multiply the two elements
G       % Grab the input again, explicitly this time
1$Zm    % Compute the least-common multiple
/       % Divide the two to get the greatest common denominator

Bạn có thể lưu một byte với hai đầu vào riêng biệt:*1MZm/
Luis Mendo

3

Vợt (Lược đồ), 44 byte

Triển khai Euclid trong Vợt (Sơ đồ)

(define(g a b)(if(= 0 b)a(g b(modulo a b))))

Chỉnh sửa: Không thấy giải pháp của @Numeri lol. Bằng cách nào đó chúng tôi có cùng một mã chính xác một cách độc lập


Điều này có làm việc trong cả hai?
NoOneIsHãy

@NoOneIsHere yeah nó hoạt động trong cả hai
kronicmage

3

> <> , 32 byte

::{::}@(?\=?v{:}-
.!09}}${{/;n/>

Chấp nhận hai giá trị từ ngăn xếp và áp dụng thuật toán euclidian để tạo GCD của chúng.

Bạn có thể thử nó ở đây !

Để có câu trả lời tốt hơn nhiều trong> <>, hãy xem của Sok !


1
Tôi đã tìm thấy một ngôn ngữ mới ngày hôm nay :)
nsane


2

GML, 57 byte

a=argument0
b=argument1
while b{t=b;b=a mod b;a=t}return a

2

Delphi 7, 148

Chà, tôi nghĩ rằng tôi đã tìm thấy ngôn ngữ tồi tệ nhất mới để chơi gôn.

unit a;interface function g(a,b:integer):integer;implementation function g(a,b:integer):integer;begin if b=0then g:=a else g:=g(b,a mod b);end;end.

Ồ, tôi không biết, ở giữa dấu ngoặc là khá nghèo cho chơi golf
MickyT

2

Hoon, 20 byte

|=
{@ @}
d:(egcd +<)

-

Hoon # 2, 39 byte

|=
{a/@ b/@}
?~
b
a
$(a b, b (mod a b))

Điều kỳ lạ là, triển khai duy nhất trong stdlib của Hoon cho GCD là ứng dụng được sử dụng cho tiền điện tử RSA của nó, cũng trả về một số giá trị khác. Tôi phải bọc nó trong một chức năng chỉ dlấy từ đầu ra.

Việc thực hiện khác chỉ là định nghĩa GCD đệ quy mặc định.


2

Python 3.5, 70 82 73 byte:

lambda*a:max([i for i in range(1,max(*a)+1)if not sum(g%i for g in[*a])])

Trong nottrường hợp này sẽ đảm bảo tổng tất cả các số trong *argsmodulo ibằng không.

Ngoài ra, bây giờ hàm lambda này có thể nhận bao nhiêu giá trị mà bạn muốn, miễn là số lượng giá trị >=2, không giống như gcdhàm của mô-đun toán học. Chẳng hạn, nó có thể lấy các giá trị 2,4,6,8,10và trả về GCD đúng bằng 2.


1
Bạn đang bị bắt vì tên biến đa biến. (Hoặc đối số chức năng, nhưng bất cứ điều gì)
CalculatorFeline

2

Ruby, 23 byte

g=->a,b{b>0?a:g[b,a%b]}

hãy nhớ rằng các khối ruby ​​được gọi bằng g [...] hoặc g.call (...), thay vì g (...)

tín dụng một phần cho voidpigeon


2
Thay vì g.call(a,b)bạn có thể sử dụng g[a,b]. Thay vì proc{|a,b|, bạn có thể sử dụng ->a,b{.
từ

1
Bạn cũng có thể lưu một byte bằng cách sử dụng b>0thay vì b<=0và chuyển đổi thứ tự của các toán hạng khác.
từ

2

Mã máy ARM, 12 byte:

hội,, tổ hợp:

gcd: cmp r0, r1
     sublt r0, r0, r1
     bne gcd

Hiện tại không thể biên dịch cái này, nhưng mỗi lệnh trong ARM mất 4 byte. Có lẽ nó có thể được đánh xuống bằng chế độ THUMB-2.


Người đàn ông làm việc tốt, bất cứ ai làm điều này trong mã máy đều nhận được đạo cụ nghiêm túc từ tôi.
Mike Shlanta

Điều này dường như là một nỗ lực đối với thuật toán của Euclid chỉ bằng phép trừ , nhưng tôi không nghĩ rằng nó hoạt động. Nếu r0 > r1sau đó subltsẽ không làm gì ( ltvị ngữ là sai) và bnesẽ là một vòng lặp vô hạn. Tôi nghĩ rằng bạn cần một trao đổi nếu không lt, vì vậy vòng lặp tương tự có thể làm b-=ahoặc a-=bkhi cần thiết. Hoặc phủ định nếu phụ sản xuất mang (còn gọi là mượn).
Peter Cordes

Hướng dẫn tập lệnh ARM này thực sự sử dụng thuật toán GCD trừ để làm ví dụ cho mục đích. (trg 25). Họ sử dụng cmp r0, r1/ subgt r0, r0, r1/ sublt r1, r1, r0/ bne gcd. Đó là 16B trong hướng dẫn ARM, có thể là 12 trong hướng dẫn thumb2?
Peter Cordes

1
Trên x86, tôi đã quản lý 9 byte với: sub ecx, eax/ jae .no_swap/ add ecx,eax/ xchg ecx,eax/ jne. Vì vậy, thay vì một cmp, tôi chỉ phụ, sau đó hoàn tác và trao đổi nếu phụ nên đi theo cách khác. Tôi đã thử nghiệm điều này, và nó hoạt động. ( addsẽ không jnethoát ra không đúng lúc, vì nó không thể tạo ra số 0 trừ khi một trong những đầu vào bằng 0 và chúng tôi không hỗ trợ điều đó. Cập nhật: chúng tôi cần hỗ trợ đầu vào bằng 0: /)
Peter Cordes

Đối với Thumb2, có một itehướng dẫn: if-then-other. Nên hoàn hảo cho cmp / sub một cách / phụ theo cách khác.
Peter Cordes

2

TI-Basic, 10 byte

Prompt A,B:gcd(A,B

Không cạnh tranh do quy tắc mới cấm gcd tích hợp


Giải pháp 17 byte không tích gcd(hợp

Prompt A,B:abs(AB)/lcm(A,B

Không cạnh tranh do quy tắc mới cấm xây dựng lcm


Giải pháp 27 byte không có gcd(hoặc tích lcm(hợp:

Prompt A,B:While B:B→T:BfPart(A/B→B:T→A:End:A

Giải pháp đệ quy 35 byte không có gcd(hoặc tích lcm(hợp sẵn (yêu cầu hệ điều hành 2,53 MP trở lên, phải được đặt tên prgmG ):

If Ans(2:Then:{Ans(2),remainder(Ans(1),Ans(2:prgmG:Else:Disp Ans(1:End

Bạn sẽ chuyển các đối số cho biến thể đệ quy như {A,B}vậy, ví dụ như vậy {1071, 462}:prgmGsẽ mang lại 21.


Màu tôi ấn tượng.
Mike Shlanta

Bạn có lẽ nên đề cập rằng cái cuối cùng cần phải được lưu dưới dạng prgmG.
một spaghetto


2

Oracle SQL 11.2, 104 118 byte

SELECT MAX(:1+:2-LEVEL+1)FROM DUAL WHERE(MOD(:1,:1+:2-LEVEL+1)+MOD(:2,:1+:2-LEVEL+1))*:1*:2=0 CONNECT BY LEVEL<=:1+:2;

Đã sửa lỗi cho đầu vào 0


Không hoạt động chính xác nếu một trong những đầu vào bằng không.
Egor Skriptunoff

Điều này sẽ giúp bạn tiết kiệm một vàiSELECT MAX(LEVEL)FROM DUAL WHERE MOD(:1,LEVEL)+MOD(:2,LEVEL)=0 CONNECT BY LEVEL<=:1+:2;
MickyT

2

> <> , 12 + 3 = 15 byte

:?!\:}%
;n~/

Yêu cầu các số đầu vào sẽ xuất hiện trên ngăn xếp, vì vậy +3 byte cho -vcờ. Hãy thử trực tuyến!

Một triển khai khác của thuật toán Euclide.

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.