Contando Troco No Ruby Quiz

Vindo do blog Nome Do Jogo, fiquei sabendo do novo desafio do Ruby Quiz. Há um tempo atrás acompanhava cada novo desafio, alguns que eu achava interessante, tentava resolvê-los, mas nunca cheguei a enviar a solução pra lá. Mas esse desafio é simples e bastante divertido.

O desafio é criar um método que recebe dois argumentos, um deles é um valor que deve ser dividido em moedas fornecidas no segundo argumento, o método tem que retornar um array com a menor combinação possível de moedas. Imagine ter que dar 37 centavos em moedas de 25, 10, 5 e 1? O certo seria receber uma de 25, uma de 10 e duas de 1, veja o código pra entender melhor:

irb(main):005:0> make_change(37, [25, 10, 5, 1])
=> [25, 10, 1, 1]

Entendeu?! Agora vamos implementar o método, somente o método, não farei nenhuma classe. Primeiro vamos fazer alguns testes antes de criar o método:

require "test/unit";

class ChangeTest < Test::Unit::TestCase
  
  def test_should_raise_error_when_change_is_impossible
    assert_raise(ChangeError) do
      make_change(23, [10, 5]);
    end
  end
  
  def test_should_accept_diferent_coins
    assert_equal [17, 17, 4], make_change(38, [17, 4]);
    assert_equal [52], make_change(52, [52]);
  end
  
  def test_should_give_minimun_number_of_coins
    assert_equal [25, 10, 1, 1], make_change(37);
    assert_equal [1, 1, 1], make_change(3);
    assert_equal [3, 3], make_change(6, [3]);
  end
  
end

Se a troca for impossível com as moedas fornecidas, o método vai devolver uma exceção do tipo ChangeError. O método também tem por default moedas de 25, 10, 5 e 1 para serem usadas. Feitos os testes, vamos partir para a implementação, para isso precisaremos adicionar um método sum na classe Array que soma os elementos de dentro do Array:

class Array
  
  def sum
    inject{|sum, n| sum + n;};
  end
  
end

Pronto, agora podemos partir para a implementação:

class ChangeError < StandardError; end

def make_change(amount, coins=[25, 10, 5, 1])
  change = coins.sort.reverse.inject([]) do |change, coin|
    change << coin until change.sum + coin > amount;
    change;
  end
  raise ChangeError unless change.sum == amount;
  change;
end

Na linha 4, eu ordeno o Array de maior para menor e uso o método inject, que é basicamente responsável por reduzir o Array a um valor. Nesse caso dentro do bloco de código eu coloco as moedas no Array change até que elas ultrapassarem o valor total, e devolvo esse Array. Na linha 8 eu checo se a soma do Array change é igual ao valor pedido, se não for retorna uma exceção ChangeError.

Não foi muito difícil, tem desafios mais elaborados no site, vale a pena dar uma conferida. Fiquei sabendo também que parece que esse é um dos últimos desafios do Ruby Quiz.

Powered by ScribeFire.

About these ads

3 respostas para Contando Troco No Ruby Quiz

  1. JulioGreff disse:

    Interessante! Pena que sou péssimo em Ruby, senão eu tentaria. Sorte!

  2. pts, eu dei uma acalmada nos meus estudos com ruby por causa do excesso de trabalho, mas creio que ainda esse final de mês eu já alivie e recomece!

    Ah! Quanto ao basquete, curto muito! Até jogo de vez em quando, mas estava me referindo mesmo é ao trabalho :p

    Um abraço mano!

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.

%d blogueiros gostam disto: