Ir ao conteúdo
  • Cadastre-se

Javascript Como diminuir a complexidade desse algoritmo?


Posts recomendados

usabilidade nula, quase todo mundo não gosta. usabilidade baixa, quase todo mundo gosta. usabilidade média, quase todo mundo adora. usabilidade alta, quase todo mundo ama.

 

HTML

 

<form>
    <p>Voc&ecirc; tem <input required id="numero_assinantes" type="number" min="0" value="0" onchange="calcular()"> assinantes ent&atilde;o precisa cobrar BRL <input readonly id="preco_assinatura" type="number" value="78"> por semana dos novos assinantes e tem um sal&aacute;rio de BRL <input readonly id="salario" type="number" value="0"> por semana. N&atilde;o pode mudar o pre&ccedil;o dos assinantes atuais. Seu sal&aacute;rio &eacute; de produtor sem nenhum afiliado e sem nenhum coprodutor.</p>
</form>

 

JavaScript

 

<script type="application/javascript">
    class TimeCounter{
        constructor(){
            this.startDate = null;
        }

        start(){
            this.startDate = new Date();
        }

        stop(){
            return (new Date() - this.startDate);
        }
    }

    function calcular(){
        var timeConter = new TimeCounter();
        timeConter.start();
        var numeroAssinantes = document.getElementById("numero_assinantes");
        var precoAssinatura = document.getElementById("preco_assinatura");
        var salario = document.getElementById("salario");
        var valorSalario01 = 0, valorSalario02 = 0, valorSalario03 = 0, valorSalario04 = 0, valorSalario05 = 0, valorSalario06 = 0, valorSalario07 = 0, valorSalario08 = 0, valorSalario09 = 0, valorSalario10 = 0, valorSalario11 = 0;
        if(numeroAssinantes.value == "" || numeroAssinantes.value < 0){
            numeroAssinantes.value = 0;
        }
        for(var i = 0; i <= numeroAssinantes.value; i++){
            if(i <= 25){
                precoAssinatura.value = 78;
                valorSalario01 = precoAssinatura.value * (i - 0);
            }
            else if(i <= 125){
                precoAssinatura.value = 70;
                valorSalario02 = precoAssinatura.value * (i - 25);
            }
            else if(i <= 625){
                precoAssinatura.value = 62;
                valorSalario03 = precoAssinatura.value * (i - 125);
            }
            else if(i <= 15625){
                precoAssinatura.value = 54;
                valorSalario04 = precoAssinatura.value * (i - 625);
            }
            else if(i <= 62500){
                precoAssinatura.value = 46;
                valorSalario05 = precoAssinatura.value * (i - 15625);
            }
            else if(i <= 250000){
                precoAssinatura.value = 38;
                valorSalario06 = precoAssinatura.value * (i - 62500);
            }
            else if(i <= 1000000){
                precoAssinatura.value = 30;
                valorSalario07 = precoAssinatura.value * (i - 250000);
            }
            else if(i <= 8000000){
                precoAssinatura.value = 22;
                valorSalario08 = precoAssinatura.value * (i - 1000000);
            }
            else if(i <= 20000000){
                precoAssinatura.value = 14;
                valorSalario09 = precoAssinatura.value * (i - 8000000);
            }
            else{
                precoAssinatura.value = 6;
                valorSalario10 = precoAssinatura.value * (i - 20000000);
            }
            valorSalario11 = valorSalario01 + valorSalario02 + valorSalario03 + valorSalario04 + valorSalario05 + valorSalario06 + valorSalario07 + valorSalario08 + valorSalario09 + valorSalario10;
        }
        if(numeroAssinantes.value == 25) precoAssinatura.value = 70;
        else if(numeroAssinantes.value == 125) precoAssinatura.value = 62;
        else if(numeroAssinantes.value == 625) precoAssinatura.value = 54;
        else if(numeroAssinantes.value == 15625) precoAssinatura.value = 46;
        else if(numeroAssinantes.value == 62500) precoAssinatura.value = 38;
        else if(numeroAssinantes.value == 250000) precoAssinatura.value = 30;
        else if(numeroAssinantes.value == 1000000) precoAssinatura.value = 22;
        else if(numeroAssinantes.value == 8000000) precoAssinatura.value = 14;
        else if(numeroAssinantes.value == 20000000) precoAssinatura.value = 6;
        salario.value = valorSalario11;
        console.log(timeConter.stop());
    }
</script>

 

Quando no número de assinantes coloco valor 60 milhões, demora 28.808 milissegundos para terminar de executar a função. Como diminuir a complexidade desse algoritmo? A usabilidade está nula, baixa, média ou alta?

Link para o comentário
Compartilhar em outros sites

