fazer o programa encontrar valor ideal

04/02/2020

23

Olá senhores!
Estou com uma dúvida para encontrar um valor ideal ou otimizado para um sistema de vendas que precisa encontrar uma quantidade de produtos ideal para um valor:

exemplo: o usuario digita em um edit que precisa de 17 litros de oleo. Em um DBgrid existem varios modelos de um garrafas de oleos, cada uma com quantidades unicas, como:
-5 litros
-10 litros
-3 litros

como fazer o programa achar a quantidade de garrafas ideal para essa situação?

desde já agradeço muito!
Antonio Brandão

Antonio Brandão

Responder

Posts

10/02/2020

Emerson Nascimento

ideal não precisa ser exata, certo?
Responder

10/02/2020

Antonio Brandão

ideal não precisa ser exata, certo?
exatamente
Responder

12/02/2020

Emerson Nascimento

conseguiu resolver?
eu fiz uma função aqui... não ficou aqueeeela coisa, mas funciona...
Responder

12/02/2020

Antonio Brandão

conseguiu resolver?
eu fiz uma função aqui... não ficou aqueeeela coisa, mas funciona...
fiz um algoritmo semelhante a um algoritmo de "quantidade de moedas de troco em centavos" mas não funciona para encontrar valores aproximados.

pode postar o que você fez por favor?
Responder

13/02/2020

Emerson Nascimento


teste o programa e veja se é isso que espera:

https://www.4shared.com/rar/SgGQCYmCiq/Project6.html

ao descompactar, troque a extensão txt para exe



Responder

13/02/2020

Antonio Brandão


teste o programa e veja se é isso que espera:

https://www.4shared.com/rar/SgGQCYmCiq/Project6.html

ao descompactar, troque a extensão txt para exe





é muito parecido com isso, quais os comandos o programa faz?
Responder

13/02/2020

Emerson Nascimento

segue a função (em Delphi):
procedure CalcTroco( Valor: integer; Opcoes: TMoedas; var aResult: TRetornoCalc;
  lAceitaAproximado: boolean = False; lNaoEstourar: boolean = True );
var
  nInit, i, n, nMult: integer;
  nResto: integer;
  ValorCalc: integer;
begin
  TArray.Sort<integer>(Opcoes);

  ValorCalc := Valor;
  SetLength(aResult,Length(Opcoes));
  nInit := Low(aResult);
  for i := High(Opcoes) downto Low(Opcoes) do
  begin
    aResult[nInit,0] := Opcoes[i];
    aResult[nInit,1] := -1;
    Inc(nInit);
  end;

  nInit := Low(aResult);

  while (ValorCalc <> 0) do
  begin

    while (ValorCalc <> 0) and (nInit <= High(aResult)) do
    begin
      ValorCalc := Valor;
      for i := nInit to High(aResult) do
      begin
        if aResult[i,1] = -1 then
          aResult[i,1] := ValorCalc div aResult[i,0];
        ValorCalc := ValorCalc - (aResult[i,1] * aResult[i,0]);
        if ValorCalc = 0 then
          break;
      end;

      // se não conseguiu o cálculo exato
      if ValorCalc <> 0 then
      begin
        if aResult[nInit,1] > 0 then
          aResult[nInit,1] := aResult[nInit,1] - 1;
        for i := nInit+1 to High(aResult) do
          aResult[i,1] := -1;
        if aResult[nInit,1] = 0 then
          Inc(nInit);
      end;

    end;

    // se o valor não foi exato
    if ValorCalc <> 0 then
    begin
      if lAceitaAproximado then // verifico se pode ser valor aproximado
      begin
        if lNaoEstourar then
          Dec(Valor)
        else
          Inc(Valor);

        nInit := Low(aResult);
        for i := Low(aResult) to High(aResult) do
          aResult[i,1] := -1;
      end
      else
        ValorCalc := 0;
    end;

  end;

  // zero as quantidades que estiverem negativas
  for i := Low(aResult) to High(aResult) do
    if aResult[i,1] < 0 then
      aResult[i,1] := 0;

  // redistribui os valores, caso necessário
  for i := High(aResult) downto Low(aResult)+1 do
    if aResult[i,1] > 0 then
      for n := (i-1) downto Low(aResult) do
      begin
        nMult := (aResult[i,1] * aResult[i,0]) div aResult[n,0];
        nResto := (aResult[i,1] * aResult[i,0]) - (nMult * aResult[n,0]);
        if (nMult > 0) and ((nResto = 0) or ((nResto mod aResult[i,0])=0)) then
        begin
          aResult[i,1] := aResult[i,1] - ((nMult * aResult[n,0]) div aResult[i,0]);
          aResult[n,1] := aResult[n,1] + nMult;
        end;
      end;

end;

para trabalhar com a função no Delphi, criei dois tipos de dados para guardar tanto as opções possíveis, quanto o resultado:
type
  TRetornoCalc = array of array[0..1] of integer;
  TMoedas = TArray<integer>;

para utilizar você precisará passar para a função o valor que deseja distribuir, as opções que poderão ser utilizadas, a variável que receberá o resultado da distribuição, se aceita valor aproximado e, caso o valor possa ser aproximado, se será permitido 'estourar' o valor.
exemplo de uso:
procedure TForm3.Button4Click(Sender: TObject);
var
  i: integer;
  aRetorno: TRetornoCalc;
  aMoedas: TMoedas;
  strMensagem: string;
begin
  SetLength(aMoedas, 3);
  aMoedas[0] := 5;
  aMoedas[1] := 3;
  aMoedas[2] := 10;

  CalcTroco( 7, // valor desejado
             aMoedas, // opções disponíveis
             aRetorno, // retorno calculado
             True, // indica se aceita cálculo aproximado (se não conseguir exato)
             False ); // indica se calculo aproximado pode 'estourar' o valor

  strMensagem := '';
  for i := Low(aRetorno) to High(aRetorno) do
    strMensagem := strMensagem + FloatToStr(aRetorno[i,1])+' un de '+FloatToStr(aRetorno[i,0])+'l' + Chr(10) + Chr(13);
  ShowMessage(strMensagem);
end;

Responder

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários,
consulte nossa política de privacidade.

Aceitar