En büyük ortak böleni


40

Göreviniz, verilen iki tamsayının en büyük ortak bölenini (GCD) olabildiğince az kod baytında hesaplamak .

Kabul edilen standart yöntemlerimizden (STDIN / STDOUT, fonksiyon parametreleri / dönüş değerleri, komut satırı argümanları vb. Dahil) giriş ve dönüş almak için bir program veya fonksiyon yazabilirsiniz .

Girdi negatif olmayan iki tamsayı olacak. Dilinizin varsayılan tamsayı tipinin desteklediği tüm aralığı ya da [0,255]hangisi daha büyükse , aralığı kullanabilmelisiniz . Girdilerden en az birinin sıfır olamayacağı garantilidir.

GCD veya LCM'yi (örneğin, en yaygın çoklu) hesaplayan yerleşikleri kullanmanıza izin verilmez.

Standart kuralları geçerlidir.

Test Kılıfları

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
Hangi kayıtların uygun olduğu her ne olursa olsun girdilerin girmesine izin veriyorsak ve uygun kayıtların sonucu ne olursa olsun, kesinlikle fonksiyonlara, hatta kod parçalarına (yani sadece bir fonksiyon gövdesi) izin vermeliyiz. Cevabımı tam bir işlev haline getirmek, MS'in 32bit vectorcall (bir xchg eax, bir mov ve bir ret) gibi bir kayıt çağıran kongre veya yaklaşık bir yığın çağıran kongre ile yaklaşık 4B ekleyecektir.
Peter Cordes

@PeterCordes Üzgünüm, daha spesifik olmalıydım. Ayı gerekli kodunu tamamen yazabilirsiniz, ancak adı geçen kodu çalıştırmanın bir yolunu da içerecek kadar nazik olsaydınız iyi olurdu.
Mike Shlanta,

Öyleyse sadece gcd kodunu say, fakat etrafındaki kodu ver, böylece insanlar doğrulayabilir / deneyebilir mi? BTW, iki girişten biri sıfıra sahip test durumlarınız x86 makine kodu cevaplarımızı aştı. Sıfır tarafından div bir donanım istisnasını yükseltir. Linux'ta işleminiz bir olur SIGFPE.
Peter Cordes,

3
@CodesInChaos Algoritmanın kendisi prensipte tüm girdileri işleyebildiği sürece bellek ve zaman sınırlamaları genellikle göz ardı edilir. Kural sadece insanların algoritmayı yapay olarak daha küçük bir girdi aralığına sınırlayan döngüler için rastgele sınırları kodlamasını engellemektir. Değişmezliğin bu duruma nasıl geldiğini tam olarak anlayamıyorum?
Martin Ender

1
gcd (0, n) hata değil n
RosLuP

Yanıtlar:


37

Retina , 16

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

Bu, Euclid algoritmasını hiç kullanmaz - bunun yerine regex eşleme grupları kullanarak GCD'yi bulur.

Çevrimiçi deneyin. - Bu örnek GCD'yi (8,12) hesaplar.

2 boşlukla ayrılmış tam sayı olarak giriş yapın. G / Ç’nin bir arada olduğunu unutmayın. Eğer bu kabul edilebilir değilse, o zaman bunu yapabiliriz:

Retina, 30

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

Çevrimiçi deneyin.

@ MartinBüttner'ın işaret ettiği gibi, bu büyük sayılar için ayrı düşmektedir (genellikle tekdüzeylerde olduğu gibi). En azından, INT_MAX girişi bir 2GB dizenin ayrılmasını gerektirecektir.


2
Buna daha fazla oy kullanmak istiyorum
MickyT

