diff options
-rw-r--r-- | assembler/gcd-x86-solaris.s | 142 | ||||
-rw-r--r-- | gcd-amd64.S (renamed from assembler/gcd-x86_64-linux.s) | 84 | ||||
-rw-r--r-- | gcd-gmp.c | 31 | ||||
-rw-r--r-- | gcd-x86.S (renamed from assembler/gcd-x86-linux.s) | 86 | ||||
-rwxr-xr-x | gcd.apl | 46 | ||||
-rw-r--r-- | gcd.bas | 41 | ||||
-rw-r--r-- | gcd.c | 36 | ||||
-rw-r--r-- | gcd.clj | 2 | ||||
-rw-r--r-- | gcd.cob | 44 | ||||
-rw-r--r-- | gcd.cpp | 89 | ||||
-rw-r--r-- | gcd.cs | 47 | ||||
-rw-r--r-- | gcd.d | 35 | ||||
-rw-r--r-- | gcd.erl | 28 | ||||
-rw-r--r-- | gcd.f90 | 1 | ||||
-rw-r--r-- | gcd.fs | 3 | ||||
-rw-r--r-- | gcd.hs | 13 | ||||
-rw-r--r-- | gcd.java | 53 | ||||
-rw-r--r-- | gcd.lisp | 33 | ||||
-rwxr-xr-x | gcd.lua | 4 | ||||
-rw-r--r-- | gcd.ml | 6 | ||||
-rw-r--r-- | gcd.pas | 6 | ||||
-rw-r--r-- | gcd.pro | 14 | ||||
-rwxr-xr-x | gcd.py | 18 | ||||
-rwxr-xr-x | gcd.rb | 1 | ||||
-rw-r--r-- | gcd.rs | 32 | ||||
-rwxr-xr-x | gcd.sh | 4 |
26 files changed, 522 insertions, 377 deletions
diff --git a/assembler/gcd-x86-solaris.s b/assembler/gcd-x86-solaris.s deleted file mode 100644 index 50a93f2..0000000 --- a/assembler/gcd-x86-solaris.s +++ /dev/null @@ -1,142 +0,0 @@ -# This program is for Solaris 11 on Intel x86 arch (32 bits). -# Written for GNU Assembler (as) with AT&T syntax - -# To make an executable binary: -# gcc -nostdlib gcd-x86-solaris.s -o gcd-x86-solaris -# or -# as gcd-x86-solaris.s -o gcd-x86-solaris.o && \ -# ld gcd-x86-solaris.o -o gcd-x86-solaris - -# On 64 bits system: -# gcc -m32 -nostdlib gcd-x86-solaris.s -o gcd-x86-solaris -# or -# as --32 gcd-x86-solaris.s -o gcd-x86-solaris.o && \ -# ld -melf_i386 gcd-x86-solaris.o -o gcd-x86-solaris -# -# To run: -# ./gcd-x86-solaris 11 22 33 121 792 -# (output should be 11) - - -.data - -# Buffer for output: -buffer: - .space 32 # enough for 32 bits integer -buf_end: - .byte 10 # new line - - -.text -.globl _start - - -# GCD of two numbers. -# input: eax, ebx - two numbers -# output: eax - GCD -# uses: eax, ebx, edx -gcd2: - and %ebx, %ebx # is %ebx == 0 ? - jz gcd2_exit # %ebx == 0, go to exit and return %eax (GCD) - xor %edx, %edx # set %edx = 0 */ - div %ebx # divide: %edx:%eax / %ebx, actually: %eax / %ebx - mov %ebx, %eax # drop quotient in %eax and keep previous %ebx in %eax - mov %edx, %ebx # put remainder in %ebx - jmp gcd2 -gcd2_exit: - ret - - - -# Print an unsigned integer in eax. -# input: eax - unsigned integer to print -# uses: eax, ebx, ecx, edx, edi, buffer -print: - mov $10, %ecx # set %ecx = 10 (radix) - mov $buf_end, %edi - -next_digit: - xor %edx, %edx # set %edx = 0 - div %ecx # divide: %edx:%eax / %ecx, actually: %eax / %ecx - # %edx is a remainder (0-9), it fits into %dl - add $48, %dl # get ASCII code: 0 => 48 = '0', 1 => 49 = '1' - dec %edi # put remainders going from the end of the buffer - mov %dl, (%edi) - # now eax is a quotient - and %eax, %eax # is quotient == 0 ? - jnz next_digit # quotient is not 0, go on - - # printing the number: - mov $4, %eax # syscall `write' - mov $buf_end, %edx - sub %edi, %edx # edx is a number of characters to write (buf_end - edi) - inc %edx # + new line - push %edx - push %edi # first character to write - push $1 # write to stdout - push $0 # dummy - int $0x91 # do syscall (print the number) - add $16, %esp # clean stack 16 = 4 pushs * 4 bytes (32 bits!) - - ret - - -# Convert string into unsigned integer -# input: esi - pointer to string -# output: ebx - unsigned integer -# uses: eax, ebx, ecx, edi, direction flag -str2uint: - xor %ecx, %ecx # it will be the string length - dec %ecx # ecx = -1 != 0 for repne - xor %eax, %eax # search for 0 (%eax = %al = 0) - mov %esi, %edi - cld # Search forward (std - backward) - repne scasb # search for 0 (in %al), incrementing edi, decrementing ecx - not %ecx # invert ecx to have the string length - dec %ecx # minus ending zero - - xor %ebx, %ebx -str2uint_loop: - lodsb # going forward from esi - # HINT: assert '0' <= al <= '9' - lea (%ebx, %ebx, 4), %ebx # ebx = 4*ebx + ebx = 5*ebx ;-) - lea -48(%eax, %ebx, 2), %ebx # ebx = 2*ebx + %eax - 48 - # ebx is multiplied by 10 each iteration, - # eax-48 will be multiplied at the next iteration ;-) - loop str2uint_loop - ret - - - -# Entry point for the program -_start: - - # Access command line, see: - # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html - # Example: ./gcd-x86-solaris 11 22 33 - pop %ecx # Get the number of command-line options (4) - pop %esi # Get the pointer to the program name (./gcd-x86-solaris), - dec %ecx # minus program name - jz exit # no arguments are given - exiting - - xor %eax, %eax -gcd_loop: - pop %esi # get next command line argument - # Well, we used all registers, now we DO NEED stack :-) - push %ecx # save argument counter - push %eax # save current GCD - call str2uint # convert string at esi to integer at ebx - pop %eax # restore current GCD - call gcd2 # gcd of eax and ebx (returned by str2uint) - # now eax is a GCD - pop %ecx # restore argument counter - loop gcd_loop - - call print # print eax with GCD - -exit: - mov $1, %eax # exit syscall - push $0 # exit code = 0 - push $0 # dummy - int $0x91 - diff --git a/assembler/gcd-x86_64-linux.s b/gcd-amd64.S index cc85933..16be38f 100644 --- a/assembler/gcd-x86_64-linux.s +++ b/gcd-amd64.S @@ -1,18 +1,36 @@ -# This program is for Linux on Intel x86_64 arch (64 bits). +# This program is for amd64 arch (64 bits) running Linux, Solaris or FreeBSD. # Written for GNU Assembler (as) with AT&T syntax - -# To make an executable binary: -# gcc -nostdlib gcd-x86_64-linux.s -o gcd-x86_64-linux +# +# Synopsis: +# +# $ gcc -nostdlib [-D OS=LINUX] gcd-amd64.S -o gcd-amd64-linux +# or +# $ cpp [-D OS=LINUX] gcd-amd64.S | as -o gcd-amd64-linux.o \ +# && ld gcd-amd64-linux.o -o gcd-amd64-linux +# +# +# $ gcc -nostdlib -D OS=SOLARIS gcd-amd64.S -o gcd-amd64-solaris # or -# as gcd-x86_64-linux.s -o gcd-x86_64-linux.o && \ -# ld gcd-x86_64-linux.o -o gcd-x86_64-linux +# $ cpp -D OS=SOLARIS gcd-amd64.S | gas -64 -o gcd-amd64-solaris.o \ +# && gld -m elf_x86_64_sol2 gcd-amd64-solaris.o -o gcd-amd64-solaris +# +# $ clang -nostdlib -D OS=FREEBSD gcd-amd64.S -o gcd-amd64-freebsd +# + +#define LINUX 1 +#define SOLARIS 2 +#define FREEBSD 3 + +#ifndef OS +#define OS LINUX +#endif .data # Buffer for output: buffer: - .space 64 # enough for 64 bits integer + .space 64 # enough for a 64-bit integer buf_end: .byte 10 # new line @@ -28,7 +46,7 @@ buf_end: gcd2: and %rbx, %rbx # is %rbx == 0 ? jz gcd2_exit # %rbx == 0, go to exit and return %rax (GCD) - xor %rdx, %rdx # set %rdx = 0 */ + xor %rdx, %rdx # set %rdx = 0 div %rbx # divide: %rdx:%rax / %rbx, actually: %rax / %rbx mov %rbx, %rax # drop quotient in %rax and keep prrvious %rbx in %rax mov %rdx, %rbx # put remainder in %rbx @@ -43,28 +61,34 @@ gcd2_exit: # uses: rax, rbx, rcx, rdx, rdi, buffer print: mov $10, %rcx # set %rcx = 10 (radix) - mov $buf_end, %rdi + mov $buf_end, %rsi next_digit: xor %rdx, %rdx # set %rdx = 0 div %rcx # divide: %rdx:%rax / %rcx, actually: %rax / %rcx # %rdx is a remainder (0-9), it fits into %dl add $48, %dl # get ASCII code: 0 => 48 = '0', 1 => 49 = '1' - dec %rdi # put remainders going from the end of the buffer - mov %dl, (%rdi) + dec %rsi # put remainders going from the end of the buffer + mov %dl, (%rsi) # now rax is a quotient and %rax, %rax # is quotient == 0 ? jnz next_digit # quotient is not 0, go on - + # printing the number: - mov $4, %rax # syscall `write' - mov $1, %rbx # write to stdout - mov %rdi, %rcx # first character to write +#if OS == LINUX + mov $1, %rax # syscall `write' +#elif OS == SOLARIS + mov $4, %rax # syscall `write' +#elif OS == FREEBSD + mov $4, %rax # syscall `write' +#else +#error bad OS. +#endif + mov $1, %rdi # write to stdout mov $buf_end, %rdx - sub %rdi, %rdx # rdx is a number of characters to write (buf_end - rdi) + sub %rsi, %rdx # rdx is a number of characters to write (buf_end - rsi) inc %rdx # + new line - int $0x80 # do syscall (print the number) - + syscall # do syscall (print the number at rsi) ret @@ -98,11 +122,13 @@ str2uint_loop: # Entry point for the program _start: - # Access command line, see: - # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html - # Example: ./gcd-x86_64-linux 11 22 33 + # Access command line. + # Example: ./gcd-amd64-linux 11 22 33 +#if OS == FREEBSD + mov %rdi, %rsp +#endif pop %rcx # Get the number of command-line options (4) - pop %rsi # Get the pointer to the program name (./gcd-x86_64-linux), + pop %rsi # Get the pointer to the program name (./gcd-amd64-linux), dec %rcx # minus program name jz exit # no arguments are given - exiting @@ -121,7 +147,15 @@ gcd_loop: call print # print rax with GCD exit: - mov $1, %rax # exit syscall - xor %rbx, %rbx # exit code = 0 - int $0x80 +#if OS == LINUX + mov $60, %rax # exit syscall +#elif OS == SOLARIS + mov $1, %rax # exit syscall +#elif OS == FREEBSD + mov $1, %rax # exit syscall +#else +#error bad OS. +#endif + xor %rdi, %rdi # exit code = 0 + syscall @@ -45,25 +45,22 @@ main (int argc, char *argv[]) if (argc > 1) { n = argc - 1; - a = malloc (sizeof (mpz_t) * n); - if (NULL != a) - { - for (i = 1; i <= n; i++) - mpz_init_set_str (a[i - 1], argv[i], 10); + a = (mpz_t *) malloc (n * sizeof (mpz_t)); + if (!a) + return EXIT_FAILURE; - mpz_init (g); - gcdn (g, a, n); - mpz_out_str (NULL, 10, g); - printf ("\n"); + for (i = 1; i <= n; i++) + mpz_init_set_str (a[i - 1], argv[i], 10); - /* No need actually before exit */ - mpz_clear (g); - for (i = 1; i <= n; i++) - mpz_clear (a[i - 1]); - free (a); - return EXIT_SUCCESS; - } - return EXIT_FAILURE; + mpz_init (g); + gcdn (g, a, n); + mpz_out_str (NULL, 10, g); + printf ("\n"); + + mpz_clear (g); + for (i = 1; i <= n; i++) + mpz_clear (a[i - 1]); + free (a); } return EXIT_SUCCESS; } diff --git a/assembler/gcd-x86-linux.s b/gcd-x86.S index aa46fd3..c8d6c79 100644 --- a/assembler/gcd-x86-linux.s +++ b/gcd-x86.S @@ -1,28 +1,36 @@ -# This program is for Linux on Intel x86 arch (32 bits). +# This program is for Intel x86 arch (32 bits) running Linux, Solaris or FreeBSD. # Written for GNU Assembler (as) with AT&T syntax - -# To make an executable binary: -# gcc -nostdlib gcd-x86-linux.s -o gcd-x86-linux +# +# Synopsis: +# +# $ gcc -nostdlib -m32 [-D OS=LINUX] gcd-x86.S -o gcd-x86-linux # or -# as gcd-x86-linux.s -o gcd-x86-linux.o && \ -# ld gcd-x86-linux.o -o gcd-x86-linux - -# On 64 bits system: -# gcc -m32 -nostdlib gcd-x86-linux.s -o gcd-x86-linux +# $ cpp [-D OS=LINUX] gcd-x86.S | as -32 -o gcd-x86-linux.o \ +# && ld -m elf_i386 gcd-x86-linux.o -o gcd-x86-linux +# +# +# $ gcc -nostdlib -m32 -D OS=SOLARIS gcd-x86.S -o gcd-x86-solaris # or -# as --32 gcd-x86-linux.s -o gcd-x86-linux.o && \ -# ld -melf_i386 gcd-x86-linux.o -o gcd-x86-linux +# $ cpp -D OS=SOLARIS gcd-x86.S | gas -32 -o gcd-x86-solaris.o \ +# && gld -m elf_i386_sol2 gcd-x86-solaris.o -o gcd-x86-solaris # -# To run: -# ./gcd-x86-linux 11 22 33 121 792 -# (output should be 11) +# +# $ clang -nostdlib -m32 -D OS=FREEBSD gcd-x86.S -o gcd-x86-freebsd +# + +#define LINUX 1 +#define SOLARIS 2 +#define FREEBSD 3 +#ifndef OS +#define OS LINUX +#endif .data # Buffer for output: buffer: - .space 32 # enough for 32 bits integer + .space 32 # enough for a 32-bit integer buf_end: .byte 10 # new line @@ -38,7 +46,7 @@ buf_end: gcd2: and %ebx, %ebx # is %ebx == 0 ? jz gcd2_exit # %ebx == 0, go to exit and return %eax (GCD) - xor %edx, %edx # set %edx = 0 */ + xor %edx, %edx # set %edx = 0 div %ebx # divide: %edx:%eax / %ebx, actually: %eax / %ebx mov %ebx, %eax # drop quotient in %eax and keep previous %ebx in %eax mov %edx, %ebx # put remainder in %ebx @@ -65,16 +73,35 @@ next_digit: # now eax is a quotient and %eax, %eax # is quotient == 0 ? jnz next_digit # quotient is not 0, go on - + # printing the number: - mov $4, %eax # syscall `write' - mov $1, %ebx # write to stdout - mov %edi, %ecx # first character to write mov $buf_end, %edx sub %edi, %edx # edx is a number of characters to write (buf_end - edi) inc %edx # + new line +#if OS == LINUX + mov $4, %eax # syscall `write' + mov $1, %ebx # write to stdout + mov %edi, %ecx # first character to write int $0x80 # do syscall (print the number) - +#elif OS == SOLARIS + mov $4, %eax # syscall `write' + push %edx + push %edi # first character to write + push $1 # write to stdout + push $0 # dummy + int $0x91 # do syscall (print the number) + add $16, %esp # clean stack 16 = 4 pushs * 4 bytes (32 bits!) +#elif OS == FREEBSD + mov $4, %eax # syscall `write' + push %edx + push %edi # first character to write + push $1 # write to stdout + push $0 # dummy + int $0x80 # do syscall (print the number) + add $16, %esp # clean stack 16 = 4 pushs * 4 bytes (32 bits!) +#else +#error bad OS. +#endif ret @@ -108,8 +135,7 @@ str2uint_loop: # Entry point for the program _start: - # Access command line, see: - # http://www.cin.ufpe.br/~if817/arquivos/asmtut/index.html + # Access command line. # Example: ./gcd-x86-linux 11 22 33 pop %ecx # Get the number of command-line options (4) pop %esi # Get the pointer to the program name (./gcd-x86-linux), @@ -132,7 +158,21 @@ gcd_loop: call print # print eax with GCD exit: +#if OS == LINUX mov $1, %eax # exit syscall xor %ebx, %ebx # exit code = 0 int $0x80 +#elif OS == SOLARIS + mov $1, %eax # exit syscall + push $0 # exit code = 0 + push $0 # dummy + int $0x91 +#elif OS == FREEBSD + mov $1, %eax # exit syscall + push $0 # exit code = 0 + push $0 # dummy + int $0x80 +#else +#error bad OS. +#endif @@ -0,0 +1,46 @@ +#!/usr/bin/apl --script +⍝ +⍝ Tested with GNU APL 1.8 (2022-10-25) +⍝ +⍝ Synopsis: +⍝ $ ./gcd.apl -- 11 22 121 +⍝ or: +⍝ $ apl --script [-f] gcd.apl -- 11 22 121 +⍝ +⍝ One-liner, where "∨" is APL's built-in GCD: +⍝ $ apl --eval "∨/⍎¨(↑⍸{'--'≡⍵}¨a)↓a←⎕ARG" -- 11 22 121 +⍝ + +⍝ Function to get the script arguments, +⍝ that is everything after '--': +∇ r ← sargs; a + a ← ⎕ARG + r ← (↑⍸{'--'≡⍵}¨a)↓a +∇ + +⍝ Function to calculate the GCD of two numbers: +∇ r ← a gcd2 b +T: →(b=0)/E ⋄ (a b) ← b (b|a) ⋄ →T +E: r ← a +∇ + +⍝ Recursive version: +⍝ ∇ r ← a gcd2 b +⍝ r ← a +⍝ →(b=0)/0 +⍝ r ← b gcd2 b|a +⍝ ∇ + +⍝ Function (lambda) to calculate the GCD of several numbers: +gcdn ← {gcd2/⍵} + +∇ main; a + a ← sargs ⍝ Get script arguments + →(0=≢a)⍴0 ⍝ Exit the function if no arguments + ⎕ ← gcdn⍎¨a ⍝ Convert strings to numbers, calculate and print GCD +∇ + +main + +)OFF + @@ -0,0 +1,41 @@ +' Tested with FreeBASIC 1.10.0 +' +' Synopsis: +' $ fbc -x gcd-bas gcd.bas +' $ ./gcd-bas 11 22 33 121 +' + +FUNCTION gcd2 (BYVAL a AS ULONGINT, BYVAL b AS ULONGINT) AS ULONGINT + DIM c AS ULONGINT + DO WHILE (b > 0) + c = b + b = a MOD b + a = c + LOOP + RETURN a +END FUNCTION + + +FUNCTION gcdn (nums() AS ULONGINT) AS ULONGINT + DIM gcd AS ULONGINT = nums(LBOUND(nums)) + FOR i AS INTEGER = LBOUND(nums) + 1 TO UBOUND(nums) + gcd = gcd2(gcd, nums(i)) + NEXT + RETURN gcd +END FUNCTION + + +DIM argc AS INTEGER = 0 +DO WHILE (LEN(COMMAND(argc + 1)) > 0) + argc += 1 +LOOP + +IF argc = 0 THEN STOP + +DIM nums(argc) AS ULONGINT +FOR i AS INTEGER = 1 TO argc + nums(i) = VALULNG(COMMAND(i)) +NEXT + +PRINT gcdn(nums()) + @@ -1,10 +1,10 @@ #include <stdlib.h> #include <stdio.h> -static unsigned long int -gcd2 (unsigned long int a, unsigned long int b) +static unsigned long +gcd2 (unsigned long a, unsigned long b) { - unsigned long int c; + unsigned long c; while (b != 0) { c = b; @@ -14,16 +14,14 @@ gcd2 (unsigned long int a, unsigned long int b) return a; } -static unsigned long int -gcdn (unsigned long int *a, size_t n) +static unsigned long +gcdn (const unsigned long *a, size_t n) { - unsigned long int r; + unsigned long r; size_t i; r = a[0]; for (i = 1; i < n; i++) - { - r = gcd2 (r, a[i]); - } + r = gcd2 (r, a[i]); return r; } @@ -31,22 +29,20 @@ gcdn (unsigned long int *a, size_t n) int main (int argc, char *argv[]) { - unsigned long int *a; + unsigned long *a; size_t i, n; if (argc > 1) { n = (size_t) (argc - 1); - a = (unsigned long int *) malloc (sizeof (unsigned long int) * n); - if (NULL != a) - { - for (i = 1; i <= n; i++) - a[i - 1] = strtoul (argv[i], NULL, 10); - printf ("%lu\n", gcdn (a, n)); - free (a); - return EXIT_SUCCESS; - } - return EXIT_FAILURE; + a = (unsigned long *) malloc (n * sizeof (unsigned long)); + if (!a) + return EXIT_FAILURE; + + for (i = 1; i <= n; i++) + a[i - 1] = strtoul (argv[i], NULL, 10); + printf ("%lu\n", gcdn (a, n)); + free (a); } return EXIT_SUCCESS; } @@ -12,7 +12,7 @@ (defn gcd2 [a b] (if (zero? b) a - (gcd2 b (mod a b)))) + (recur b (mod a b)))) (defn gcdn [aa] (reduce gcd2 aa)) @@ -0,0 +1,44 @@ + * Tested with GNU COBOL 4 + * + * Synopsis: + * + * $ cobc -x gcd.cob -o gcd-cob + * $ ./gcd-cob 11 22 33 121 + * + IDENTIFICATION DIVISION. + PROGRAM-ID. GCD. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 WS-COUNT PIC 9(20). + 01 WS-GCD PIC 9(20). + 01 WS-NUM PIC 9(20). + 01 WS-OUT PIC Z(20). + PROCEDURE DIVISION. + ACCEPT WS-COUNT FROM ARGUMENT-NUMBER. + IF WS-COUNT = 0 STOP RUN. + ACCEPT WS-GCD FROM ARGUMENT-VALUE. + PERFORM WITH TEST BEFORE UNTIL WS-COUNT = 1 + ACCEPT WS-NUM FROM ARGUMENT-VALUE + CALL 'GCD2' USING WS-GCD, WS-NUM + SUBTRACT 1 FROM WS-COUNT + END-PERFORM. + MOVE WS-GCD TO WS-OUT. + DISPLAY FUNCTION TRIM (WS-OUT LEADING). + END PROGRAM GCD. + + IDENTIFICATION DIVISION. + PROGRAM-ID. GCD2. + DATA DIVISION. + WORKING-STORAGE SECTION. + 01 WS-C PIC 9(20). + LINKAGE SECTION. + 01 L-A PIC 9(20). + 01 L-B PIC 9(20). + PROCEDURE DIVISION USING L-A, L-B. + PERFORM WITH TEST BEFORE UNTIL L-B = 0 + MOVE L-B TO WS-C + DIVIDE WS-C INTO L-A GIVING L-A REMAINDER L-B + MOVE WS-C TO L-A + END-PERFORM. + END PROGRAM GCD2. + @@ -7,65 +7,70 @@ * * * To use GNU Multiple Precision Arithmetic Library: - * - * # g++ -o gcd-cpp-gmp -DGMP -lgmpxx -lgmp gcd.cpp + * + * # g++ -DGMP gcd.cpp -lgmpxx -lgmp -o gcd-cpp-gmp * # ./gcd-cpp-gmp 1234567890987654321 987654321234567 * # 63 * */ - #include <cstdlib> #include <iostream> -#include <vector> #include <sstream> - -using namespace std; +#include <vector> +#if __cplusplus >= 201703L +#include <execution> +#include <numeric> +#endif #ifdef GMP - #include <gmpxx.h> - typedef mpz_class Number; +#include <gmpxx.h> +typedef mpz_class Number; #else - typedef unsigned int Number; -#endif // GMP +typedef unsigned long Number; +#endif -typedef vector<Number> Numbers; +using std::vector; -Number gcd(Number a, Number b) -{ - Number c; - while (b != 0) { - c = b; - b = a % b; - a = c; - } - return a; +template <class N> N gcd2(N a, N b) { + while (b != 0) { + N c = b; + b = a % b; + a = c; + } + return a; } -Number gcd(const Numbers & ns) -{ - Number r = 0; - for(Numbers::const_iterator n = ns.begin(); n != ns.end(); ++n) - r = gcd(*n, r); - return r; +#if __cplusplus >= 201703L +template <class N> class GCD { +public: + N operator()(N a, N b) const { return gcd2(a, b); }; +}; + +template <class N> N gcd(const vector<N> &ns) { + GCD<N> GCD; + return reduce(std::execution::par, begin(ns), end(ns), N(0), GCD); } +#else -int main (int argc, char *argv[]) -{ - if (argc > 1) { - Numbers ns(argc - 1); - for(int n = 1; n < argc; ++n) { - stringstream str; - str << argv[n]; - str >> ns[n-1]; - /* NOTE: - * For GMP we can just assign: ns[n-1] = argv[n], - * and sstream is not needed. - */ - } - cout << gcd(ns) << endl; - } - return EXIT_SUCCESS; +template <class N> N gcd(const vector<N> &ns) { + N r = 0; + for (typename vector<N>::const_iterator n = ns.begin(); n != ns.end(); ++n) + r = gcd2(*n, r); + return r; } +#endif +int main(int argc, char *argv[]) { + if (argc > 1) { + vector<Number> ns(argc - 1); + for (int n = 1; n < argc; ++n) { + std::stringstream str; + str << argv[n]; + str >> ns[n - 1]; + } + std::cout << gcd(ns) << std::endl; + } + return EXIT_SUCCESS; +} @@ -1,32 +1,27 @@ using System; +using System.Linq; -namespace GCD { - class Program { - static uint gcd2(uint a, uint b) { - uint c; - while (b != 0) { - c = b; - b = a % b; - a = c; - } - return a; - } +class Program { + static ulong gcd2(ulong a, ulong b) { + ulong c; + while (b != 0) { + c = b; + b = a % b; + a = c; + } + return a; + } - static uint gcdn(uint [] n) { - uint r = n[0]; - for (int i = 1; i < n.Length; i++) - r = gcd2(r, n[i]); - return r; - } + static ulong gcdn(ulong[] nums) { + return nums.Aggregate(0UL, (gcd, n) => gcd2(gcd, n)); + } - static void Main(string [] argv) { - uint [] a = Array.ConvertAll<string, uint>(argv, - new Converter<string, uint> - (delegate(string s) {return uint.Parse(s);}) - ); + static void Main(string[] argv) { + ulong[] nums = Array.ConvertAll<string, ulong>( + argv, new Converter<string, ulong>( + delegate(string s) { return ulong.Parse(s); })); - Console.WriteLine("{0}", gcdn(a)); - } - } + if (nums.Length > 0) + Console.WriteLine("{0}", gcdn(nums)); + } } - @@ -0,0 +1,35 @@ +// D: https://dlang.org +// +// Synopsis: +// +// GNU D Compiler (tested GCC 12): +// $ gdc gcd.d -o gcd-d +// $ ./gcd-d 11 22 33 121 +// +// LLVM D Compiler (tested LDC2 1.24.0): +// $ ldc2 --run gcd 11 22 33 121 +// or +// $ ldc2 --of=gcd-d gcd.d +// $ ./gcd-d 11 22 33 121 +// + +import std.algorithm: map, reduce; +import std.conv: to; +import std.stdio: writeln; + +ulong gcd2(ulong a, ulong b) { + ulong c; + while (b > 0) { + c = b; + b = a % b; + a = c; + } + return c; +} + +void main(string[] args) { + if (args.length > 1) { + auto gcd = args[1..$].map!(to!ulong).reduce!gcd2(); + writeln(gcd); + } +} @@ -0,0 +1,28 @@ +% Synopsis: +% +% $ escript gcd.erl 11 22 33 121 +% +% or +% +% $ erl -compile gcd / erlc gcd.erl +% $ erl -noshell -run gcd main 11 22 33 121 +% + +-module(gcd). +-export([main/1, main/0]). +-mode(compile). + +gcd2(A, 0) -> A; +gcd2(A, B) -> gcd2(B, A rem B). + +gcdn(Nums) -> + lists:foldl(fun gcd2/2, 0, Nums). + +main() -> init:stop(). + +main([]) -> init:stop(); +main(Args) -> + Nums = lists:map(fun erlang:list_to_integer/1, Args), + io:format("~w\n", [gcdn(Nums)]), + init:stop(). + @@ -12,6 +12,7 @@ program GCD character(len=20) :: tmpstr n = command_argument_count() + if (n == 0) stop allocate (ns(n)) @@ -30,7 +30,8 @@ r> 1 + >r repeat 2drop - r> gcdn . cr + r> + dup 0 <> if gcdn . cr else drop endif ; main bye @@ -14,17 +14,16 @@ or: -} import System.Environment (getArgs) -gcd2 :: Integer -> Integer -> Integer +gcd2 :: Integral a => a -> a -> a gcd2 a 0 = a gcd2 a b = gcd2 b (a `rem` b) -gcdn :: [Integer] -> Integer +gcdn :: Integral a => [a] -> a gcdn = foldl1 gcd2 -str2int :: String -> Integer -str2int = read +out :: [String] -> IO () +out [] = return () +out a = print (gcdn (map read a) :: Integer) main :: IO () -main = do - a <- getArgs - print $ gcdn (map str2int a) +main = getArgs >>= out @@ -1,41 +1,38 @@ /* * SYNOPSIS: * - * # gcj -o gcd --main=gcd gcd.java - * # ./gcd 11 22 33 44 121 - * * # javac gcd.java * # java gcd 11 22 33 * */ -public class gcd -{ - public static int gcd2(int a, int b) { - int c; - while (b != 0) { - c = b; - b = a % b; - a = c; - } - return a; +public class gcd { + public static long gcd2(long a, long b) { + long c; + while (b != 0) { + c = b; + b = a % b; + a = c; } + return a; + } - public static int gcdn(int [] a) { - int r = a[0]; - for (int i = 1; i < a.length; i++) - r = gcd2(r, a[i]); - return r; - } + public static long gcdn(long[] a) { + long r = a[0]; + for (int i = 1; i < a.length; i++) + r = gcd2(r, a[i]); + return r; + } + + public static void main(String[] argv) { + if (argv.length == 0) + return; - public static void main(String [] argv) { - if (argv.length == 0) - return; - int [] n = new int [argv.length]; - for (int i = 0; i < argv.length; i++) { - n[i] = Integer.parseInt(argv[i]); - } - System.out.println(gcdn(n)); + long[] n = new long[argv.length]; + for (int i = 0; i < argv.length; i++) { + n[i] = Long.parseLong(argv[i]); } -} + System.out.println(gcdn(n)); + } +} @@ -1,29 +1,30 @@ ; SYNOPSIS: ; # clisp gcd.lisp 11 22 33 121 +; # ecl --shell gcd.lisp 121 22 33 +; # gcl -f gcd.lisp 121 22 33 ; # sbcl --script gcd.lisp 121 22 33 -; (defun gcd2 (a b) - (if (= b 0) - a - (gcd2 b (mod a b)))) + (loop while (/= b 0) do + (psetq a b b (mod a b)) + finally (return a))) -(defun gcdn (&rest numbers) - (reduce #'gcd2 (rest numbers) - :initial-value (first numbers))) +(defun gcdn (n &rest ns) + (reduce #'gcd2 ns :initial-value n)) -; Command line access is different on different Lisps (defun program-args () (or - #+SBCL (rest *posix-argv*) #+CLISP *args* - ;#+ECL (ext:command-args) - ;#+CMU extensions:*command-line-words* - ;#+LISPWORKS system:*line-arguments-list* + #+ECL (cdr ext:*unprocessed-ecl-command-args*) + #+GCL (cdr si::*command-args*) + #+SBCL (cdr *posix-argv*) nil)) -(write (apply #'gcdn - (map 'list #'parse-integer (program-args)) - )) -(fresh-line) +(defun numbers () + (mapcar #'parse-integer (program-args))) + +(let ((ns (numbers))) + (when ns + (write (apply #'gcdn ns)) + (fresh-line))) @@ -21,5 +21,7 @@ function gcdn(ns) return r end -print(gcdn(arg)) +if #arg ~= 0 then + print(gcdn(arg)) +end @@ -27,7 +27,9 @@ let rec gcd a b = let gcdn = List.fold_left gcd 0 ;; let args = List.tl (Array.to_list Sys.argv) ;; -let nums = List.map int_of_string args ;; -Printf.printf "%d\n" (gcdn nums) ;; +if args <> [] then begin + let nums = List.map int_of_string args + in Printf.printf "%d\n" (gcdn nums) +end ;; @@ -1,6 +1,6 @@ { FreePascal: https://www.freepascal.org/ -Tested with FreePascal 2.4.0, 3.0.0 +Tested with FreePascal 3.2 Usage: @@ -39,8 +39,12 @@ Var n: array Of integer; i: integer; Begin + If ParamCount = 0 then exit; + SetLength(n, ParamCount); + For i := 1 To ParamCount Do n[i-1] := StrToInt(ParamStr(i)); + Writeln(gcdn(n)) End. @@ -2,12 +2,10 @@ % % Tested with GNU Prolog 1.3.1 % -% # gplc --no-top-level gcd.pro -% # ./gcd 22 33 44 121 +% # gplc --no-top-level -o gcd-pro gcd.pro +% # ./gcd-pro 22 33 44 121 -% 1st number, 2nd number, GCD - % It is true that GCD of A and 0 is A % (The fact is GCD of A and 0 is A) gcd2(A, 0, A). @@ -20,14 +18,18 @@ gcdn(A, [], A). gcdn(A, [B|Bs], G) :- gcd2(A, B, N), gcdn(N, Bs, G). gcdn([A|As], G) :- gcdn(A, As, G). -:- initialization(main). - str2int([], []). str2int([S|St], [N|Nt]) :- number_atom(N, S), str2int(St, Nt). +not_empty([]) :- halt. +not_empty(_). + main :- argument_list(Args), + not_empty(Args), str2int(Args, Numbers), gcdn(Numbers, G), write(G), nl. +:- initialization(main). + @@ -3,16 +3,16 @@ import sys import functools + def gcd2(a, b): - if b == 0: - return a - else: - return gcd2(b, a % b) + while b != 0: + a, b = b, a % b + return a + -def gcdn(ns): - return functools.reduce(gcd2, ns) +def gcdn(nums): + return functools.reduce(gcd2, nums) -ints = map(int, sys.argv[1:]) -gcd = gcdn(ints) -print(gcd) +if len(sys.argv) > 1: + print(gcdn(map(int, sys.argv[1:]))) @@ -8,7 +8,6 @@ def gcd2 a, b end end -# http://railspikes.com/2008/8/11/understanding-map-and-reduce def gcdn ns ns.reduce{ |a, b| gcd2 a, b } end @@ -1,7 +1,17 @@ -use std::env; +// Synopsis: +// +// $ rustc gcd.rs -o gcd-rs +// $ ./gcd-rs 11 22 33 121 +// 11 +// -fn gcd2(mut a: u64, mut b: u64) -> u64 { - while b != 0 { +use std::{cmp, env, ops}; + +fn gcd2<T>(mut a: T, mut b: T) -> T +where + T: cmp::PartialEq + Copy + ops::Rem<Output = T> + ops::Neg<Output = T>, +{ + while b != -b { let c = b; b = a % b; a = c; @@ -10,11 +20,17 @@ fn gcd2(mut a: u64, mut b: u64) -> u64 { a } -fn main() { - // XXX skip(1) to skip program name: - let nums = env::args().skip(1).map(|s| s.parse().unwrap()); +fn gcdn<T>(nums: impl IntoIterator<Item = T>) -> Option<T> +where + T: cmp::PartialEq + Copy + ops::Rem<Output = T> + ops::Neg<Output = T>, +{ + nums.into_iter().reduce(gcd2) +} - let gcd = nums.fold(0, gcd2); +fn main() { + let nums = env::args().skip(1).map(|s| s.parse::<i64>().unwrap()); - println!("{}", gcd); + if let Some(gcd) = gcdn(nums) { + println!("{gcd}"); + } } @@ -16,5 +16,7 @@ gcdn() { echo $r } -gcdn $* +if test $# -gt 0 ; then + gcdn $* +fi |