Code Contest: Em tempos de Mega Sena Acumulada

18 respostas
RodrigoSol

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]&lt=&gta[1]}.to_a.slice(0,6).each{|e| puts "#{e[0]} --&gt #{e[1]}"}

Será possível fazer em menos linhas com Python, Groove, 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…

18 Respostas

sergiotaborda

Esse desafio é meio furado… repare que vc está usando logo para começar Hash ( que suponho seja algo como Map)… logo ai tem um monte de linhas de codigo disfarçadas de objeto.
Se formos por essa linha em java vc faz com 1 linha

(new Desafio()).solve()

:smiley: :lol: :lol:

[adicionado]
O que quero dizer é que deveria ser explicito se se pode criar ou não classes especiais.
Se for usar só as classes padrão do Java tlv não dê para fazer em 3 linhas ou menos, mas se criar algumas
classes utilitárias concerteza dá.
[/adicionado]

RodrigoSol

Acho que voce nao entendeu o espirito da coisa, mas tudo bem…

Voce pode criar quantas classes quiser, mas cada linha que vc tiver digitado sera contada. Entao se seu metodo solve() tem 10 linhas mais a linha da chamada teriamos 11.

Alem disso, da forma que voce colocou, um simples “TESTE”.equals(“TESTE”) teria varias linhas ja que o metodo equals() eh feito de um metodo com N linhas.

sergiotaborda

Divirtam-se!

A

Em Scala (acho que não deve ser difícil implementar em menos linhas, mas gostei dessa versão):

/** Função que retorna uma sequência infinita de aleatórios entre 1 e 60*/
def randoms = {
   val rng = new Random
   def rstream():Stream[Int] = Stream.cons(rng.nextInt(60) + 1, rstream())
   rstream()
}

/** Retorna um Map associando valores a freqüencias. Note o uso do foldLeft (aka /: )*/
def hist(count:Int) = (Map[Int,Int]().withDefaultValue(1) /: randoms.take(count)) {
   case (map, rnd) =&gt map + rnd -&gt  (map(rnd) + 1)
}

hist(100000).toList sort {case ((_, c1), (_, c2)) if (c1 &gt= c2) =&gt true; case _ =&gt false} take 6 map {case (a,b) =&gt a+"  --&gt  "+b} foreach (println(_))
//Evil shit nessa última linha: Decomposição das tuplas por pattern matching; Sintaxe de chamada de método sem "."; 
//   parâmetros padrão em funções anônimas com "_"
T

O problema resolvido em Java. Deu 13 linhas, mas acho que este programa tem dois problemas:

  • Não serve para um número de sorteios maior que 33.554.431 (leia o programa e me diga por quê)
  • Uso um truque um pouco sujo (guardar dois números dentro de um "int"), que poderia muito bem ser feito em C, C++ ou Fortran.
class Sorteio {
    public static void main(String[] args) {
        int[] hist = new int[60];
        java.util.Random r = new java.util.Random();
        for (int i = 1; i &lt= 100000; ++i) 
            hist[r.nextInt(60)]++;
        for (int i = 0; i &lt 60; ++i)
            hist[i] = (hist[i] &lt&lt 6) | i;
        java.util.Arrays.sort (hist);
        for (int i = 59; i &gt= 54; --i)
            System.out.printf ("n = %2d =&gt freq= %d%n", 1 + (hist[i] & 0x3F), hist[i] &gt&gt&gt 6);
    }
}
RodrigoSol

Muito Bacana esta solucao…

Acredito que a limitacao vem dos 6 bits ou 2^6 que voce usou pra guardar o numero sorteado. Nesse caso sobrariam 2^25 que da 33,554,432. Mas o inteiro tem 32 bits ne? 6 + 26 + 1 do sinal = 32.

Agora nao entendi o 1 que ficou faltando da subtracao de 33.554.432 por 33.554.431?

RodrigoSol

thingol:

  • Uso um truque um pouco sujo (guardar dois números dentro de um "int"), que poderia muito bem ser feito em C,

Cara… Trabalho com um pouco de codigo em ALGOL e posso dizer que esse truque eh muito usado. Eh comum, por exemplo, guardar os 3 indices de uma matriz de 3 dimensoes em um REAL (que tem 48 bits). Isso te permite indexar 64k em cada dimensao. Junte a isso o DEFINE (parece com o do C, mas pode ser parametrizado) e temos codigo do tipo:

result := mat[IDX] para acessar o elemento na matriz.

T

A solução abaixo também é grande e ainda por cima requer Java 6.0. Entretanto, é completamente estúpida (nenhuma coisa esquisita) e tem 19 linhas. Uma coisa que faz falta no Java é a parte de processamento de listas, presente nas linguagens funcionais e em muitas linguagens de script.

