Barato, rápido, bueno: factor común (mayor) [cerrado]

10

Inspirado por Cheap, Fast, Good , implementaremos un algoritmo que tiene exactamente dos de ellos.

Las matemáticas

Dados dos números enteros no nulos a y b , el GCF d es el mayor número entero que divide tanto una y b sin resto. Los coeficientes de Bézout son pares de enteros (x, y) de modo que ax + by = d . Los coeficientes de Bézout no son únicos. Por ejemplo, dado:

a = 15, b = 9

Tenemos

d =  3
x =  2
y = -3

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

Una forma común de calcular el MCD y un par de coeficientes de Bézout es usar el algoritmo de Euclides , pero de ninguna manera es la única forma.

El código

Su programa debe tomar dos enteros como entradas. Debería generar / devolver el máximo factor común y un par de coeficientes de Bézout.

Entrada de ejemplo:

15 9

salida de ejemplo

3 (2, -3)

La salida puede estar en cualquier orden y formato, pero debe quedar claro cuál es el MCD y cuáles son los coeficientes.

El deshonesto

Su programa tiene el potencial de ser barato, rápido y bueno. Desafortunadamente, solo pueden ser dos de esos a la vez.

  • Cuando no es barato , el programa debe usar una cantidad excesiva de recursos del sistema.
  • Cuando no es rápido , el programa debería tomar una cantidad excesiva de tiempo.
  • Cuando no es bueno , la salida del programa debería ser incorrecta.

El programa debería poder hacer (bueno, no hacer) los tres. Lo que hace cuando depende de usted, podría basarse en el tiempo, el compilador, qué entrada es más grande, etc. Algunas notas adicionales:

  • Obviamente, su programa no debe ser sencillo y debe pasar una inspección superficial. Sospecharía un poco si implementaras tres algoritmos separados.
  • En el caso barato , "cantidad excesiva de recursos del sistema" es cualquier cosa que ralentizaría otros programas. Puede ser memoria, ancho de banda, etc.
  • En el caso rápido , "tiempo excesivo" significa relativo a cómo funciona en los casos baratos y buenos . El programa aún debería terminar. Cuanto más cerca esté de "increíblemente frustrante pero no lo suficientemente frustrante como para detener el programa", mejor (más divertido).
  • En el buen caso, la salida no debería ser obviamente incorrecta y debería pasar una inspección superficial. Sería muy sospechoso si me diera un MCD de "2 anna half".

Este es un concurso de popularidad, ¡así que la mayoría de los votos positivos gana!

EDITAR

Para aclarar, estoy buscando programas que pueden ser "rápidos y baratos" y "baratos y buenos" y "rápidos y buenos" en diferentes casos, no aquellos que solo hacen uno de ellos.

Hovercouch
fuente
1
Es bueno tener un desafío original como este. :)
Ypnypn
¿El programa tiene que ser exactamente dos a la vez o está bien si solo es bueno en algunos casos y barato y rápido (pero no bueno) en otros?
Dennis
1
Estoy buscando tres casos, con exactamente dos en cada uno.
Hovercouch
Si el programa no es bueno, ¿su salida debería ser incorrecta? Entonces, ¿cuál es el punto de calcular algo correctamente?
Ricardo A
44
Estoy votando para cerrar esta pregunta como fuera de tema porque es un desafío [poco claro], que estaba en tema hace un año, pero ahora está fuera de tema por consenso de la comunidad .
James

Respuestas:

2

C

Es barato y rápido. Obtienes mcd en un abrir y cerrar de ojos. Sin embargo, el tipo que lo hizo no tenía idea de ese "co-algo de Bézier", por lo que simplemente dividió ayb por mcd. (para empeorar las cosas, en ese punto ayb están bastante lejos de su valor inicial debido al algoritmo que eligió sabiamente)

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;
}
bebe
fuente
0

C#

Esto calcula los coeficientes de Bézout. He utilizado el algoritmo de Euclides extendido .

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

    }
}
Bura Chuhadar
fuente
¿Cuándo es esto costoso, cuándo es lento y cuándo es malo?
undergroundmonorail
@undergroundmonorail Pondré esos valores cuando tenga la oportunidad.
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__

No es barato: main () se llama de forma recursiva (llenando la pila) hasta que perl active una advertencia de "recursión profunda" que cerrará la aplicación debido al controlador __WARN__.

No rápido: cuando los algoritmos gcf () devuelven resultados correctos, el código solo se cuelga durante unos segundos (select () en main ()).

No es bueno: todos los resultados superiores a 99 (o inferiores a -99) son incorrectos.

En general, no es tan creativo; esperando respuestas más elegantes.

Matías
fuente
0

Pitón

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

Esto es barato y rápido, pero es malo en el hecho de que el rango está limitado a la entrada más grande, por lo que es posible que no encuentre un par de coeficientes.

Buen rompecabezas

Ricardo A
fuente
0

Javascript

No es barato

Utiliza muchos recursos del 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];
}

No rapido

Utilice una devolución de llamada, solo como un extra a prueba de fallas.

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

No está bien

Límite estricto de gcf(10, 10), solo para ahorrar espacio en 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]];
}
Ion de potasio
fuente
¿Cuándo es barato y rápido pero no es bueno?
Hovercouch
Esta respuesta es barata, buena, pero no rápida.
Ion de potasio el
El desafío es escribir un programa que sea "no barato", "no rápido" y "no bueno" en diferentes circunstancias.
Hovercouch
Respuesta corregida ...
Potassium Ion