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


10

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

수학

두 개의 0이 아닌 정수 ab가 주어지면 GCF dab 를 나머지없이 나누는 가장 큰 정수입니다 . 베즈 아웃 계수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.