싸고 빠르며 좋다-공통 요소 (최고) [닫힘]


10

Cheap, Fast, Good 에서 영감을 얻어 정확히 두 가지 알고리즘을 구현할 것입니다.

수학

두 개의 0이 아닌 정수 a 와 b가 주어지면 GCF d 는 a 와 b 를 나머지없이 나누는 가장 큰 정수입니다 . 베즈 아웃 계수 는 ax + by = d 와 같은 정수 쌍 (x, y) 입니다. 베즈 아웃 계수는 고유하지 않습니다. 예를 들면 다음과 같습니다.

a = 15, b = 9

우리는

d =  3
x =  2
y = -3

이후 15*2 + 9*(-3) = 30 - 27 = 3.

GCF와 Bézout 계수 쌍을 계산하는 일반적인 방법은 Euclid 's Algorithm 을 사용하는 것이지만 결코 유일한 방법은 아닙니다.

코드

프로그램은 두 개의 정수를 입력으로 사용해야합니다. 가장 큰 공약수와 한 쌍의 Bézout 계수를 출력 / 반환해야합니다.

입력 예 :

15 9

예제 출력

3 (2, -3)

출력은 어떤 순서와 형식으로도 가능하지만 어느 것이 GCF이고 어떤 계수인지는 분명해야합니다.

언더 핸드

귀하의 프로그램은 저렴하고 빠르며 좋습니다. 불행히도 한 번에 두 개만 될 수 있습니다.

  • 저렴 하지 않은 경우 프로그램은 과도한 양의 시스템 리소스를 사용해야합니다.
  • 빠르지 않으면 프로그램에 시간이 오래 걸립니다.
  • 좋지 않으면 프로그램 출력이 잘못되어야합니다.

이 프로그램은 세 가지를 모두 수행 할 수 있어야합니다. 시간, 컴파일러, 입력이 큰 등을 기반으로 할 수 있습니다. 몇 가지 추가 참고 사항 :

  • 귀하의 프로그램은 명백하게 처리되어서는 안되며, 철저한 검사를 통과해야합니다. 세 개의 별도 알고리즘을 구현하면 조금 의심 스러울 것입니다.
  • 에서 싼 경우, "시스템 자원의 과도한 양의는"다른 프로그램을 느리게 할 수있는 모든 작업입니다. 메모리, 대역폭 등일 수 있습니다.
  • 에서 빠른 경우, "과도한 시간"가에서 실행하는 방법에 비해 의미 저렴 하고 좋은 경우. 프로그램은 여전히 ​​완료되어야합니다. "놀랍게도 실망 스럽지만 프로그램을 중지 할만큼 좌절하지는 않습니다."
  • 에서 좋은 경우, 출력은 분명히 잘못 안되며, 피상적 인 검사를 통과해야한다. 그것이 "2 anna half"의 GCF를 주었다면 나는 매우 의심 스러울 것이다.

이것은 인기 콘테스트이므로 대부분의 공감대가 승리합니다!

편집하다

명확히하기 위해, 나는 단지 그들 중 하나를 수행하는 것이 아니라 다른 경우에 "빠르고 저렴" 하고 "싸고 좋은" 그리고 "빠르고 좋은" 프로그램을 찾고 있습니다.


1
이와 같은 독창적 인 도전을하는 것이 좋습니다. :)
— Ypnypn

프로그램이 한 번에 정확히 두 개 여야합니까, 아니면 어떤 경우에만 좋고 다른 경우에는 싸고 빠르지 만 (좋지 않은 경우) 괜찮습니까?
— 데니스

1
정확히 두 개씩 세 가지 경우를 찾고 있습니다.
— Hovercouch 2016 년

프로그램이 좋지 않으면 출력이 정확하지 않습니까? 그렇다면 올바르게 계산하는 요점은 무엇입니까?
— Ricardo A

4
나는이 질문을 1 년 전에 주제에 대한 논란이 있었지만 이제는 지역 사회의 합의에 의한 주제가 아니기 때문에 주제를 논외 주제로 폐쇄하기로 투표하고 있습니다.
— James

