Найбільший загальний дільник


40

Ваше завдання - обчислити найбільший спільний дільник (GCD) з двох заданих цілих чисел на якомога менше байтів коду.

Ви можете написати програму або функцію, приймаючи введення та повернення виводу будь-яким із прийнятих нами стандартних методів (включаючи STDIN / STDOUT, параметри функцій / значення повернення, аргументи командного рядка тощо).

Вхідними даними будуть два невід’ємних цілих числа. Ви повинні мати змогу обробляти або весь діапазон, підтримуваний типовим цілим типом вашої мови, або діапазон [0,255], залежно від того, який більший. Вам гарантовано, що принаймні один із входів буде нульовим.

Вам заборонено використовувати вбудовані модулі, які обчислюють або GCD, або LCM (найменше загальний множина).

Діють стандартні правила .

Випробування

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
Якщо ми дозволяємо asm мати вхід у будь-які регістри, які зручні, і результат у будь-якому регістрі є зручним, ми, безумовно, повинні дозволяти функції, або навіть фрагменти коду (тобто лише тіло функції). Здійснення моєї відповіді повною функцією додало б близько 4В з конвенцією виклику реєстру, як 32-бітний векторний виклик MS (один xchg eax, один mov і ret) або більше з умовою виклику стека.
Пітер Кордес

@PeterCordes Вибачте, я повинен був бути більш конкретним. Ви можете повністю просто написати необхідний код ведмедя, але якщо ви будете настільки люб'язними, щоб включити спосіб запуску вказаного коду, було б добре.
Майк Шланта

Тож рахуйте лише код gcd, але надайте навколишній код, щоб люди могли перевірити / експериментувати / покращити? До речі, ваші тестові випадки з нулем на одному з двох входів ламають наші відповіді машинного коду x86. div by zero підвищує апаратний виняток. У Linux ваш процес отримує SIGFPE.
Пітер Кордес

3
@CodesInChaos Зазвичай пам'ять та обмеження часу ігноруються до тих пір, поки алгоритм може в принципі обробляти всі входи. Це правило якраз покликане уникати жорсткого кодування довільних обмежень для циклів, що штучно обмежує алгоритм меншим діапазоном входів. Я не зовсім бачу, як незмінність вступає в це?
Мартін Ендер

1
gcd (0, n) - помилка не n
RosLuP

Відповіді:


37

Сітківка , 16

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

Це взагалі не використовує алгоритм Евкліда - натомість він знаходить GCD, використовуючи групи, що відповідають регулярному вираженню.

Спробуйте в Інтернеті. - Цей приклад обчислює GCD (8,12).

Введіть як два цілих числа, розділених пробілом. Зауважте, що введення / вивід не є одинаковим. Якщо це не прийнятно, ми можемо зробити це:

Сітківка, 30

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

Спробуйте в Інтернеті.

Як зазначає @ MartinBüttner, це розпадається на велику кількість (як правило, це стосується будь-якого непорядного). Як мінімум, для введення INT_MAX потрібно буде виділити рядок 2 Гб.


2
Я хотів би проголосувати ще за це
MickyT

Зараз має бути добре з діапазоном чисел. Я змінив специфікацію (з дозволу ОП), щоб вимагати лише природний діапазон чисел мови (або [0,255], якщо це більше). Вам доведеться підтримувати нулі, хоча я думаю, що зміна вашого +s на *s повинна зробити. І ви можете значно скоротити останній етап довгого коду, зменшивши його до 1.
Мартін Ендер

2
Для подальшої довідки я щойно знайшов альтернативне 16-байтове рішення, яке працює для довільної кількості входів (включаючи один), тому воно може бути кориснішим в інших контекстах: retina.tryitonline.net/…
Martin Ender

1
Щойно зауважив, що ні ваші рішення, ні те, що в моєму коментарі вище, не потребують ^, тому що матч не може зійти зі стартової позиції.
Мартін Ендер

28

i386 (x86-32) код машини, 8 байт (9B для неподписаного)

+ 1B, якщо нам потрібно обробляти b = 0на вході.

машинний код amd64 (x86-64), 9 байт (10B для непідписаних чи 14B 13B для 64b цілих чисел, підписаних або непідписаних)

10 9B для неподписаного на amd64, який переривається з будь-яким входом = 0


Входи 32bit ненульові підписані цілі числа eaxі ecx. Вихід в 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

