安く、速く、良い-共通要素(最大)[終了]


10

Cheap、Fast、Goodに触発され 2つだけのアルゴリズムを実装します。

数学

ゼロ以外の2つの整数aおよびbが与えられた場合、GCF dは、abの両方を余りなく除算する最大の整数です。係数Bézout整数のペアである(x、y)のようにAX +による= D。ベズー係数は一意ではありません。たとえば、次の場合:

a = 15, b = 9

我々は持っています

d =  3
x =  2
y = -3

以来15*2 + 9*(-3) = 30 - 27 = 3

GCFとBézout係数のペアを計算する一般的な方法は、ユークリッドのアルゴリズムを使用することですが、これが唯一の方法というわけではありません。

コード

プログラムは、2つの整数を入力として受け取る必要があります。最大の共通因子と1組のベズー係数を出力/返すはずです。

入力例:

15 9

出力例

3 (2, -3)

出力は任意の順序と形式にすることができますが、どちらがGCFでどれが係数であるかは明確でなければなりません。

アンダーハンド

あなたのプログラムは安くて速くて良いものになる可能性があります。残念ながら、それは同時に2つしかありません。

  • 安価ではない場合、プログラムは過剰なシステムリソースを使用する必要があります。
  • 速くない場合は、プログラムに過度の時間がかかるはずです。
  • それが良くない場合、プログラムの出力は間違っているはずです。

プログラムは3つすべてを実行できます(実行できます)。それはあなた次第です-それは時間、コンパイラ、どの入力が大きいかなどに基づく可能性があります。いくつかの追加の注意事項:

  • あなたのプログラムは明らかに下手であってはならず、大まかな検査に合格するべきです。3つの個別のアルゴリズムを実装した場合、少し疑わしいと思います。
  • 安い場合、「システムリソースの過剰な量」とは、他のプログラムを遅くすることは何もです。メモリ、帯域幅などが考えられます。
  • では、高速、それが実行されている方法と比較した場合、「過度の時間」とは安い良い例。プログラムはまだ終了するはずです。「信じられないほどイライラするが、プログラムを停止するのに十分なほどイライラしない」に近づくほど(おかしく、そして)良くなります。
  • 良い場合、出力は明らかに間違ってはならないと通り一遍の検査に合格しなければなりません。「2アンナハーフ」のGCFが得られた場合は、非常に疑わしいと思います。

これは人気のコンテストなので、ほとんどの賛成票が勝ちます!

編集

明確にするために、私は「高速で安価」「安価で良い」「高速で優れた」さまざまなケースで実行できるプログラムを探しています。


1
このようなオリジナルのチャレンジがあるのは素晴らしいことです。:)
Ypnypn 2014年

プログラムは一度に正確に 2つである必要がありますか、それとも一部の場合にのみ優れていて、他の場合には安価で高速(ただし良くない)であれば問題ありませんか?
Dennis

1
私は、それぞれ2つずつ、3つのケースを探しています。
Hovercouch 2014年

プログラムが良くない場合、出力は正しくありませんか?それでは、何かを正しく計算することのポイントは何ですか?
Ricardo A

4
この質問は[1つ前の]課題でしたが、1年前に話題になりましたが、現在はコミュニティの合意により話題から外れているため、この質問を話題外として閉じることに投票します。
James

回答:


2

C

安くて速いです。あなたは瞬く間にgcdを取得します。しかし、それをした人はその「ベジエ共同何か」についての手がかりを持っていなかったので、彼は単に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

C#

これはベズー係数を計算します。私は拡張ユークリッドアルゴリズムを使用しました。

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私は機会があればそれらの値を入れます。
Bura Chuhadar、2014年

0

Perl 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__

安くない:main()は、__ WARN__ハンドラーのためにアプリケーションを終了するperlによって「深い再帰」の警告が出されるまで、再帰的に呼び出されます(スタックがいっぱいになります)。

高速ではありません: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))

これは安価で高速ですが、範囲が最大入力で上限が設定されているため、1組の係数を見つけられない可能性があるという点で悪いです。

良いパズル。


0

Javascript

安くない

多くのシステムリソースを使用します。

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

安くて速くて良くないのはいつですか?
ホバーカッチ2014年

この答えは安くて良いですが、速くはありません。
カリウムイオン

課題は、さまざまな状況で「安くない」、「速くない」、「良くない」のそれぞれであるプログラムを書くことです。
ホバーカウチ、2014

回答を修正しました...
カリウムイオン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.