답변:


2

씨

싸고 빠릅니다. 눈이 깜박이면 gcd가 나타납니다. 그러나 그것을 한 사람은 "Bézier co-something"에 대한 단서가 없었기 때문에 단순히 a와 b를 gcd로 나누었습니다. (문제를 악화시키기 위해, 그 시점에서 a와 b는 현명하게 선택한 알고리즘 때문에 초기 값과는 거리가 멀다)

int main(int argc, char **argv){
    unsigned int a, b, tmp;
    a = (unsigned int)atoi(argv[1]);
    b = (unsigned int)atoi(argv[2]);
    for (tmp = 0; ((a | b) & 1) == 0; ++tmp){
        a >>= 1;
        b >>= 1;
    }
    while ((a & 1) == 0) 
        a >>= 1;
    do {
        while ((b & 1) == 0)
            b >>= 1;
        if (a > b){
            unsigned int t = b; 
            b = a; 
            a = t;
        }  
        b = b - a;
    } while (b != 0);
    tmp = a << tmp;
    printf("%u, (%u,%u)", tmp, a/tmp, b/tmp);
    return 0;
}

0

씨#

Bézout 계수를 계산합니다. 나는 확장 유클리드 알고리즘을 사용했다 .

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Enter your first number.");
            int firstNumber = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("Enter your second number.");
            int secondNumber = Convert.ToInt32(Console.ReadLine());

            double max = Math.Max(firstNumber, secondNumber);
            double min = Math.Min(firstNumber, secondNumber);
            double s1 = 1;
            double s2 = 0;
            double t1 = 0;
            double t2 = 1;
            double quotient = 0;
            double remainder = 0;
            double[] remainders = new double[0];

            int i = 0;
            do
            {
                quotient = (int)(max / min);
                remainder = max - quotient * min;
                if (remainder > 0)
                {
                    Array.Resize(ref remainders, remainders.Length + 1);
                    remainders[i] = remainder;

                }
                if (i % 2 == 0)
                {
                    s1 = s1 - quotient * s2;
                    t1 = t1 - quotient * t2;
                }
                else
                {
                    s2 = s2 - quotient * s1;
                    t2 = t2 - quotient * t1;
                }

                if (i == 0)
                {
                    max = min;

                }
                else if (i >= 1)
                {
                    max = remainders[i - 1];
                }


                min = remainder;
                i++;
            } while (remainder > 0);

            Console.WriteLine((remainders[remainders.Length - 1]).ToString() + " " + (i % 2 == 0 ? "(" + s1 + "," + t1 + ")" : "(" + s2 + "," + t2 + ")"));
        }

    }
}

언제 비싸고, 느리고 언제 나쁩니 까?
— undergroundmonorail

@undergroundmonorail 나는 기회가있을 때 그 값을 넣을 것입니다.
— 부라 추하다 르

0

펄 5

#!/usr/bin/perl
use strict;
use warnings;

$SIG{__WARN__} = sub { exit };

print(<<INTRO);
Greatest Common Factor

    goodbye           -- exit the application
    [number] [number] -- compute gcf of both numbers

INTRO

main();
sub main {
    print "> ";
    chomp(local $_ = <STDIN>);

    print "Have a good one.\n" and exit if /goodbye/;

    my @nums = /(-?\d+)/g;
    print "invalid input\n" and return main() if @nums != 2;

    my ($gcf, @coeff) = gcf(@nums);
    unless (grep abs($_) > 99, $gcf, @coeff) {
        select $\,$\,$\, rand for 1..10;
    }

    local $" = ", "; #"
    print "gcf(@nums) = $gcf\n";
    print "bezout coefficients: @coeff\n";
    main();
}