Ця структура циклу не відповідає тестовому випадку, де ecx = 0. ( divвикликає #DEапаратне вилучення при поділі на нуль. (У Linux ядро ​​забезпечує SIGFPE(виняток із плаваючою точкою)). Якщо точка входу в цикл була прямо перед inc, ми б уникнули проблеми. Версія x86-64 може це впоратися безкоштовно дивіться нижче.

Відповідь Майка Шланта стала відправною точкою для цього . Мій цикл робить те саме, що і його, але для підписаних цілих чисел, оскільки cdqна один байт коротший xor edx,edx. І так, він працює правильно з одним або обома вхідними мінусами. Версія Майка працюватиме швидше і займе менше місця в загальному кеші ( xchg3 процесори на процесорах Intel і loopна більшості процесорів дійсно повільні ), але ця версія виграє при розмірі машинного коду.

Я спочатку не помітив, що для запитання потрібен 32-розрядний без підпису . Повернення до xor edx,edxзамість цього cdqобійдеться в один байт. divмає той самий розмір idiv, що і все інше може залишатися однаковим ( xchgдля руху даних та inc/loopроботи).

Цікаво, що для 64-бітних операндів розміром ( raxі rcx) підписані та непідписані версії мають однаковий розмір. Підписана версія потребує префікса REX для cqo(2B), але неподписана версія все ще може використовувати 2B xor edx,edx.

У 64-бітовому коді inc ecxє 2B: однобайтові inc r32та dec r32опкоди були перестановлені у вигляді префіксів REX. inc/loopне зберігає жодного розміру коду в 64-бітовому режимі, так що ви можете також test/jnz. Операція з 64-бітовими цілими числами додає ще один байт на інструкцію в префіксах REX, за винятком loopабо jnz. Для решти всі нулі мають низький 32b (наприклад gcd((2^32), (2^32 + 1))), тому нам потрібно протестувати весь rcx і не можемо зберегти байт test ecx,ecx. Однак, більш повільний jrcxzінс становить лише 2B, і ми можемо поставити його у верхній частині циклу для обробки ecx=0при вході :

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

Повна тестова програма, mainяка працює, що включає printf("...", gcd(atoi(argv[1]), atoi(argv[2])) ); джерело та вихід ASM у Провіднику Godbolt Compiler , для версій 32 та 64b. Тестували та працювали для 32-бітових ( -m32), 64-бітових ( -m64) та x32 ABI ( -mx32) .

Також включена: версія, що використовує лише повторне віднімання , яка становить 9В для непідписаного, навіть для режиму x86-64, і може приймати один із своїх входів у довільному регістрі. Однак він не може обробити жоден вхід 0 при вході (він виявляє, коли subвиробляє нуль, що x - 0 ніколи не робить).

Вбудоване джерело ASM GNU C для 32-бітної версії (компілювати з 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;
}

Зазвичай я б написав цілу функцію в ASM, але GNU C вбудований asm, здається, є найкращим способом включити фрагмент, який може мати вхід / вихід у будь-які регіони, які ми виберемо. Як бачите, GNU C вбудований синтаксис asm робить asm некрасивим і галасливим. Це також дійсно складний спосіб засвоїти асм .

Він насправді .att_syntax noprefixзбирається і працює в режимі, тому що всі використовувані записи є одиничними / без операнду або xchg. Не дуже корисне спостереження.


2
@MikeShlanta: Дякую Якщо вам подобається оптимізувати asm, перегляньте деякі мої відповіді на stackoverflow. :)
Пітер Кордес

2
@MikeShlanta: я знайшов використання для jrcxzкінця у версії uint64_t :). Крім того, не помітили, що ви вказали без підписання, тому я також включив кількість байтів для цього.
Пітер Кордес

Чому ви не могли використати jecxz32-бітну версію з таким же ефектом?
Коді Грей

1
@CodyGray: inc/loopстановить 3 байти в 32-бітній версії, але 4B у 64-бітній версії. Це означає, що лише в 64-бітній версії це не коштує зайвих байтів, jrcxzа не jmpзамість них inc / loop.
Пітер Кордес

Ви не можете вказати середину як запис?
l4m2

14

Шестикутник , 17 байт

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

Розгорнуто:

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

Спробуйте в Інтернеті!

Встановити його в сторону довжиною 3 було вітром. Бриття цих двох байтів наприкінці не було ... Я також не впевнений, що це оптимально, але я впевнений, що думаю, що це близько.

Пояснення

Ще одна реалізація алгоритму Евкліда.

Програма використовує три ребра пам'яті, які я називаю A , B і C , при цьому вказівник пам'яті (MP) починається так, як показано:

введіть тут опис зображення

Ось схема управління потоком:

введіть тут опис зображення

Контрольний потік починається на сірій стежці з короткого лінійного біта для введення:

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

Зауважте, що код тепер обмотується навколо країв до <лівого кута. Це <виступає як галузь. Якщо поточний край дорівнює нулю (тобто алгоритм Евкліда закінчується), IP відхиляється ліворуч і приймає червоний шлях. В іншому випадку, ітерація алгоритму Евкліда обчислюється на зеленому шляху.

Спочатку ми розглянемо зелену стежку. Зауважте, що >і \всі вони виступають як дзеркала, які просто відхиляють покажчик інструкції. Також зауважте, що контрольний потік обертається по краях три рази, один раз знизу до верху, один раз від правого кута до нижнього ряду та нарешті від правого нижнього кута до лівого кута, щоб повторно перевірити стан. Також зауважте, що .немає ніяких операцій.

Це залишає такий лінійний код для однієї ітерації:

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

Тепер ми повернулися з того, що ми почали, за винятком того, що три краї змінили свої ролі циклічно (оригінальний C зараз бере роль B, а оригінальний B - роль A ...). Насправді ми перенесли вхід Aі Bвідповідно, Bі A % Bвідповідно.

Після того, як A % B(по краю C ) дорівнює нулю, то НСД можна знайти на кромці B . Знову >просто відхиляє IP, тому на червоному шляху ми виконуємо:

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

9

32-розрядний машинний код маленького ендіанського x86, 14 байт

Створено за допомогою 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
Я знизив це до 8 байт, використовуючи cdqі підписавши idiv, і однобайт xchg eax, r32замість mov. Для 32-бітового коду: inc/loopзамість test/jnz(я не бачив способу використання jecxz, а його немає jecxnz). Я опублікував свою остаточну версію як нову відповідь, оскільки думаю, що зміни є досить великими, щоб виправдати її.
Пітер Кордес

9

T-SQL, 153 169 байт

Хтось згадав найгіршу мову для гольфу?

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

Створює функцію оцінювання таблиці, яка використовує рекурсивний запит для опрацювання загальних дільників. Потім він повертає максимум . Тепер використовується алгоритм Евкліда для визначення GCD, отриманого з моєї відповіді тут .

Приклад використання

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
Ісус, що є багатослівним.
Кіос

9

Желе, 7 байт

ṛß%ðḷṛ?

Рекурсивна реалізація алгоритму Евкліда. Спробуйте в Інтернеті!

Якби вбудовані модулі не були заборонені, g(1 байт, вбудований GCD) досягнув би кращої оцінки.

Як це працює

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

Це майже схоже на обман ха-ха, можливо, мені доведеться уточнити, що у відповідях не можна використовувати butlins ...
Майк Шланта

13
Якщо ви вирішили це зробити, ви повинні зробити це швидко. Наразі це скасує три відповіді.
Денніс

Зверніть увагу, що вказана довжина знаходиться в байтах - ці символи здебільшого> 1 байт у UTF8.
корти

8
@cortices Так, усі змагання з гольфними кодами за замовчуванням оцінюються у байтах. Однак Jelly не використовує UTF-8, а користувацьку кодову сторінку, що кодує кожен із 256 символів, які він розуміє як один байт.
Денніс

@Dennis ах, розумний.
корти

7

Хаскелл, 19 байт

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

Приклад використання: 45 # 35-> 5.

Евклід, знову.

PS: звичайно, є і вбудований gcd.


Ви повинні пояснити хитрість, яка скасовує порядок введення, щоб уникнути умовної перевірки
гордий haskeller

@proudhaskeller: який трюк? Усі використовують цей алгоритм, тобто зупинятись 0чи продовжуватися з модулем.
німі

Неврмінд, всі використовують трюк
гордий haskeller

Це, менш гольф, майже саме те, що єPrelude
Майкл Клейн

6

Пітон 3, 31

Збережено 3 байти завдяки Sp3000.

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

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

@ Sp3000 Приємно, я не знав, що вони перенесли це на математику.
Морган Трапп

1
Поки ти на це:g=lambda a,b:b and g(b,a%b)or a
Sp3000

@ Sp3000 Дякую! Я щойно закінчив рекурсивне рішення, але це навіть краще, ніж у мене.
Морган Трапп

Вбудовані модулі для GCD та LCM заборонені, тому друге рішення не було б дійсним.
mbomb007