Şimdi sayı aralığı ile iyi olmalı. Spesifikasyonu (OP'nin izniyle) yalnızca dilin doğal sayı aralığını (veya daha fazlası varsa [0,255]) gerektirecek şekilde değiştirdim. Ben değişen düşünüyorum karşın, yine de sıfır desteklemek gerekecek +için s *yapmalıdır s. Ve uzun kodun son aşamasını azaltmak için önemli ölçüde kısaltabilirsiniz 1.
Martin Ender

2
Gelecekte referans olarak, az sayıda rastgele girdi için çalışan (biri dahil) alternatif 16 baytlık bir çözüm buldum, bu nedenle diğer bağlamlarda daha yararlı olabilir: retina.tryitonline.net/…
Martin Ender

1
Sadece sizin çözümünüzün veya yukarıdaki yorumumda yer alanın gerekmediğini fark ettim ^, çünkü maçın başlama pozisyonundan başarısız olması imkansız.
Martin Ender

28

i386 (x86-32) makine kodu, 8 bayt (imzasızlar için 9B)

+ 1B b = 0girişi ele almamız gerekiyorsa .

amd64 (x86-64) makine kodu, 9 bayt (imzasızlar için 10B veya imzalı veya imzasız 64b tamsayılar için 14B 13B)

10 = 9B giriş veya 0 ile kesen amd64'te işaretsiz olanlar için


Girişler 32bit sıfırdan farklıdır imzalı tamsayılar eaxve ecx. Çıktı 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

Bu döngü yapısı, test durumunda başarısız olur ecx = 0. ( divBir neden #DEsıfıra bölme donanım Execption. (Linux'ta, çekirdek bir teslim SIGFPE)) (kayan nokta istisna. Döngü giriş noktası hemen önce olsaydı inc, biz sorunu önleyeceğini. X86-64 versiyonu halledebilirim ücretsiz, aşağıya bakınız.

Mike Shlanta'nın cevabı bunun başlangıç ​​noktasıydı . cdqDöngünüm onunla aynı şeyi yapıyor, ancak işaretli tamsayılar için çünkü ondan daha kısa bir xor edx,edx. Ve evet, negatif girişlerden biri veya ikisi ile doğru çalışıyor. Mike'ın sürümü daha hızlı çalışacak ve uop önbelleğinde daha az yer kaplayacak ( xchgIntel CPU'larda 3 ay ve loopçoğu CPU'da gerçekten yavaş ), ancak bu sürüm makine kodu boyutunda kazanacaktır.

İlk başta sorunun imzasız 32 bit gerektirdiğini fark etmedim . xor edx,edxBunun yerine geri gitmek cdqbir bayt mal olacak. divaynı boyuttadır idivve diğer her şey aynı kalabilir ( xchgveri hareketi ve inc/loophala çalışmak için).

İlginç bir şekilde, 64bit işlemsel boyutu ( raxve rcx) için, imzalı ve imzasız sürümleri aynı boyuttadır. İmzalı sürüm cqo(2B) için bir REX ön ekine ihtiyaç duyar , ancak imzasız sürüm hala 2B kullanabilir xor edx,edx.

64bit kodunda inc ecx2B'dir: tek bayt inc r32ve dec r32opkodlar REX önekleri olarak değiştirildi. inc/loop64bit modunda herhangi bir kod boyutunu kaydetmez, bu yüzden de olabilir test/jnz. 64bit tamsayılarda çalıştırma, REX öneklerinde, loopveya dışında bir komut başına bir bayt ekler jnz. Kalanın tümünün sıfırın 32b'de (örn. gcd((2^32), (2^32 + 1))) Olması mümkündür, bu nedenle tüm rcx'i test etmemiz gerekir ve bir bayttan tasarruf edemeyiz test ecx,ecx. Ancak, yavaş jrcxzinsn sadece 2B'dir ve ecx=0girişte işlemek için onu döngünün en üstüne koyabiliriz :

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

32 ve 64b versiyonları için Godbolt Compiler Explorer'da kaynak ve asm çıktısınımain çalıştıran bir program içeren tam çalıştırılabilir test programı . 32bit ( ), 64bit ( ) ve x32 ABI ( ) için test edildi ve çalışıyor .printf("...", gcd(atoi(argv[1]), atoi(argv[2])) ); -m32-m64-mx32

Ayrıca dahil: yalnızca tekrarlanan çıkarma işlemini kullanan , x86-64 modunda bile imzasızlar için 9B olan ve rastgele bir sicildeki girişlerinden birini alabilen bir sürüm . Bununla birlikte, girişte 0 olan her iki girişi de kaldıramaz ( subsıfır ürettiğinde algılar , ki bu x - 0 asla yapmaz).

32bit sürümü için GNU C satır içi asm kaynağı (derleme ile 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;
}

Normalde bir fonksiyonun tamamını asm olarak yazardım, ama GNU C satır içi asm, hangi regs'de olursa olsun giriş / çıkış yapabilen bir snippet'i dahil etmenin en iyi yolu gibi görünüyor. Gördüğünüz gibi GNU C satır içi asm sözdizimi çirkin ve gürültülü yapar. Aynı zamanda bir var gerçekten zor yolu öğrenmek asm .

Aslında, derleme ve .att_syntax noprefixmodda çalışacaktı , çünkü kullanılan tüm insns ya tek / operand değil xchg. Gerçekten faydalı bir gözlem değil.


2
@MikeShlanta: Teşekkürler. Asm optimizasyonunu seviyorsanız, stackoverflow hakkındaki cevaplarımın bazılarına bir göz atın. :)
Peter Cordes,

2
@MikeShlanta: jrcxzuint64_t versiyonunda :) bir sonuç buldum. Ayrıca, imzasız olarak belirttiğinizi farketmedim, bu yüzden ben de bunun için bayt sayımları dahil ettim.
Peter Cordes