sub gcf {
    my ($x, $y) = @_;

    my @r = ($x, $y);
    my @s = (1, 0);
    my @t = (0, 1);

    my $i = 1;
    while ($r[$i] != 0) {
        my $q = int($r[$i-1] / $r[$i]);
        for (\@r, \@s, \@t) {
            $_->[$i+1] = $_->[$i-1] - $q * $_->[$i];
        }
        $i++;
    }

    return map int(1.01 * $_->[$i-1]), \@r, \@s, \@t;
}

__END__

저렴하지는 않습니다 : __WARN__ 핸들러로 인해 응용 프로그램을 종료하는 perl에 의해 "심층 재귀"경고가 발생할 때까지 main ()이 재귀 적으로 호출됩니다 (스택을 채운다).

빠르지 않음 : gcf () 알고리즘이 올바른 결과를 반환하면 코드는 몇 초 동안 정지됩니다 (main ()에서 select ()).

양호하지 않음 : 99 이상 (또는 -99 미만)의 모든 결과가 올바르지 않습니다.

전혀 창의적이지는 않다. 더 우아한 답변을 기대합니다.


0

파이썬

#!/usr/bin/python
def gcd(x, y):
    l = 0
    if x < y:
        l = x
    else:
        l = y
    for g in reversed(range(l + 1)):
        if x%g == 0 and y%g == 0 and g > 1:
            return g
        else:
            if g == 1:
                return 1

def bezout(x,y,g):
    c1 = 0
    c2 = 0
    k = 0
    if x < y:
        k = y
    else:
        k = x
    for _k in range(k):
        tc = (gcd(x,y) - x*_k)%y
        if tc == 0:
            c1 = _k
            c2 = (gcd(x,y) - y*_k)/x
            return (c1, c2)

gc = gcd(15,9)
be, bf = bezout(9,15,gc)
print("%d (%d, %d)" % (gc, be, bf))

이것은 저렴하고 빠르지 만 범위가 가장 큰 입력에서 제한되므로 한 쌍의 계수를 찾지 못할 수도 있습니다.

좋은 퍼즐.


0

자바 스크립트

싸구려

많은 시스템 리소스를 사용합니다.

function gcf(a, b) {
    var result = 1;
    for (var i = 1; i < 100000000 * a && i < 100000000/* Do it a few extra times, just to make sure */ * b; i++) {
        if (a % i == 0 && b % i == 0) {
            result = i;
        }
    }
    return [result, a / result, b / result];
}

빠르지 않다

추가적인 안전 장치처럼 콜백을 사용하십시오.

function gcf(a, b) {
    setTimeout(function() {
        var result = 1;
        for (var i = 1; i < 2 * a && i < 2 * b; i++) {
            if (a % i == 0 && b % i == 0) {
                result = i;
            }
        }
        alert(result.toString() + " (" + (a / result).toString() + ", " + (b/result).toString() + ")");
    }, 10000);
}

안좋다

gcf(10, 10)안전한 디스크 공간에 대한 엄격한 제한 .

function gcf(a, b) {
    var gcfTable = [[1,1,1,1,1,1,1,1,1,1],[1,2,1,2,1,2,1,2,1,2],[1,1,3,1,1,3,1,1,3,1],[1,2,1,4,1,2,1,4,1,2],[1,1,1,1,5,1,1,1,1,5],[1,2,3,2,1,6,1,2,3,2],[1,1,1,1,1,1,7,1,1,1],[1,2,1,4,1,2,1,8,1,2],[1,1,3,1,1,3,1,1,9,1],[1,2,1,2,5,2,1,2,1,10]];
    return [gcfTable[a - 1][b - 1], a / gcfTable[a - 1][b - 1], b / gcfTable[a - 1][b - 1]];
}

싸고 빠르지 만 좋지 않은 때는 언제입니까?
— Hovercouch

이 대답은 싸고 훌륭하지만 빠르지는 않습니다.
— 칼륨 이온 18

문제는 서로 다른 상황에서 각각 "싸지 않은", "빠르지 않은"및 "좋지 않은"각각의 프로그램을 작성하는 것입니다.
— Hovercouch

답변 고정 ...
— 칼륨 이온
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.