6

MATL , 11 9 байт

Здається, ніхто досі не використовував грубу силу, тому ось вона.

ts:\a~f0)

Вхід - це масив стовпців з двома номерами (використовуючи ;як роздільник).

Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Пояснення

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 байт

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

1
Потрібно включити визначення функції у свій рахунок.
Rɪᴋᴇʀ

1
@Riker вибачте за це, я додаю визначення та оновлюю кількість
як Чен

Ви можете зберегти два байти, назвавши функцію gзамість gcd.
Steadybox

@Steadybox ок, так, вперше приєднайтесь до цієї спільноти :)
Як Чень

1
Ласкаво просимо до PPCG!
Rɪᴋᴇʀ

4

C, 28 байт

Досить проста функція, що реалізує алгоритм Евкліда. Можливо, можна скоротити використання альтернативного алгоритму.

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

Якщо ви пишете трохи основної обгортки

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

то можна перевірити кілька значень:

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

Лабіринт , 18 байт

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

Закінчується помилкою, але повідомлення про помилку переходить до STDERR.

Спробуйте в Інтернеті!

Це ще не зовсім оптимально, але в даний момент я не бачу способу стиснути цикл нижче 3х3.

Пояснення

Для цього використовується алгоритм Евкліда.

По-перше, є лінійний біт, щоб прочитати вхід і потрапити в основний цикл. Покажчик інструкцій (IP) починається у верхньому лівому куті, йде на схід.

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

Тепер ми вводимо своєрідний цикл while-do, який обчислює алгоритм Евкліда. Вершини стеків містять aі b(поверх неявної нескінченної кількості нулів, але вони нам не знадобляться). Ми будемо представляти стеки стороною вбік, зростаючи назустріч один одному:

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

Цикл закінчується один раз aдорівнює нулю. Ітерація циклу працює наступним чином:

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

Ви можете бачити, ми замінили aі bз b%aі aвідповідно.

Нарешті, як тільки b%aдорівнює нулю, IP продовжує рухатися на схід і виконує:

{    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

Джулія, 21 15 байт

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

Рекурсивна реалізація алгоритму Евкліда. Спробуйте в Інтернеті!

Якби вбудовані модулі не були заборонені, gcd(3 байти, вбудований GCD) мали б кращу оцінку.

Як це працює

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 байт

?v%uII/;O@

Спробуйте тут

Це загортається на куб наступним чином:

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

Використовує евклідовий метод.

IIДва числа захоплюють з STDIN і ставлять на стек
/Потік, відображений вгору
%Mod the Top of Stack. Залишився ліворуч на вершині стека
?Якщо TOS 0 потім продовжувати, інакше поверніть праворуч
vЯкщо не 0, то перейдіть вниз і uдвічі поверніть праворуч на мод
/Якщо 0 об’їжджайте куб до відбивача,
;падайте TOS, Oвиведіть TOS і @закінчіть


Я щойно написав 12-байтну відповідь Cubix, потім почав прокручувати відповіді, щоб побачити, чи потрібно мені обробляти обидва 0,xі x,0... тоді я натрапив на це. Хороший!
ETHproductions


3

Пакет Windows, 76 байт

Рекурсивна функція. Називайте це як GCD a bіз назвою файлу 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 байт

pG1$Zm/

Спробуйте в Інтернеті!

Пояснення

Оскільки ми не можемо явно використовувати вбудовану функцію GCD ( Zdв MATL), я скористався тим фактом, що найменший спільний кратний aі bкращий найбільший спільний знаменник aі bдорівнює добутку aі 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

Можна зберегти один байт з двома окремими входами:*1MZm/
Луїс Мендо

3

Ракетка (схема), 44 байти

Реалізація Euclid в ракетці (схема)

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

Редагувати: Не бачив рішення @Numeri lol. Якось ми отримали такий самий код незалежно


Чи працює це в обох?
NoOneIsHere

@NoOneIsHere так, це працює в обох
kronicmage

3

> <> , 32 байти

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

Приймає два значення із стеку та застосовує евклідовий алгоритм для отримання їх GCD.

Ви можете спробувати тут !

Для набагато кращої відповіді в <<>, перегляньте Сока !


1
Я знайшов нову мову сьогодні :)
nsane



2

Дельфи 7, 148

Ну, я думаю, я знайшов нову найгіршу мову для гольфу.

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.

О, я не знаю, що дужка дуже погана для гри в гольф
MickyT

2

Хун, 20 байт

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

