Code Contest: Em tempos de Mega Sena Acumulada
Um pequeno desafio:
Escrever em qualquer linguagem de programação um programa que realize 100.000 sorteios de um numero entre 1 e 60 e mostre na tela os 6 mais freqüentes.
Ganha quem fizer o programa com o menor numero de linhas possíveis, lembrando que a linha considerada é a linha da unidade léxica da linguagem, portanto a seguinte linha em Java seria considerada duas: int i =0; sysout(i);
Fiz com 3 linhas em Ruby:
hist = Hash.new(0)
100000.times{|e| hist[1 + rand(60)] += 1}
hist.sort{|a,b| b[1]<=>a[1]}.to_a.slice(0,6).each{|e| puts "#{e[0]} --> #{e[1]}"}
Será possível fazer em menos linhas com Python, Groovy, Haskell ou Prolog? Em Ruby da pra fazer com menos? Citei essas porque acho quase impossível fazer com menos do que isso com Java, C/C++ ou C#, mas se alguém quiser provar o contrario...
Update II
Para ficar mais organizado novas Contribuições estão sendo postadas aqui.
Update
O ZehOliveira do GUJ fez com 3 linhas na interessantísima IO (Valeu Zé!):
h := Map;
100000 repeat(if(h hasKey(n := Random value(1, 60) round asString), h atPut(n, h at(n)+1), h atPut(n, 1)))
h asList sortBy(block(f, s, f at(1) > s at(1))) slice(v, 6) foreach(k, writeln(k at(0), " --> ", k at(1)))
O Daniel Martins também fez com 3 linhas em Groovy e em SmallTalk(Value Daniel!):
def hist = [:], v
100000.times{hist[v = 1 + Math.random() * 60 as int] = !hist[v] ? 1 : hist[v] + 1}
println hist.keySet().toList().sort{-hist[it]}[0..5].sort().join(‘,’)
| s |
s := ((OrderedCollection withAll: ((1 to: 100000) collect: [:each | 60 atRandom])) groupBy: [:each | each] having: [:each | true]) asSortedCollection: [:a :b | b size < style="">].
1 to: 6 do: [:each | Transcript show: ((s at: each) at: 1); cr]
E os grandes vencedores até agora são o Walter Cruz e o Bernado Rufino Perder eles não perdem, só se inventarem a meia linha. O caras fizeram em uma inacreditável linha:
Versão em Python do Walter Cruz:
x = [item for item in sorted([(k, len(list(g))) for k, g in groupby(sorted([randrange(1,61) for item in xrange(0,100000)]))],key=itemgetter(1),reverse=True)][:6]
print(x)
Versão em Ruby do Bernado Rufino:
Array.new(100000){rand(60)+1}.inject(Hash.new(0))
{|hash, i| hash if hash[i] += 1}.invert.sort.reverse[0..6].each{|t, n| puts "#{n}
repeated #{t} times"}
Por problemas no layout( que ja passou da hora de ser revisto) tive que quebrar a linha, mas acreditem é uma só;

44 Comments:
Realmente a linguagem é expressiva, em detrimento da legibilidade do código. Em Perl deve ser possível fazer com o mesmo número de linhas de código ou menos...
Fiz em io language, em três linhas também: http://joseoliveira.com/2007/08/26/code-contest-em-tempos-de-mega-sena-acumulada/
Usando a mesma lógica que tu usou. :D
Pois é.
Nesse caso o critério legibilidade foi para o espaço.
No dia-a-dia o bom senso nos impede (ou pelo menos deveria) de escrever esses ninhos.
Por outro lado, o que eu queria destar é flexibilidade dessa nova geração de linguagens dinâmicas que eu simplesmente acho fantástico!
Zeh.
Tomei a liverdade de postar seu codigo de IO aqui! Ficou muito legal!!!
Tomei a liberdade de escrever um programa em Groovy para solucionar esse desafio que você propôs (que, por sinal, é bem oportuno). :P
Abraço.
Com 1 linha em Ruby! Code Contest: Mega Sena em 1 linha!:
http://bermonruf.wordpress.com/2007/09/01/code-contest-mega-sena-em-1-linha
Hehehe.. Tirando as linhas dos import, foi praticamente só uma linha em python também :D. Mas esse código do Bernardo é uma coisa de doido sô!
Perdão Walter.
Nao conheco Python. Quando abri seu blog o print(x) tava na linha de baixo. Me enganei.
Irei atualizar aqui. Aproveito para perguntar: Lexicamente como eh uma linha em Python?
Abracos
:)
Bom, na verdade, lexicamente, a versão que te mandei são 5 linhas mesmo :(
Dá pra colocar em 4 linhas colocando o print em volta do cálculo, mas ainda assim são 3 a mais!
Então, apesar do cálculo ter sido em uma única linha, foram 3 de import, o que me deixa de fato, 4 linhas acima do campeão :D
Mas o que vale é a lógica e não os imports, por mim em uma linha também.
Aproveita e atualiza lá em cima, coloca o print em volta do cálculo.
Opa...
Os imports pra mim tambem nao conta.
Mera formalidade.
Daqui a pouco atualizo lá.
[]'s
Tem a versão do Daniel Martins em smalltalk agora!
Atualizado!
To querendo aprender smalltalk. Alguém indica um começo?
Este comentário foi removido pelo autor.
Opa, acho que fiz com 2 linhas em javascript. Alguém dá um bizu pra ver se tá valendo?
Macaco Chefe, por favor valida minah solução:
http://www.mouseoverstudio.com/blog/?p=23
Olá, uma possível solução em c++:
int main() { for(int freq[] =
{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,
35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60},
i = 0; i == 100000 ? printf("%d %d %d %d %d %d\n", freq[59]%100,
freq[58]%100, freq[57]%100, freq[56]%100, freq[55]%100,
freq[54]%100)*0 : 1;sort(freq, freq+sizeof(freq)/sizeof(int)), i++,
freq[rand()%60]+=100); }
Em javascript modificando o codigo do Micox e do Diego Carrion:
http://www.fazedordesite.com/blog/2007/09/07/code-contest-mega-sena-acumulada/
Opa, em Perl, isso vale como 2 linhas?:
for $i (1 .. 100000) { $h{int(rand()*60)+1}++; }
print join(' ', (sort { $h{$b} <=> $h{$a} } keys %h)[0..5]) . "\n";
Opa, eu também consegui uma solução em apenas uma linha, em python, tentei ao maximo fazer diferente da solução do Walter Cruz.
segue..
sorted([ (y,k) for x in [[ random.randint(1,60) for z in xrange(100000) ]] for k in xrange(1,60) for y in [x.count(k)] ], reverse=True)[:6]
Uma linha de Perl, muito parecida com a solução de Rafael em C++:
for (1..100001) { ($_ == 100001) ? print join(" ", (sort { $h{$b} <=> $h{$a} } keys %h)[0..5]) . "\n": $h{int(rand()*60+1)}++ }
outra versão em c++:
int main() {
for(vector< int> v(60,0),i(0,0); i[0] == 100060 ? printf("%d %d %d %d %d %d\n", v[59]%70, v[58]%70, v[57]%70, v[5 6]%70, v[55]%70, v[54]%70)*0 : 1; v[i[0] < 60 ? 59 - i[0] : (rand()%60)]+= i[0] < 60 ? i[0]+1 : 70, i[0]++, sort(v.begin(), v.end()));
}
Vi que na minha solução o for sobre y é completamente desnecessario.
Ficando como solução:
sorted([ (x.count(k),k) for x in [[ random.randint(1,60) for z in xrange(100000) ]] for k in xrange(1,61) ], reverse=True)[:6]
O resultado fica no formato
[(qntidade, numero), ...]
Caso seja necessario o formato (numero, qntidade) pode-se usar como parâmetro key na função sorted o itemgetter(1) como o Walter Cruz utilizou ou key=lambda x: x[1].
Segue a resposta noutro formato:
sorted([ (k,x.count(k)) for x in [[ random.randint(1,60) for z in xrange(100000) ]] for k in xrange(1,61) ], key=itemgetter(1), reverse=True)[:6]
Sim... só deixando de claro que a solução em Perl eu tomei cuidado só para usar recursos da linguagem, nada de importar módulos (use).
Pessoal,
To viajando... Quando chegar atualizo o blog com as novas versões.
Abraços.
Cara, tá aí o meu em PHP. 1 linha.
for ($i=0, $ns = array(); $i<=100000; $i++, $ns[rand(1, 60)]++, arsort($ns)) { } echo implode(", ", array_slice(array_keys($ns), 0, 6));
Se isso não for 1 linha me avisa que eu dou uma arrumada. =]
Abraço
Vinicius,
Se seguirmos a risca o que é lexicamente uma linha a maioria não das contribuições nao poderia ser considerada... Mas quer saber, o objetivo real era mostrar a expressividade de uma linguagem e seu exemplo mostra como PHP poder bem expressivo.
Daqui a pouco atualizo.
[]'s
Opa,
To aprendendo elisp e resolvi fazer uma versao para meu Emacs. Assim fica mais fácil escolher os números que vou apostar na mega-sena semana que vem :-)
Ficou gigante, espero poder reduzir esse código qdo tiver dominando mais Elisp:
(defun mega-sena ()
(interactive)
(let ((l ())
(n 100000)
i)
(dotimes (count 60)
(setq l (cons `(,(- 60 count) . 0) l)))
(while (> n 0)
(setq i (random 60))
(setcdr (car (nthcdr i l)) (1+ (cdr (car (nthcdr i l)))))
(setq n (1- n)))
(setq l (sort l (lambda (a b) (> (cdr a) (cdr b)))))
(setq n 0)
(while (< n 6)
(insert (format "%d " (car (car l))))
(setq n (1+ n))
(setq l (cdr l)))
(insert "\n")))
essa linha em Perl vale?
print join(' ',(sort{$t{$b}<=>$t{$a}}grep(!$t{$_}++,map{(int rand 60)+1}1..1000))[0..5])."\n"
Outro code em PHP..
-
$i=0;while(1){$r=rand(1,60);$t[$r]++;if(++$i==100000)die(arsort($t).join(',',array_splice(array_keys($t),1,6)));}
-
[]s
Opa! uma pequena modificação..
$i=0;while(1){$t[rand(1,60)]++;if(++$i==100000)die(arsort($t).join(',',array_splice(array_keys($t),1,6)));}
[]s :D
PHP, 2 linhas(primeira tentativa)
Desculpem a cadeia de chamadas de array. mas para o resultado ficar organizado soh assim mesmo ;).
for($x = 0; $x < 100000; $x++, $i = mt_rand(1,60) ) $ar[$i] = (!isset($ar[$i]))?array(1,$ i):array($ar[$i][0]+1,$i);
echo ( (rsort($ar) and ($ar=array_slice($ar,0,6)) )?"":"" )."{$ar[0][1]}: {$ar[0][0]} vez es - {$ar[1][1]}: {$ar[1][0]} vezes - {$ar[2][1]}: {$ar[2][0]} vezes - {$ar[3][1]}: {$ar[3][0]} vezes - {$ar[4][1]}: {$ar[4][0]} vezes - {$ar[5][1]}: {$ar[5][0]} vezes";
solução em python:
from random import randint
l , ct = [] , {}
while len(l) <= 100000: l += [ randint(1,60) ]
for x in l: ct[x] = l.count(x)
count = ct.values()
count.sort()
for n in ct.keys():
if ct[n] == count[len(count)-1] or ct[n] == count[len(count)-2] or ct[n] == count[len(count)-3] or ct[n] == count[len(count)-4] or ct[n] == count[len(count)-5] or ct[n] == count[len(count)-6] : print n
o que eu estava procurando, obrigado
mesothelioma support and information!
[url=http://www.mesothelioma-support.org/]houston mesothelioma[/url]
Fiz em io language, em três linhas também: http://joseoliveira.com/2007/08/26/code-contest-em-tempos-de-mega-sena-acumulada/
Realmente a linguagem é expressiva, em detrimento da legibilidade do código. Em Perl deve ser possível fazer com o mesmo número de linhas de código ou menos...
mesothelioma support and information!
[url=http://www.mesothelioma-support.org/]houston mesothelioma[/url]
Se for necessário formatar o claro (qntidade número) pode ser usado como um parâmetro essencial na função ordenados itemgetter (1), Walter Cruz ou usado key = lambda x: x, que é muito prático
Por outro lado, o que eu queria destar é flexibilidade dessa nova geração de linguagens dinâmicas que eu simplesmente acho fantástico!
Se for necessário formatar o claro (qntidade número) pode ser usado como um parâmetro essencial na função ordenados itemgetter (1), Walter Cruz ou usado key = lambda x: x, que é muito prático
Acho que consegui diminuir alguma coisa, depois de usar um dos pequenos códigos daqui por algum tempo:
OBS: Não sou programador.
Como o meu código não saiu aqui, coloquei ele em:
http://olocutor.com/m
Look At This buy tramadol with cod delivery - buy tramadol online australia no prescription
Postar um comentário
<< Home