Neden jecxz32 bit sürümde aynı etkiyi kullanmadınız?
Cody Gray

1
@CodyGray: inc/loop32 bit sürümde 3 bayt, 64 bit sürümde ise 4B'dir . 64 bit sürümünde, kullanımı ekstra bayt mal olmaz Bunun anlamı jrcxzve jmpyerine inc / loop.
Peter Cordes,

Ortadaki girişi olarak gösteremez misin?
18m2'de

14

Altıgen , 17 bayt

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

Kırımsız:

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

Çevrimiçi deneyin!

Kenar uzunluğu 3'e oturtmak bir esinti oldu. Sonunda bu iki baytı tıraş etmek de değildi ... Ben de en iyisine ikna olmadım, ama sanırım yakın olduğunu düşünüyorum.

açıklama

Başka bir Öklid algoritması uygulaması.

Program, gösterildiği gibi bellek işaretçisi (MP) ile A , B ve C olarak adlandırdığım üç bellek kenarını kullanır :

görüntü tanımını buraya girin

İşte kontrol akış şeması:

görüntü tanımını buraya girin

Kontrol akışı, giriş için kısa bir doğrusal bit ile gri yolda başlar:

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

Kodun artık kenarları <sol köşedeki kenarlara sardığını unutmayın . Bu <bir şube gibi davranır. Geçerli kenar sıfır ise (yani Öklid algoritması sona erer), IP sola saptırılır ve kırmızı yolu alır. Aksi takdirde, yeşil yol üzerinde Öklid algoritmasının bir yinelemesi hesaplanır.

İlk önce yeşil yolu ele alacağız. Not olduğunu >ve \tüm basitçe talimat işaretçi saptırmak aynalar gibi davranır. Ayrıca kontrol akışının koşulu tekrar kontrol etmek için kenarların etrafına bir kez alttan üste, bir kez sağ köşeden alt sırasına ve son olarak sağ alt köşeden sol köşeye sarıldığını unutmayın. Ayrıca .no-ops olmadığını unutmayın .

Bu, tek bir yineleme için aşağıdaki doğrusal kodu bırakır:

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

Şimdi başladığımız yere geri döndük, ancak üç kenar rollerini döngüsel olarak değiştirdiler (orijinal C şimdi B rolünü alır ve orijinal B şimdi A rolünü alır ...). Gerçekte, girdileri relpaced ettik Ave Bbirlikte Bve A % Bsırasıyla.

Bir kez A % B(kenar üzerinde C ) sıfır, elusyonu kenarı üzerinde bulunabilir B . Yine >sadece IP saptırıyor, bu yüzden kırmızı yolda yürütürüz:

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

9

32 bit küçük endian x86 makine kodu, 14 bayt

Kullanılarak oluşturulan 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
Bunu kullanarak kullanıp cdqimzalayıp 8 bayta idiv, xchg eax, r32yerine 1 bayta indirdim mov. 32bit kod için: inc/loopyerine ( Kullanmanın test/jnzbir yolunu göremedim jecxzve yok jecxnz). Son versiyonumu yeni bir cevap olarak yayınladım, çünkü değişikliklerin bunu haklı çıkaracak kadar büyük olduğunu düşünüyorum.
Peter Cordes,

9

T-SQL, 153 169 bayt

Birisi golf oynamak için en kötü dilden mi bahsetti?

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