-

Хун №2, 39 байт

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

Як не дивно, єдиною реалізацією в stdlib Hoon для GCD є те, що використовується для його криптовалюти RSA, яка також повертає деякі інші значення. Я мушу загорнути його у функцію, яка бере лише dвихід.

Інша реалізація - це лише рекурсивне визначення GCD за замовчуванням.


2

Python 3.5, 70 82 73 байт:

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

У notцьому випадку переконаєтесь, що сума всіх чисел у *argsмодулі iдорівнює нулю.

Крім того, тепер ця лямбда-функція може приймати стільки значень, скільки ви хочете, до тих пір, поки кількість значень >=2, на відміну від gcdфункції математичного модуля. Наприклад, він може приймати значення 2,4,6,8,10і повертати правильний GCD 2.


1
Ви заарештовані за багатокористувацькі імена змінних. (Або аргументи функцій, але все, що завгодно)
CalculatorFeline

2

Рубін, 23 байти

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

пам'ятайте, що блоки рубіну викликаються g [...] або g.call (...), а не g (...)

часткові кредити до voidpigeon


2
Замість g.call(a,b)вас можна використовувати g[a,b]. Замість цього proc{|a,b|можна використовувати ->a,b{.
невдалий

1
Ви також можете зберегти один байт, використовуючи b>0замість цього b<=0і перемикаючи порядок інших операндів.
невдалий

2

АРМ машинного коду, 12 байт:

складання:

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

Наразі це неможливо скласти, але кожна інструкція в ARM займає 4 байти. Можливо, це можна було бити в гольф, використовуючи режим THUMB-2.


Хороша людина, яка займається машинним кодом, отримує від мене серйозні реквізити.
Майк Шланта

Це здається спробою альго Евкліда, використовуючи лише віднімання , але я не думаю, що це працює. Якщо r0 > r1тоді subltнічого не зробиш ( ltприсудок хибний) і bneбуде нескінченним циклом. Я думаю, що вам потрібен своп, якщо ні lt, тож той самий цикл можна робити b-=aабо a-=bяк потрібно. Або заперечення, якщо субпродукція несе (ака позику).
Пітер Кордес

Цей посібник з набору інструкцій ARM фактично використовує алгоритм віднімання GCD як приклад прогнозування. (стор. 25). Вони використовують cmp r0, r1/ subgt r0, r0, r1/ sublt r1, r1, r0/ bne gcd. Це 16B в інструкціях до ARM, можливо, 12 в thumb2 інструкціях?
Пітер Кордес,

1
На x86 я керував 9 байтами за допомогою: sub ecx, eax/ jae .no_swap/ add ecx,eax/ xchg ecx,eax/ jne. Тож замість cmp я просто підмиваю, потім скасовую та міняю місцями, якщо підрядник повинен був піти іншим шляхом. Я це перевірив, і це працює. ( addЧи не буде робити jneвихід в неправильний час, тому що він не може виробляти нуль , якщо один з входів ні дорівнює нулю , щоб почати с, і ми не підтримуємо , що оновлення :. Нам потрібно підтримувати або вхід, рівним нулю: /)
Пітер Кордес

Для Thumb2 є iteвказівка: if-then-else. Повинна бути ідеальною для cmp / sub в одну сторону / sub в інший спосіб.
Пітер Кордес

2

TI-Basic, 10 байт

Prompt A,B:gcd(A,B

Неконкурентований через нове правило, забороняє вбудовані програми gcd


17-байтне рішення без gcd(вбудованого

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

Неконкурентований через нове правило, забороняє вбудовані lcm вбудовані


27 байт рішення без gcd(або lcm(вбудований:

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

35-байт- рекурсивне рішення без gcd(або lcm(вбудованих (потрібно операційну систему 2,53 МП або вище, потрібно назвати prgmG ):

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

Ви б передали аргументи рекурсивному варіанту, як, {A,B}наприклад, це {1071, 462}:prgmGпризведе 21.


Колір мене вразив.
Майк Шланта

Напевно, ви повинні згадати, що останній потрібно зберегти як prgmG.
спагетто


2

Oracle SQL 11.2, 104 118 байт

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


Не працює правильно, якщо один із входів дорівнює нулю.
Єгор Скриптунов

Це мало би заощадити васSELECT MAX(LEVEL)FROM DUAL WHERE MOD(:1,LEVEL)+MOD(:2,LEVEL)=0 CONNECT BY LEVEL<=:1+:2;
MickyT

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.