import java.util.*;
class Sorteio {
    public static void main(String[] args) {
        Map<Integer,Integer> hist = new TreeMap<Integer,Integer>();
        java.util.Random r = new java.util.Random();
        for (int i = 1; i &lt= 100000; ++i) {
            int x = r.nextInt (60) + 1;
            hist.put (x,  hist.get(x) == null ? 1 : hist.get(x) + 1);
        }
        NavigableMap<Integer,Integer> inverseHist = new TreeMap<Integer,Integer>();
        for (Map.Entry<Integer,Integer> entry : hist.entrySet()) 
            inverseHist.put (entry.getValue(), entry.getKey());
        int i = 0;
        for (Integer freq : inverseHist.descendingKeySet()) {
            if (++i &gt 6) break;
            System.out.printf ("n = %2d =&gt freq = %d%n", inverseHist.get(freq), freq);
        }
    }
}
Z

Em io language:

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) &gt s at(1))) slice(0, 6) foreach(k, writeln(k at(0), " --&gt ", k at(1)))

T

Em C++/STL deu 17 linhas. A solução é praticamente igual à do Java 6.0.

#include <map>
#include <cstdio>
#include <ctime>
int main (int argc, char*argv[]) {
    srand(time(0));
    std::map<int,int> hist, reverse_hist;
    for (int i = 1; i <= 100000; ++i) {
        int x = (rand() % 60) + 1;
        hist[x]++;
    }
    for (std::map<int,int>::iterator it = hist.begin(); it != hist.end(); ++it) 
        reverse_hist[it-> second] = it-> first;
    std::map<int, int>::reverse_iterator it = reverse_hist.rbegin();
    for (int i = 1; i <= 6; ++i, ++it) {
        printf ("%2d => %d\n", it-> second, it-> first);
    }
}
RodrigoSol

thingol,

Porque aquela diferença de 1 no seu primeiro exemplo?
Fiquei curioso…

T

Ora, para fazer uma analogia: (é mais fácil pensar com números pequenos que grandes)
se um campo tem 4 bits, ele só pode conter valores de 0 até (2 elevado a 4) - 1, ou seja, 15. O número 16 requer 5 bits (10000 em binário). Certo?

A

RodrigoSol, ALGOL? Fiquei curioso, para que tipo de plataforma é a aplicação?

GiancarloBraga

Confesso que fiquei curioso também.
Será você uma das excessões que entende o ALGOL 68? :smiley:

RodrigoSol

Confesso que fiquei curioso também.
Será você uma das excessões que entende o ALGOL 68? :D

Pois é. Conheço um pouco, na verdade ainda estou aprendendo. Trabalho numa aplicação que é bastante heterogênea, tem Java/VB/PL-SQL na baixa e COBOL/ALGOL no mainframe.

Linguagens de programação é o tópico dentro da computação que eu mais gosto, seja programar ou estudar o design. Gosto de linguagens OO, Procedurais, Funcionais e Lógicas, e não tenho preconceito. Tem alguns programas em ALGOL aqui com mais de 20 anos que foram magistralmente escritos. Os caras pensaram em cada detalhe que vocês ficariam impressionados. Acho que muito disso é por casa das limitações que existiam.

Atualmente, uma das coisas que estou trabalhando é na integração de Ruby com mainframes.

Vocês ainda trabalham com Algol? A única pessoa que freqüenta essas bandas que eu sei que ja trabalhou é o Luca.

Luca

Olá

Na verdade nunca trabalhei com Algol. Aprendi Algol porque precisei converter coisas de Algol para Fortran. O Algol era muito usado nos velhos tempos do Burroughs, hoje Unisys. Era uma linguagem muito poderosa. Dois amigos meus da COPPE, daquela turma que desenvolveu a tecnologia de TI usada na prospeção de petróleo em águas profundas, desenvolveram um sistema muito avançado em Algol e na época eles chegaram a dizer que Algol era o que havia de melhor para sistemas científicos. Um destes amigos é hoje um dos grandes nomes na área de data mining no Brasil. Acho que nem lembram mais de Algol.

[]s
Luca (trabalhando ainda com Fortran)

GiancarloBraga

Não programo ALGOL não.

Mas na matéria de ‘Linguagens de programação’ na faculdade eu li um pouco sobre o ALGOL, suas versões. Acho um assunto muito interessante.

RodrigoSol

Luca:
Olá
O Algol era muito usado nos velhos tempos do Burroughs, hoje Unisys.

Esse é o meu caso. Trabalho na Unisys. Tem muito projeto rodando Algol até hoje.

Criado 25 de agosto de 2007
Ultima resposta 27 de ago. de 2007
Respostas 18
Participantes 7