Sobre macaca, macaca-de-auditório, macacal, macacão, macacar, macacarecuia, macacaria, macaco, macacoa*, macaco-adufeiro, macaco-aranha, macaco-barrigudo, macaco-cabeludo, macaco-da-meia-noite, macaco-da-noite macaco-de-bando, macaco-de-cheiro, macaco-inglês, macaco-japonês, macaco-narigudo, macaco-patrona, macaco-prego, macaco-prego-do-peito-amarelo e TI.

sábado, agosto 25, 2007

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:

At 12:02 PM, Anonymous Anônimo said...

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...

 
At 5:10 PM, Anonymous Zeh Oliveira said...

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

 
At 7:58 PM, Blogger RodrigoSol said...

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!

 
At 7:59 PM, Blogger RodrigoSol said...

Zeh.

Tomei a liverdade de postar seu codigo de IO aqui! Ficou muito legal!!!

 
At 9:07 PM, Anonymous Daniel F. Martins said...

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.

 
At 8:10 PM, Blogger Bermonruf said...

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

 
At 11:50 PM, Blogger Walter Cruz said...

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ô!

 
At 11:59 AM, Blogger RodrigoSol said...

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

 
At 1:06 PM, Blogger Walter Cruz said...

:)

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

 
At 1:47 PM, Blogger Bermonruf said...

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.

 
At 2:02 PM, Blogger RodrigoSol said...

Opa...

Os imports pra mim tambem nao conta.
Mera formalidade.

Daqui a pouco atualizo lá.

[]'s

 
At 5:49 PM, Blogger Walter Cruz said...

Tem a versão do Daniel Martins em smalltalk agora!

 
At 9:12 AM, Blogger RodrigoSol said...

Atualizado!

To querendo aprender smalltalk. Alguém indica um começo?

 
At 10:36 AM, Blogger Micox - Náiron J. C. G. said...

Este comentário foi removido pelo autor.

 
At 11:00 AM, Blogger Micox - Náiron J. C. G. said...

Opa, acho que fiz com 2 linhas em javascript. Alguém dá um bizu pra ver se tá valendo?

 
At 1:30 PM, Anonymous Diego Carrion said...

Macaco Chefe, por favor valida minah solução:

http://www.mouseoverstudio.com/blog/?p=23

 
At 9:32 PM, Anonymous Rafael said...

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); }

 
At 6:24 AM, Blogger Rodrigo Fante said...

Em javascript modificando o codigo do Micox e do Diego Carrion:

http://www.fazedordesite.com/blog/2007/09/07/code-contest-mega-sena-acumulada/

 
At 3:06 PM, Blogger Rodrigo said...

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";

 
At 4:08 PM, Anonymous Rodrigo Fenrrir said...

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]

 
At 4:13 PM, Blogger Rodrigo said...

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)}++ }

 
At 4:54 PM, Anonymous Rafael said...

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()));
}

 
At 4:58 PM, Anonymous Rodrigo Fenrrir said...

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]

 
At 6:04 PM, Blogger Rodrigo said...

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).

 
At 12:23 PM, Blogger RodrigoSol said...

Pessoal,

To viajando... Quando chegar atualizo o blog com as novas versões.

Abraços.

 
At 11:26 PM, Anonymous Vinícius said...

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

 
At 9:02 AM, Blogger RodrigoSol said...

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

 
At 10:03 AM, Blogger Rodrigo said...

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")))

 
At 1:53 PM, Anonymous Renan said...

essa linha em Perl vale?

print join(' ',(sort{$t{$b}<=>$t{$a}}grep(!$t{$_}++,map{(int rand 60)+1}1..1000))[0..5])."\n"

 
At 12:41 AM, Anonymous caio ariede said...

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

 
At 11:16 AM, Anonymous caio ariede said...

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

 
At 10:25 PM, Blogger Walker said...

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";

 
At 3:15 PM, Blogger lucas nogueira said...

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

 
At 6:12 PM, Anonymous Anônimo said...

o que eu estava procurando, obrigado

 
At 12:04 AM, Anonymous Anônimo said...

mesothelioma support and information!
[url=http://www.mesothelioma-support.org/]houston mesothelioma[/url]

 
At 11:17 AM, Anonymous Anônimo said...

Fiz em io language, em três linhas também: http://joseoliveira.com/2007/08/26/code-contest-em-tempos-de-mega-sena-acumulada/

 
At 11:17 AM, Anonymous Anônimo said...

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...

 
At 11:18 AM, Anonymous Anônimo said...

mesothelioma support and information!
[url=http://www.mesothelioma-support.org/]houston mesothelioma[/url]

 
At 11:20 AM, Anonymous buy viagra said...

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

 
At 11:21 AM, Anonymous Anônimo said...

Por outro lado, o que eu queria destar é flexibilidade dessa nova geração de linguagens dinâmicas que eu simplesmente acho fantástico!

 
At 11:22 AM, Anonymous buy viagra said...

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

 
At 10:09 PM, Anonymous Locutor Antonio Cezar said...

Acho que consegui diminuir alguma coisa, depois de usar um dos pequenos códigos daqui por algum tempo:


OBS: Não sou programador.

 
At 10:48 PM, Anonymous Locutor Antonio Cezar said...

Como o meu código não saiu aqui, coloquei ele em:
http://olocutor.com/m

 
At 5:19 AM, Anonymous Anônimo said...

Look At This buy tramadol with cod delivery - buy tramadol online australia no prescription

 

Postar um comentário

<< Home