Pelo que entendi, um esboço de refatoração do seu código, poderia estar em separar essa função em duas e chamar essas duas funções  na função calcular().

Poderia também remover todas essas variáveis : ""valorSalario1, valorSalario2 ...."  e lançar o resultado, somente em uma variável, ou direto na input.

Poderia remover essa correção  que você faz no laço for,  do tipo " (i - 25) ", Entendi porque você faz isso, pra remover o valor anterior ao if, e a multiplicação ficar correta, mas também tem como remover. 

E organizar todos esses parâmetros em um objeto.

Um esboço , mais ou menos ficaria assim 

 

<script>
const numeroAssinantes  = document.getElementById("numero_assinantes");
const precoAssinatura   = document.getElementById("preco_assinatura");
const salario           = document.getElementById("salario");
//NOTE QUE AS CONSTS ESTÃO FORA DA FUNÇÃO
function calcular (){

const parametro  = {
  all:[
      {assinantes : 25       , valor: 78},
      {assinantes : 125      , valor: 70},
      {assinantes : 625      , valor: 62},
      {assinantes : 15625    , valor: 54},
      {assinantes : 62500    , valor: 46},
      {assinantes : 250000   , valor: 38},
      {assinantes : 1000000  , valor: 30},
      {assinantes : 8000000  , valor: 22},
      {assinantes : 20000000 , valor: 14},
      {assinantes : null     , valor: 6 },
  ]
}

numeroAssinantes.value = verificarCampoInvalio()
calcularSalario( parametro.all )
}


function verificarCampoInvalio(){
  return  numeroAssinantes.value
  === "" || numeroAssinantes.value
  < 0 ?  0 : numeroAssinantes.value
}

function calcularSalario( param ){

    for(p of param) {

      if(numeroAssinantes.value <= p.assinantes ){
         precoAssinatura.value    = p.valor
         salario.value            =  numeroAssinantes.value * p.valor
         break;
      }
      if(p.assinantes === null){
          precoAssinatura.value   = p.valor
          salario.value           =   numeroAssinantes.value * p.valor
       }
  }
}
  </script>

 

 

Aconselho você usar a const para fazer referência aos elementos do html ao invés do var. 

Basicamente na função calcular(), constaria o objeto com os parâmetros de assinantes e valor, o "parametro" , mais uma função que verificar se o valor inserido no campo "numeroAssinantes" foi inválido e uma função que calcula o salário .  E você pode colocar o TimeCounter() dentro da função calcular(), também, eu não pus ai , porque só reescrevi a função a calcular.  

 

Então na minha opinião, você poderia fazer mais ou menos esses procedimentos.

Falou  

 

 

Link para o comentário
Compartilhar em outros sites

Pelo que eu entendi do seu algoritmo, se o número de assinantes for menos de 25 o valor do serviço seria de 78, se for maior que 25 o valor seria 70, assim por diante. 

Se for isso, o correto seria assinantes : 25 , valor: 78

Mas você pode modificar e inserir novos valores no objeto "parametro", que automaticamente a função calcularSalario irá incorporar. 

Ai tu dá uma testada.   

Link para o comentário
Compartilhar em outros sites

 Joguei seu algoritmo no VScode e entendi, agora, que tem um acúmulo dos assinantes  nos valores anteriores. Eu não tinha notado isso.

Nesse caso, vai precisar fazer uma modificação no código. Fiz, uma fórmula matemática pra que essa conta seja possível.

E achei melhor alterar o último valor do objeto "parametro" de "null" para 20000000. 

Acabei de testar a função VerificarCampoInvalido() não deu erro, mas notei que quando escrevi aqui, eu coloque  "VerificarCampoInvalio()", tá escrito errado, depois você vê se isso pode ser o motivo do erro.

 

Modificações no código

 

<script>
const numeroAssinantes  = document.getElementById("numero_assinantes");
const precoAssinatura   = document.getElementById("preco_assinatura");
const salario           = document.getElementById("salario");
const parametro  = {
  all:[
      {assinantes : 25       , valor: 78},
      {assinantes : 125      , valor: 70},
      {assinantes : 625      , valor: 62},
      {assinantes : 15625    , valor: 54},
      {assinantes : 62500    , valor: 46},
      {assinantes : 250000   , valor: 38},
      {assinantes : 1000000  , valor: 30},
      {assinantes : 8000000  , valor: 22},
      {assinantes : 20000000 , valor: 14},
      {assinantes : 20000000 , valor: 6 },
  ]
}

function calcular (){
    numeroAssinantes.value = verificarCampoInvalido()
    calcularSalario( parametro.all )
}


function verificarCampoInvalido(){
  return  numeroAssinantes.value
  === "" || numeroAssinantes.value
  < 0 ?  0 : numeroAssinantes.value
}

