Barato, rápido, bom - fator comum (ótimo) [fechado]

10

Inspirados em Barato, Rápido, Bom , vamos implementar um algoritmo que possui exatamente dois deles.

A matemática

Dado dois números inteiros diferentes de zero a e b , o GCF d é o maior número inteiro que divide a e b sem deixar resto. Os coeficientes de Bézout são pares de números inteiros (x, y) tais que ax + by = d . Os coeficientes de Bézout não são únicos. Por exemplo, dado:

a = 15, b = 9

Nós temos

d =  3
x =  2
y = -3

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

Uma maneira comum de calcular o GCF e um par de coeficientes de Bézout é usar o algoritmo de Euclides , mas não é o único caminho.

O código

Seu programa deve receber dois números inteiros como entradas. Deve gerar / retornar o maior fator comum e um par de coeficientes de Bézout.

Exemplo de entrada:

15 9

saída de exemplo

3 (2, -3)

A saída pode estar em qualquer ordem e formato, mas deve ficar claro qual é o GCF e quais são os coeficientes.

The Underhanded

Seu programa tem potencial para ser barato, rápido e bom. Infelizmente, só podem ser dois deles ao mesmo tempo.

  • Quando não é barato , o programa deve usar uma quantidade excessiva de recursos do sistema.
  • Quando não é rápido , o programa deve levar uma quantidade excessiva de tempo.
  • Quando não está bom , a saída do programa deve estar errada.

O programa deve ser capaz de executar (bem, não executar) todos os três. O que significa quando depende de você - pode ser com base no tempo, no compilador, em qual entrada é maior etc. Algumas notas adicionais:

  • Seu programa não deve estar obviamente oculto e deve passar por uma inspeção superficial. Eu ficaria um pouco desconfiado se você implementasse três algoritmos separados.
  • No caso barato , "quantidade excessiva de recursos do sistema" é algo que atrasaria outros programas. Pode ser memória, largura de banda, etc.
  • No caso rápido , "tempo excessivo" significa em relação à maneira como funciona de maneira barata e boa. casos . O programa ainda deve terminar. Quanto mais perto você puder "incrivelmente frustrante, mas não frustrante o suficiente para interromper o programa", melhor (mais engraçado e).
  • No bom caso, a saída não deve estar obviamente errada e deve passar por uma inspeção superficial. Eu ficaria muito desconfiado se isso me desse um GCF de "2 anna half".

Este é um concurso de popularidade, então a maioria dos upvotes ganha!

EDITAR

Para esclarecer, estou procurando programas que podem ser "rápidos e baratos" e "baratos e bons" e "rápidos e bons" em diferentes casos, não aqueles que apenas fazem um deles.

Hovercouch
fonte
11
É bom ter um desafio original como esse. :)
Ypnypn
O programa precisa ser exatamente dois de uma vez ou tudo bem se for bom em alguns casos e barato e rápido (mas não bom) em outros?
Dennis
11
Estou procurando por três casos, com exatamente dois em cada um.
Hovercouch
Se o programa não for bom, a saída deve estar incorreta? Então, qual é o sentido de calcular qualquer coisa corretamente?
Ricardo A
4
Estou votando para encerrar esta questão como fora de tópico, porque é um desafio [disfarçado], que estava presente há um ano, mas agora está fora de tópico por consenso da comunidade .
James

Respostas:

2

C

É barato e rápido. Você recebe um CD em um piscar de olhos. No entanto, o cara que fez isso não tinha idéia sobre o "co-algo de Bézier", então ele simplesmente dividiu aeb por gcd. (para piorar as coisas, nesse ponto aeb estão bem longe do valor inicial por causa do algoritmo que ele sabiamente escolheu)

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
fonte
0

C #

Isso calcula os coeficientes de Bézout. Eu usei o algoritmo euclidiano estendido .

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
fonte
Quando é caro, quando é lento e quando é ruim?
Undergroundmonorail
@undergroundmonorail Vou colocar esses valores quando tiver chance.
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__

Não é barato: main () é chamado recursivamente (preenchendo a pilha) até que um aviso de "recursão profunda" seja disparado pelo perl, que encerrará o aplicativo devido ao manipulador __WARN__.

Não é rápido: quando os algoritmos gcf () retornam resultados corretos, o código permanece por alguns segundos (select () em main ()).

Não é bom: todos os resultados acima de 99 (ou abaixo de -99) estão incorretos.

Em suma, não é tão criativo; ansioso por respostas mais elegantes.

Matthias
fonte
0

Pitão

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

Isso é barato e rápido, mas é ruim porque a faixa é limitada na maior entrada, portanto, pode não encontrar um par de coeficientes.

Bom quebra-cabeça.

Ricardo A
fonte
0

Javascript

Não é barato

Usa muitos recursos do 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];
}

Não rápido

Use um retorno de chamada, assim como uma proteção extra contra falhas.

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

Não é bom

Limite estrito de gcf(10, 10), apenas para espaço em disco seguro.

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]];
}
Iões de potássio
fonte
Quando é barato e rápido, mas não é bom?
precisa
Essa resposta é barata, boa, mas não rápida.
Potassium Ion
o desafio é escrever um programa que seja "não barato", "não rápido" e "não bom" em diferentes circunstâncias.
Hovercouch
Resposta fixada ...
Potassium Ion