Economico, veloce, buono - Fattore comune (massimo) [chiuso]


10

Ispirati da Cheap, Fast, Good , implementeremo un algoritmo che ne ha esattamente due.

La matematica

Dati due numeri interi non nulli una e B , la GCF d è il numero intero più grande che divide sia un e b senza residuo. I coefficienti di Bézout sono coppie di numeri interi (x, y) tali che ax + di = d . I coefficienti di Bézout non sono unici. Ad esempio, dato:

a = 15, b = 9

abbiamo

d =  3
x =  2
y = -3

Da allora 15*2 + 9*(-3) = 30 - 27 = 3.

Un modo comune per calcolare il GCF e una coppia di coefficienti di Bézout è usare l'algoritmo di Euclide , ma non è affatto l'unico modo.

Il codice

Il tuo programma dovrebbe prendere due numeri interi come input. Dovrebbe produrre / restituire il massimo fattore comune e una coppia di coefficienti di Bézout.

Esempio di input:

15 9

esempio di output

3 (2, -3)

L'output può essere in qualsiasi ordine e formato, ma dovrebbe essere chiaro quale sia il GCF e quali siano i coefficienti.

The Underhanded

Il tuo programma ha il potenziale per essere economico, veloce e buono. Sfortunatamente, possono essere solo due di quelli contemporaneamente.

  • Quando non è economico , il programma dovrebbe utilizzare una quantità eccessiva di risorse di sistema.
  • Quando non è veloce , il programma dovrebbe richiedere un tempo eccessivo.
  • Quando non va bene , l'output del programma dovrebbe essere sbagliato.

Il programma dovrebbe essere in grado di fare (bene, non fare) tutti e tre. Il che fa quando dipende da te, potrebbe essere basato sul tempo, sul compilatore, su quale input è più grande, ecc. Alcune note aggiuntive:

  • Il tuo programma non dovrebbe essere ovviamente subdolo e dovrebbe passare un controllo superficiale. Sarei un po 'sospettoso se implementassi tre algoritmi separati.
  • Nel caso economico , "una quantità eccessiva di risorse di sistema" è qualcosa che potrebbe rallentare altri programmi. Potrebbe essere memoria, larghezza di banda, ecc.
  • Nel caso rapido , "tempo eccessivo" significa rispetto a come funziona nei casi economici e buoni . Il programma dovrebbe ancora terminare. Il più vicino possibile a "incredibilmente frustrante ma non abbastanza frustrante per fermare il programma" il (più divertente e) migliore.
  • Nel buon caso, l'output non dovrebbe essere ovviamente sbagliato e dovrebbe passare un controllo superficiale. Sarei molto sospettoso se mi desse un GCF di "2 anna half".

Questo è un concorso di popolarità, quindi vince la maggior parte dei voti!

MODIFICARE

Per chiarire, sto cercando programmi che possano essere "veloci ed economici" e "economici e buoni" e "veloci e buoni" in diversi casi, non quelli che ne fanno solo uno.


1
È bello avere una sfida originale come questa. :)
Ypnypn,

Il programma deve essere esattamente due contemporaneamente o va bene se è buono solo in alcuni casi e economico e veloce (ma non buono) in altri?
Dennis,

1
Sto cercando tre casi, con esattamente due in ciascuno.
Hovercouch,

Se il programma non funziona, l'output dovrebbe essere errato? Allora qual è il punto di calcolare qualcosa correttamente?
Ricardo A

4
Sto votando per chiudere questa domanda come fuori tema perché è una sfida [subdola], che era in tema un anno fa, ma ora è fuori tema per consenso della comunità .
James,

Risposte:


2

C

È economico e veloce. Ottieni gcd in un batter d'occhio. Tuttavia, il ragazzo che lo ha fatto non aveva idea di quel "co-qualcosa di Bézier", quindi ha semplicemente diviso aeb per gcd. (a peggiorare le cose, a quel punto aeb sono piuttosto lontani dal loro valore iniziale a causa dell'algoritmo che ha saggiamente scelto)

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 #

Questo calcola i coefficienti di Bézout. Ho usato l' algoritmo euclideo esteso .

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 + ")"));
        }

    }
}

Quando è costoso, quando è lento e quando è cattivo?
undergroundmonorail,

@undergroundmonorail Metterò questi valori quando ne avrò la possibilità.
Bura Chuhadar,

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__

Non economico: main () viene chiamato in modo ricorsivo (riempiendo lo stack) fino a quando un avviso di "ricorsione profonda" viene generato da perl che chiuderà l'applicazione a causa del gestore __WARN__.

Non veloce: quando gli algoritmi di gcf () restituiscono risultati corretti, il codice rimane bloccato per alcuni secondi (selezionare () in main ()).

Non buono: tutti i risultati sopra 99 (o sotto -99) non sono corretti.

Tutto sommato non così creativo; in attesa di risposte più eleganti.


0

Pitone

#!/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))

Questo è economico e veloce, ma è negativo nel fatto che l'intervallo è limitato all'ingresso più grande, quindi potrebbe non trovare una coppia di coefficienti.

Buon puzzle.


0

Javascript

Non economico

Utilizza molte risorse di sistema.

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

Non veloce

Utilizzare un callback, proprio come un extra fail-safe.

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

Non bene

Limite rigoroso di gcf(10, 10), solo per proteggere lo spazio su disco.

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

Quando è economico e veloce ma non buono?
Hovercouch,

Questa risposta è economica, buona, ma non veloce.
Ione di potassio

la sfida è scrivere un programma che sia "non economico", "non veloce" e "non buono" in circostanze diverse.
Hovercouch,

Risposta risolta ...
Ione di potassio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.