function formula( aa , na, pv ){
  return  (aa * (p.valor +8 )) + (( na - aa ) * pv)
}

function calcularSalario( param ){
       let assinantesAnterior = 0
    for(p of param) {

      if(numeroAssinantes.value <= p.assinantes ){
         precoAssinatura.value = p.valor
         salario.value         =  formula(assinantesAnterior,numeroAssinantes.value, p.valor)
         console.log(p.assinantes)
         break;
      }
      else{
        assinantesAnterior += p.assinantes 
        console.log(assinantesAnterior)
      }
      if( numeroAssinantes.value  > parametro.all[ parametro.all.length-1].assinantes){
          precoAssinatura.value   = p.valor
          salario.value           = formula(assinantesAnterior,numeroAssinantes.value, p.valor)
       } 
  }
}
</script>

 

Depois tu dá uma olhada se consegue melhorar esse código com o método reduce(). 

 

 

Link para o comentário
Compartilhar em outros sites

@Eduardo de Quadrospara o if/else você troca por switch e para cada função diferente do seu sistema se estiver totalmente orientado a objetos as classe você separa entre entidade e métodos, ou seja: classe pessoa: entidade = pessoa, qual seriam os métodos da pessoa? se-mexer, falar, ouvir... O que não seria um métoda da pessoa? dirigir. Quem dirige é o motorista e não uma pessoa. logo assim você separa a complexidade de um algoritmo orientado a objetos. Isso se chama *single responsibility principle* dos conceitos S.O.L.I.D. Se for fazer no modo raiz, separe todas as responsabilidades "únicas" em funções  com o nome da responsabilidade e só chama no momento certo. 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Meu HTML:

 

<form>
  <p>Voc&ecirc; &eacute; um produtor que tem <input required id="numero_assinantes" type="number" min="0" value="0" onchange="calcularPrecoWebsite()"> assinantes, <input required id="numero_afiliados" type="number" min="0" max="0" value="0" onchange="calcularPrecoWebsite()"> afiliados e <input required id="numero_coprodutores" type="number" min="0" max="0" value="0" onchange="calcularPrecoWebsite()"> coprodutores ent&atilde;o precisa cobrar BRL <span id="preco_assinatura">78</span> por semana dos novos assinantes e tem um sal&aacute;rio de BRL <span id="salario">0</span> por semana. N&atilde;o pode mudar o pre&ccedil;o dos assinantes atuais. Pelo seu sal&aacute;rio, seu n&iacute;vel de <span id="pobreza_ou_riqueza">pobreza</span> &eacute; <span id="nivel_pelo_salario">miser&aacute;vel</span>.</p>
</form><br>

 

Meu JavaScript:

 

class TimeCounter{
  constructor(){
    this.startDate = null;
  }

  start(){
    this.startDate = new Date();
  }

  stop(){
    return (new Date() - this.startDate);
  }
}

