Sorteio de números em Ruby
|
|
Pessoal, Precisava fazer um scriptzinho que sorteasse 5mil números entre 1000 pessoas. Cada uma teria 5 números pro sorteio. Ainda nem comecei a escrever, só fiz uns testes rápidos no IRB. @x = {"Arthur" => [1, 2, 3, 4, 5], “Matz” => [6, 7, 8, 9, 10]} Só que eu não consegui iterar pelos valores do array de números e adicionar esses dados no Hash. |
|
|
variavel_hash[objeto_indice] = valor |
|
|
Mas como eu vou adicionando estes valores assim como o método << faz com arrays? E testei dessa maneira tb: Eu sei que eu poderia pegar todos os valores e depois dar um hash[indice] = array mas queria ver se tem como fazer dessa maneira que eu perguntei e entender pq acontece isso com estes códigos que eu passei… |
|
|
Tenta isso daqui: Esse é um idioma legal do Ruby pra se trabalhar com hashes de array. Se o array não existe dentro do hash ele já cria e associa, se o array existe, ele simplesmente associa. Não é lá muito legível pra quem não conhece, mas faz bem o trabalho. |
|
|
Legal Ronie! Funcionou! mas e aê, alguém sabe explicar pq aqueles meus testes retornam um Hash em branco e o outro retorna um valor 16? Agora fiquei curioso! |
|
|
O código abaixo também funciona tranqüilo sem precisar repetir o ||= [] toda hora. a = Hash.new([]) a[:arthur] << 2 a[:arthur] << 3 Sobre o código retornar um hash em branco, pelo que eu entendi acontece o seguinte: quando o valor é simples, o método to_s do hash retorna tranqüilo. Se o valor é composto, ele não exibe nada. Compare:
{ 1 => 2 }.to_s
{ 1 => [1, 2] }.to_s
o TaQ, que já investigou bem mais a linguagem provavelmente pode explicar o porquê disse melhor. Sobre o valor 16, o código executado naquele momento foi 2 << 3 (note que você atribuiu 2 e depois fez << 3). O operador << significa shift left para inteiros. O número passou de (em binário): 00000010 (2) para 00010000 (16). |
|
|
Ronaldo, cuidado com o Hash.new([]). Ele mantém o mesmo array pra todos os elementos do hash criados por default. O melhor é usar um bloco de código pra obter o mesmo efeito. Eu costumo usar aquele idioma pq normalmente é só uma linha no meio de um loop. Mas tá certo, ele é bem confuso. |
|
|
Caramba, boa pegada. :-) “Mim ter que aprender muito sobre o Ruby ainda”. E faz o maior sentido mesmo já que o array fica parametrizado em uma variável de instância pelo visto. O bloco seria a solução mesmo. Sobre o idioma, acho que realmente é um dos mais comuns do Ruby. Só que se precisar repetir muito fica realmente confuso. |
|
|
Vish.. Bom, eu não preciso escrever um hash no scriptzinho que vou fazer, mas que isso tá estranho, tá! (ou o lerdo aqui não entendeu nada..haha) |
|
|
Cara, mea culpa. Eu coloquei o to_s pensando que ele voltava a mesma coisa que a representação. Olhando a documentação vejo que não volta. E eu estava errado de qualquer forma. Eu fiz alguns testes aqui e parece que o problema está no uso do default que o Ronie apontou. Veja:
>> a = Hash.new { |hash,key| hash[key] = "" }
=> {}
>> a[:a] << 2
=> "\002"
>> a[:a] << 3
=> "\002\003"
>> a
=> {:a=>"\002\003"}
>> a = Hash.new("")
=> {}
>> a[:a] << 2
=> "\002"
>> a[:a] << 3
=> "\002\003"
>> a
=> {}
|
|
|
Gente, desculpem a correria, mas estamos com umas situações novas aqui na empresa e bem corridos. Fiz meio “nas coxas” aqui mas acho que dá para ver que ele distribui os números para a galera usando umas “magias negras” do Hash.new. Aí é só aumentar o limite das pessoas e do limite numérico. No final tem uma checagem para ver se não houveram números repetidos. |
|
|
TaQ vc é O cara! hehe Valeu! Eu já tinha desenvolvivo uma soluçãozinha aqui mas nada comparada com essa sua versão! hehe É por isso que eu gosto do pessoal aqui.. eu pedi ajuda num método e já me passam uma versão do script inteiro funcionando e muito mais “elegante” do que eu tava fazendo.. :) Isso pq você tá numa correria… :p |
|
|
Mestre Taq Tiuzão Metaleiro! Nada como arranjar um tiu que manja :) |
|
|
Mas que #$#$#$ de #$#%$#$% de tio que é esse. :-) Sobre essas “magias negras” do Hash.new eu postei um lance interessante aqui, inclusive passei para o Luca que havia feito uma comparação do Fibonacci em Java e Ruby. Antes de usar o Hash.new eu costumava desenhar um pentagrama no chão, acender umas velas vermelhas e sacrificar um bode para esses lances obscuros. Aí uma vez minha sogra apareceu do nada no meio do pentagrama e eu parei com essas coisa do demo. Agora, só as em código. :-) |
|
|
Eu digo, e as pessoas não acreditam, que o Taq é esse cara aqui , ai depois ficam ai chorando as minguas… |
|
|
HUAHUAHUA! Boa Carlos! TaQ: A Fibonacci em uma linha fica bem criptica. Parece até formula para conjurar a sogr… digo, o cramulhão. =/ |
|
|
Só um detalhe besta: pode ser escrito: Tou pra “louse slayer” hoje, heim, tá louco? :p |
|
|
Putz… o TaQ me atiçou :) fiquei brincando aqui um pouco e cheguei nesse programinha
limit = 100
by_user = 5
users = %w[taq ronaldo arthur ronie carlos ghost]
sorted_array = (1..limit).to_a.sort_by { rand }
result = {}
users.each_with_index do |it, index|
min = index * by_user
result[it] = sorted_array[min, by_user]
end
result.each do |key, value|
puts key + ' - ' + value.join(", ")
end
- Editado: colocado pre pq code bagunçou o coreto - A única magia negra aí, bem legal, é essa linha: Ela cria um array de “limit” posições e bagunça o dito :D . Bastou ordenar por rand . Peguei esse truque daqui Esse code snippets é bem legal!!!! |
|
|
Falando em atiçar:
def lottery(users, total, per_user)
(1..total).sort_by(&:rand).inject(Hash[*users.zip([]).flatten]) { |r, i| r.each { |k, v| r[k] ||= []; r[k] << i and break if r[k].size < per_user }; r }
end
lottery(%w[taq ronaldo arthur ronie carlos], 100, 5).each do |user, values|
puts user + ": " + values.join(", ")
end
O lance do &:rand depende de você estar usando suporte a isso; assim, melhor testado em um console Rails. |
|
|
Vish! Ronaldo, o que impede, ou é que é preciso, pra ter esse suporte ao &:rand fora do Rails? |
|
|
É que o suporte a Symbol#to_proc, do qual o &:rand depende, só existe atualmente no Rails (a menos, é claro, que você tenha implementado em suas bibliotecas. A próxima versão do Ruby terá isso por default. |
|
|
Maluuuuucoooo!!! Preciso estudar mais isso o_O Viajei!!! Mas essa do &:rand é muito legal. Já tinha visto aqui no fórum “de outra feita”, mas tinha esquecido. Muito bom! |
|
|
Ou, vai fundir a cuca aí vai. :-) |
|
|
Um idioma que está me agradando muito no Rails é o tal do “expressão and comando” com if ou unless opcional. Você pode fazer algo como: redirect_to :controller => "login" and return unless session[:user] Eu acho que fica super-legível :-) Sobre o lance acima, eu confesso que abusei do inject. O coitado não foi feito para esse tipo de coisa. Mas a performance é relativamente boa porque nada é transformado duas vezes e os loops são pequenos. |