Ortak bölenleri çözmek için özyinelemeli bir sorgu kullanan tablo değerli bir işlev oluşturur . Sonra maksimum değerini döndürür . Şimdi burada cevabımdan türetilen GCD'yi belirlemek için öklid algoritmasını kullanıyor .

Örnek kullanım

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
Ayrıntılı olan İsa.
Cyoce

9

Jöle, 7 bayt

ṛß%ðḷṛ?

Öklid algoritmasının özyinelemeli uygulaması. Çevrimiçi deneyin!

Yerleşikler yasaklanmasaydı g(1 bayt, yerleşik GCD) daha iyi bir puan alacaktı.

Nasıl çalışır

ṛß%ðḷṛ?  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).

Neredeyse haha ​​aldatmak gibi geliyor, cevapların
butlin

13
Bunu yapmaya karar verirseniz, hızlı bir şekilde yapmalısınız. Şu anda cevapların üçünü geçersiz kılacaktır.
Dennis,

Belirlenen uzunluk bayt cinsindendir - bu karakterler UTF8'de çoğunlukla> 1 bayttır.
kortlar

8
@cortices Evet, tüm kod golf yarışmaları varsayılan olarak bayt cinsinden puanlanır. Bununla birlikte, Jelly UTF-8'i kullanmaz, ancak tek bir bayt olarak anladığı 256 karakterin her birini kodlayan özel bir kod sayfasıdır .
Dennis,

@Dennis ah, zekice.
kortlar

7

Haskell, 19 bayt

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

Kullanım örneği: 45 # 35-> 5.

Yine Euclid.

PS: Elbette bir de yerleşik var gcd.


koşullu kontrolü önlemek için girdi sırasını tersine çeviren hileyi açıklamalısınız
proud haskeller

@ proudhaskeller: ne numarası? Herkes bu algoritmayı kullanıyor, yani 0modülü durdurup devam ettiriyor.
nimi

Nevrmind, herkes hile kullanıyor
gururlu haskeller

Bu, daha az golf oynadı, neredeyse tam olarak ne olduğunuPrelude
Michael Klein

6

Python 3, 31

Sp3000 sayesinde 3 bayt kurtardı.

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

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

@ Sp3000 Nice, matematiğe taşıdıklarını bilmiyordum.
Morgan Thrapp

1
Siz varken:g=lambda a,b:b and g(b,a%b)or a
Sp3000

@ Sp3000 Teşekkürler! Özyinelemeli bir çözümü yeni bitirdim, fakat sahip olduklarımdan daha iyi.
Morgan Thrapp

GCD ve LCM için yerleşiklere izin verilmez, bu nedenle 2. çözüm geçerli olmaz.
mbomb007

6

MATL , 11 9 bayt

Şimdiye kadar hiç kimse kaba kuvvet kullanmamış gibi görünüyor, işte burada.

ts:\a~f0)

Giriş, iki sayının bulunduğu bir sütun dizisidir ( ;ayırıcı olarak kullanılır ).

Çevrimiçi deneyin! veya tüm test durumlarını doğrulayın .

açıklama

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 bayt

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

1
İşlev tanımını bayt sayınıza eklemeniz gerekir.
17:24

1
@Riker bunun için üzgünüm, tanımı ekledim ve sayısını güncelle
Chen

İşlev gyerine, yalnızca ad vererek iki bayt kaydedebilirsiniz gcd.
Steadybox,

@Steadybox tamam, evet, bu topluluğa ilk defa katılıyor :)
Nasıl Chen

1
PPCG'ye Hoşgeldiniz!
Rɪᴋᴇʀ

4

C, 28 bayt

Euclid algoritmasını uygulayan oldukça basit bir fonksiyon. Belki bir alternatif algoritma kullanarak daha kısa olabilir.

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

Bir küçük bir ana sargı yazarsa

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

o zaman kişi birkaç değeri test edebilir:

$ ./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

Labirent , 18 bayt

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

Hata ile sonlanır, ancak hata mesajı STDERR'ye gider.

Çevrimiçi deneyin!

Bu henüz tam olarak en uygun görünmüyor, ancak bu noktada 3x3 altındaki döngüyü sıkıştırmanın bir yolunu göremiyorum.

açıklama

Bu, Öklid algoritmasını kullanır.

İlk önce, girişi okumak ve ana döngüye girmek için doğrusal bir bit var. Yönlendirme işaretçisi (IP) sol üst köşeden başlayarak doğuya doğru ilerler.

?    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.

Şimdi, Öklid algoritmasını hesaplayan bir tür while-do döngüsüne giriyoruz. Yığınların üst kısımları içerir ave b(üstü kapalı miktarda sıfırlar içerir, ancak bunlara ihtiyacımız olmayacak). Birbirlerine doğru büyüyen yığınları yan yana temsil edeceğiz:

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

Döngü bir kez sonlanır a, sıfırdır. Bir döngü yineleme aşağıdaki gibi çalışır:

=    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 ... ]

Sence yerini ettik görebilirsiniz ave bile b%ave asırasıyla.

Son olarak, bir kez b%asıfır olduğunda, IP doğuya devam eder ve yürütür:

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

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

Öklid algoritmasının özyinelemeli uygulaması. Çevrimiçi deneyin!

Yerleşikler yasaklanmasaydı gcd(3 bayt, yerleşik GCD) daha iyi bir skor elde edecekti.

Nasıl çalışır

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

Cubix , 10 12 bayt

?v%uII/;O@

Burada dene

Bu, küp üzerine şu şekilde sarılır:

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

Öklid Metodunu kullanır.

IIİki numaralar STDIN'den yakaladı ve yığın konur
/Akış yukarı yansıyan
%Stack Mod Üst. Kalan yığının tepesine sol
?sağ TOS 0 ardından aksi halde devam açarsanız
vsonra aşağı yönlendirmek ve 0 Değilse umod üzerine iki kez doğru geri çevirmek
/durumunda reflektör için küp civarında 0 Git
;damla TOS, Oçıkış TOS ve @bitiş


12 baytlık bir Cubix cevabı yazdım, sonra ikisini de kullanmam gerekip gerekmediğini görmek için cevaplar arasında dolaşmaya başladım 0,xve x,0... ... bununla karşılaştım. Güzel!
ETHProductions,


3

Windows Toplu İş, 76 bayt

Özyinelemeli işlevi. GCD a bDosya adı gibi arayın 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 bayt

pG1$Zm/

Çevrimiçi Deneyin!

açıklama

Biz açıkça (yerleşik OBEB işlevi kullanamazsınız yana ZdMatl olarak), ben en küçük ortak birden gerçeğini istismar var ave bsüreleri en büyük ortak paydası ave bürünü eşittir ave b.

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

İki ayrı *1MZm/
girişle

3

Raket (Düzen), 44 bayt

Rakette Öklid uygulaması (Şema)

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

Düzenleme: @Nümeri'nin çözümü lol görmedim. Her nasılsa bağımsız olarak aynı kodu aldık


Bu her ikisinde de işe yarıyor mu?
NoOneIsHere

@HayırOnlarHere evet her ikisinde de işe
yarar

3

> <> , 32 bayt

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

Yığından iki değer alır ve onların GCD'lerini üretmek için euclidian algoritmasını uygular.

Burada deneyebilirsiniz !

> <> ' Daki daha iyi bir cevap için Sok's !


1
Bugün yeni bir dil buldum :)
nsane


2

GML, 57 bayt

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

2

Delphi 7, 148

Golf için en kötü dili bulduğumu düşünüyorum.

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.

Bilmiyorum, parantez golf
oynamak

2

Hoon, 20 bayt

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

-

Hoon # 2, 39 bayt

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

İşin garibi, Hoon’un GCD için stdlib’indeki tek uygulama, aynı zamanda bazı diğer değerleri de veren RSA şifrelemesi için kullanılan uygulama. Sadece dçıktıdan alan bir fonksiyona sarmalıyım.

Diğer uygulama sadece varsayılan özyinelemeli GCD tanımıdır.


2

Python 3.5, 70 82 73 bayt:

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

notBu durumda emin toplamı bütün numaraları yapacak *argsmodülo isıfırdır.

Ayrıca, şimdi bu lambda işlevi , matematik modülünün işlevinden >=2farklı olarak , değerlerin miktarı olduğu sürece, istediğiniz kadar değer alabilir gcd. Örneğin, değerleri alabilir 2,4,6,8,10ve 2'nin doğru GCD'sini geri getirebilir .


1
Multichar değişken isimleri yüzünden tutuklusun. (Veya fonksiyon argümanları, ama her neyse)
CalculatorFeline

2