function calcularPrecoWebsite(){
  var timeConter = new TimeCounter();
  timeConter.start();
  var numeroAssinantes = document.getElementById("numero_assinantes");
  var numeroAfiliados = document.getElementById("numero_afiliados");
  var numeroCoprodutores = document.getElementById("numero_coprodutores");
  var maxSomaAfiliadosCoprodutores = 0;
  var precoAssinatura = document.getElementById("preco_assinatura");
  var salario = document.getElementById("salario");
  var pobrezaOuRiqueza = document.getElementById("pobreza_ou_riqueza");
  var nivelPeloSalario = document.getElementById("nivel_pelo_salario");
  var valorSalario01 = 0, valorSalario02 = 0, valorSalario03 = 0, valorSalario04 = 0, valorSalario05 = 0, valorSalario06 = 0, valorSalario07 = 0, valorSalario08 = 0, valorSalario09 = 0, valorSalario10 = 0, valorSalario11 = 0, valorSalario12 = 0;
  if(numeroAssinantes.value == "" || numeroAssinantes.value < 0){
    numeroAssinantes.value = 0;
  }
  if(numeroAfiliados.value == "" || numeroAfiliados.value < 0){
    numeroAfiliados.value = 0;
  }
  if(numeroCoprodutores.value == "" || numeroCoprodutores.value < 0){
    numeroCoprodutores.value = 0;
  }
  for(var i = 0; i <= numeroAssinantes.value; i++){
    if(i <= 25){
      precoAssinatura.innerHTML = 78;
      valorSalario01 = precoAssinatura.innerHTML * (i - 0);
    }
    else if(i <= 125){
      precoAssinatura.innerHTML = 70;
      valorSalario02 = precoAssinatura.innerHTML * (i - 25);
    }
    else if(i <= 625){
      precoAssinatura.innerHTML = 62;
      valorSalario03 = precoAssinatura.innerHTML * (i - 125);
    }
    else if(i <= 15625){
      precoAssinatura.innerHTML = 54;
      valorSalario04 = precoAssinatura.innerHTML * (i - 625);
    }
    else if(i <= 62500){
      precoAssinatura.innerHTML = 46;
      valorSalario05 = precoAssinatura.innerHTML * (i - 15625);
    }
    else if(i <= 250000){
      precoAssinatura.innerHTML = 38;
      valorSalario06 = precoAssinatura.innerHTML * (i - 62500);
    }
    else if(i <= 1000000){
      precoAssinatura.innerHTML = 30;
      valorSalario07 = precoAssinatura.innerHTML * (i - 250000);
    }
    else if(i <= 8000000){
      precoAssinatura.innerHTML = 22;
      valorSalario08 = precoAssinatura.innerHTML * (i - 1000000);
    }
    else if(i <= 20000000){
      precoAssinatura.innerHTML = 14;
      valorSalario09 = precoAssinatura.innerHTML * (i - 8000000);
    }
    else{
      precoAssinatura.innerHTML = 6;
      valorSalario10 = precoAssinatura.innerHTML * (i - 20000000);
    }
    valorSalario11 = valorSalario01 + valorSalario02 + valorSalario03 + valorSalario04 + valorSalario05 + valorSalario06 + valorSalario07 + valorSalario08 + valorSalario09 + valorSalario10;
  }
  if(numeroAssinantes.value == 25) precoAssinatura.innerHTML = 70;
  else if(numeroAssinantes.value == 125) precoAssinatura.innerHTML = 62;
  else if(numeroAssinantes.value == 625) precoAssinatura.innerHTML = 54;
  else if(numeroAssinantes.value == 15625) precoAssinatura.innerHTML = 46;
  else if(numeroAssinantes.value == 62500) precoAssinatura.innerHTML = 38;
  else if(numeroAssinantes.value == 250000) precoAssinatura.innerHTML = 30;
  else if(numeroAssinantes.value == 1000000) precoAssinatura.innerHTML = 22;
  else if(numeroAssinantes.value == 8000000) precoAssinatura.innerHTML = 14;
  else if(numeroAssinantes.value == 20000000) precoAssinatura.innerHTML = 6;
  valorSalario12 = valorSalario11;
  while(valorSalario12 > 0){
    valorSalario12 = Math.floor(valorSalario12 * 0.9);
    maxSomaAfiliadosCoprodutores++;
  }
  numeroAfiliados.max = maxSomaAfiliadosCoprodutores - numeroCoprodutores.value;
  numeroCoprodutores.max = maxSomaAfiliadosCoprodutores - numeroAfiliados.value;
  valorSalario12 = valorSalario11;
  valorSalario12 = Math.floor(valorSalario12 * Math.pow(0.9, numeroCoprodutores.value));
  valorSalario12 = Math.floor(valorSalario12 * Math.pow(0.9, numeroAfiliados.value));
  salario.innerHTML = valorSalario12;
  if(salario.innerHTML < 300){
    pobrezaOuRiqueza.innerHTML = "pobreza";
    if(salario.innerHTML < 12) nivelPeloSalario.innerHTML = "miser&aacute;vel";
    else if(salario.innerHTML < 60) nivelPeloSalario.innerHTML = "pobre";
    else nivelPeloSalario.innerHTML = "modesto";
  }
  else{
    pobrezaOuRiqueza.innerHTML = "riqueza";
    if(salario.innerHTML < 10000) nivelPeloSalario.innerHTML = "capitalizado";
    else if(salario.innerHTML < 60000) nivelPeloSalario.innerHTML = "rico";
    else if(salario.innerHTML < 200000) nivelPeloSalario.innerHTML = "afortunado";
    else if(salario.innerHTML < 1000000) nivelPeloSalario.innerHTML = "magnata";
    else nivelPeloSalario.innerHTML = "soberano";
  }
  if(valorSalario12 >= 1000){
    salario.innerHTML = salario.innerHTML.slice(0, salario.innerHTML.length - 3) + "." + salario.innerHTML.slice(salario.innerHTML.length - 3);
    if(valorSalario12 >= 1000000){
      salario.innerHTML = salario.innerHTML.slice(0, salario.innerHTML.length - 7) + "." + salario.innerHTML.slice(salario.innerHTML.length - 7);
      if(valorSalario12 >= 1000000000){
        salario.innerHTML = salario.innerHTML.slice(0, salario.innerHTML.length - 11) + "." + salario.innerHTML.slice(salario.innerHTML.length - 11);
      }
    }
  }
  console.log(timeConter.stop());
}

 

No Google Chrome, insiro 25 milhões de assinantes, e acontece isso:

 

image.png.150d6ad3ded517d180e6b55d493017ea.png

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...