Ruby, 23 bayt

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

ruby bloklarının g (...) yerine g [...] veya g.call (...) ile çağrıldığını unutmayın.

voidpigeon için kısmi krediler


2
g.call(a,b)Senin yerine kullanabilirsin g[a,b]. Bunun yerine proc{|a,b|kullanabilirsiniz ->a,b{.
afuous

1
Diğer işlenenlerin sırasını kullanmak b>0yerine b<=0ve onu kullanarak bir bayt da kaydedebilirsiniz .
afuous

2

ARM makine kodu, 12 bayt:

montaj:

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

Şu anda bunu derleyemiyorum, ancak ARM'deki her komut 4 bayt alıyor. Muhtemelen THUMB-2 modunu kullanarak golf oynamak olabilir.


Güzel bir iş adamı, makine kodunda bunu yapan herkes benden ciddi malzemeler alıyor.
Mike Shlanta,

Bu, Euclid’in algosunda sadece çıkarma kullanarak yapılan bir girişim gibi görünüyor , ama işe yaradığını sanmıyorum. Eğer r0 > r1o subltzaman hiçbir şey yapmaz ( ltyüklem yanlıştır) ve bnesonsuz bir döngü olacaktır. Sanmıyorum eğer bir değiş tokuş yapmanıza gerek yok lt, bu yüzden aynı döngü yapabilir b-=aya a-=bda gerektiği gibi. Ya da eğer üretilen alt taşınırsa olumsuz (aka ödünç).
Peter Cordes

Bu ARM komut seti kılavuzu aslında tahmin için bir örnek olarak bir çıkarma GCD algoritması kullanır. (sf 25). Onlar kullanmak cmp r0, r1/ subgt r0, r0, r1/ sublt r1, r1, r0/ bne gcd. ARM talimatlarında 16B, thumb2 talimatlarında 12 olabilir.
Peter Cordes

1
X86'da 9 byte'ı sub ecx, eax/ jae .no_swap/ add ecx,eax/ xchg ecx,eax/ ile yönetdim jne. Yani bir cmp yerine, ben sadece sub, sonra geri almak ve sub başka bir şekilde gitmiş olsaydı değiş tokuş. Bunu test ettim ve işe yarıyor. ( yanlış zamanda çıkış addyapmaz jneçünkü girişlerden biri başlangıçta sıfır olmadıkça sıfır üretemez ve bunu desteklemiyoruz. Güncelleme: girişin sıfır olmasını desteklememiz gerekir: /)
Peter Cordes

Thumb2 için bir itetalimat var: if-then-else. Cmp / sub bir şekilde / alt diğer için mükemmel olmalıdır.
Peter Cordes

2

TI-Basic, 10 bayt

Prompt A,B:gcd(A,B

Gcd yerleşiklerini yasaklayan yeni kural nedeniyle rekabet etmeyen


17 bayt olmadan çözüm gcd(yerleşik

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

Lcm yerleşiklerini yasaklayan yeni kural nedeniyle rekabet dışı


Yerleşikgcd( veya lcm(yerleşik 27 byte çözüm :

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

35 bayt özyinelemeli çözüm olmadan gcd(veya lcm(yerleşik (2.53 MP işletim sistemi veya üstü gerektirir, adlandırılmış olmalıdır prgmG ):

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

Bu şekilde yinelemeli varyanta argümanları olur {A,B}, böylece örneğin {1071, 462}:prgmGdoğuracak 21.


Beni etkiledi renk.
Mike Shlanta,

Muhtemelen sonuncunun olarak kaydedilmesi gerektiğini söylemelisin prgmG.
bir


2

Oracle SQL 11.2, 104 118 bayt

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;

0 girişi için sabit


Girdilerden biri sıfır olduğunda doğru çalışmıyor.
Egor Skriptunoff

Bu size bir kaç tasarruf etmeliSELECT MAX(LEVEL)FROM DUAL WHERE MOD(:1,LEVEL)+MOD(:2,LEVEL)=0 CONNECT BY LEVEL<=:1+:2;
MickyT

2

> <> , 12 + 3 = 15 bayt

:?!\:}%
;n~/

Girdi numaralarının yığında bulunmasını, -vbayrak için +3 bayt olmasını bekler . Çevrimiçi deneyin!

Öklid algoritmasının başka bir uygulaması.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.