Google Code Jam

06/20/2008 14:35:00 By Felipe Pessoto

O desafio mundial da Google aos melhores programadores do mundo e que consiste em resolver quatro problemas de algoritmos no menor tempo possível está com inscrições abertas até o próximo dia 17 de julho. A finais regionais acontecerão em Belo Horizonte, em outubro.

Os 500 melhores classificados ganharão uma viagem com tudo pago para as semifinais na capital mineira, de onde serão selecionados os 100 primeiros para a grande final na sede da Google em Mountain View. Além da viagem, também há prêmios em dinheiro:

· 1º lugar: US$ 10 mil

· 2º lugar: US$ 5 mil

· 3º lugar: US$ 2,5 mil

· 4º - 10º lugares: US$ 1,5 mil cada

· 11º - 30º lugares: US$ 1 mil cada

· 31º - 50º lugares: US$ 750 cada

· 51º - 75º lugares: US$ 500 cada

· 76º - 100º lugares: US$ 250 cada

Citando o comunicado da imprensa:

Uma novidade do Google Code Jam 2008 é a inserção de ferramentas próprias que permitem que os participantes programem em qualquer linguagem. Essas ferramentas foram criadas por uma equipe de funcionários que dedica 20% do seu horário de trabalho a projetos inovadores de seu interesse, e que é formada também por vencedores de Code Jams passados.



Nada mal, faturar um trocado, ter seu nome estampado com glória em sites geek pelo mundo afora e conseguir uma vaguinha em Montain View. Mas não pense que a coisa é fácil... em 2006, para se ter uma idéia, o vencedor latino-americano foi o carioca Fábio Dias Moreira, com um total de 753,4 pontos. Já o campeão mundial foi o russo Petr Mitrichev, com 972,02!

Via: Meio Bit

Nota: Fiz o primeiro teste prático(Alien Numbers). E não é fácil, mas também não é impossível. Demorei 2 horas pra criar o algoritmo, ficaria um pouco atrás do segundo colocado neste teste. Recomendo pra quem quiser praticar um pouco de lógica.

Computação Paralela - CTP de Junho

06/03/2008 08:48:00 By Felipe Pessoto

Saiu o Community Technology Preview da Extensão para Computação Paralela para .Net 3.5.

"Parallel Extensions to the .NET Framework is a managed programming model for data parallelism, task parallelism, and coordination on parallel hardware unified by a common work scheduler. Parallel Extensions makes it easier for developers to write programs that scale to take advantage of parallel hardware by providing improved performance as the numbers of cores and processors increase without having to deal with many of the complexities of today’s concurrent programming models.

Parallel Extensions provides library based support for introducing concurrency into applications written with any .NET language, including but not limited to C# and Visual Basic."


Download

Mais Informações

MSDN Magazine - Maio 2008

06/03/2008 08:34:00 By Felipe Pessoto

Está disponível a edição de Maio da MSDN Magazine. Assuntos de capa:


  • Aplicativos do Office: Integração do VSTO aos tipos de conteúdo do SharePoint
    Veja como criar uma personalização do Visual Studio Tools for Office em nível de documento e integrá-la a um tipo de conteúdo no SharePoint.
    Steve Fox

  • MOSS 2007: Implantação automatizada de aplicativos Web com a API do SharePoint
    Saiba como automatizar implantações de aplicativo do SharePoint personalizado, usar a API do SharePoint e evitar a dificuldade das definições de site personalizadas.
    E. Wilansky, P. Olszewski, and R. Sneddon

  • C++ Plus: Reforce os aplicativos Windows com o Feature Pack do Visual C++ 2008
    Kenny Kerr faz grandes elogios ao novo Feature Pack do Visual C++ 2008, que apresenta recursos convenientes e modernos para o Visual C++.
    Kenny Kerr

  • Segurança: Autenticação mais segura com a solução de senha One-Time Password Solution
    As senhas únicas oferecem soluções para ataques de dicionário, phishing, interceptação e muitas outras violações de segurança. Eis como tudo funciona.
    Dan Griffin

  • Sopa de letrinhas: Uma pesquisa sobre linguagens e paradigmas .NET
    Apresentamos aqui um resumo dos vários paradigmas das linguagens baseadas no CLR por meio de introduções rápidas e exemplos de código.
    Joel Pobar


Download em Português

Covariância e Contravariância em C#, Parte Sete: Por que precisamos de uma sintaxe para tudo?

05/16/2008 09:12:00 By Felipe Pessoto

Suponha que estamos implementando interface genérica e variância delegada em um futura versão hipotética do C#. Como, hipoteticamente, deveria ser a sintaxe? Há muitas opções que poderíamos considerar.

Antes de pensarmos nas opções, nos perguntamos, "E se não tivermos uma sintaxe para tudo?" Por que não inferimos a variância para o desenvolvedor, de modo que tudo apenas magicamente funcione?

Infelizmente isso não existe, por várias razões.

Primeira, assim parece que a variância devia ser algo que você deliberadamente implementa em sua interface ou delegate. Fazendo isso você começa a perder o controle do objetivo que o usuário busca.

Fazer isso "automagicamente" também significa que, assim como o processo de desenvolvimento e métodos forem adicionados às interfaces, a variância da interface pode mudar inesperadamente. Isto pode introduzir inesperadas e profundas mudanças em outros pontos do programa.

Segundo, tentar fazer isso introduz um novo tipo de ciclo à análise da linguagem. Nós já temos que detectar coisas como ciclos nas classes base, ciclos na interfaces base e ciclos nas regras de tipos genéricos, então em teoria não tem nenhuma novidade. Mas na prática, há alguns problemas.

No artigo anterior não discutimos sobre restrições adicionais que nós precisamos para criar interfaces variantes. Uma restrição importante é que a interface variante que herda de outra interface variante deve fazer de uma maneira que não introduza problemas no sistema de tipos. Basicamente, todas as regras para quando um tipo de parâmetro pode ser covariante ou contravariante precisam "fluir" para a interface base.

Por exemplo, suponha que o compilador esteja tentando deduzir a variância neste programa:

interface IFrob<T> : IBlah<T> { }
interface IBlah<U>
{
    IFrob<U> Frob();
}

E nos perguntamos "é válido para T ser variante em IFrob<T>?" Para responder esta pergunta, nós precisamos determinar se é válido para U ser variante em IBlah. E para responder esta pergunta nós precisamos saber se válido para U ser variante no tipo de saída IFrob<U>, e...voltamos do ponto que começamos!

Não queremos que o compilador entre em um loop infinito quando compilar este programa. Mas esta claro que este programa é perfeitamente válido. Quando detectarmos um ciclo nas classes base, podemos parar e dizer "Seu programa é inválido". Mas não podemos fazer isso aqui. É uma questão complicada.

Terceiro, mesmo se pudéssemos descobrir uma maneira de resolver o problema do ciclo, nós ainda teríamos um problema com o caso acima. Ou seja, há três possíveis respostas logicamente consistentes: "ambas invariantes", "+T, +U" e "-T, -U" todas produzem programas que seriam typesafe. Como podemos escolher?

Podíamos começar em situações ainda piores:

interface IRezrov<V, W>
{
    IRezrov<V, W> Rezrov(IRezrov<W, V> x);
}

Nesta interface louca podemos deduzir que "ambas invariantes", <+V, -W> e <-V, +W> são todas as possibilidades. Novamente, como escolher?

E quarto, mesmo se pudéssemos resolver todos esses problemas, suspeito que o desempenho de tal algoritmo seria potencialmente muito ruim. Isto tem tudo para ter um "crescimento exponencial". Temos outros algoritmos exponenciais no compilador, mas prefiro não adicionar mais, se podemos evitar.

Assim, se adicionarmos interface e variância delegada em uma hipotética futura versão do C#, precisamos dar uma sintaxe para ela.

Covariância e Contravariância em C#, Parte Seis:Variância de Interface

05/14/2008 16:12:00 By Felipe Pessoto

Nos posts passados nós discutimos como seria possível tratar um delegate como contravariante nos seus argumentos e covariante no seu tipo de retorno. Um delegate é basicamente um objeto que representa uma chamada de função. Nós podemos fazer estes mesmos tipos de coisas para outros que representam chamadas de funções. Interfaces, por exemplo, são contratos que especificam qual o conjunto de chamadas de função que estão disponíveis em um objeto em particular.

Isto quer dizer que nós devemos extender a noção de variância para definições de interface também, usando as mesmas regras que nós temos para delegates. Por exemplo, considere:

public interface IEnumerator<T> : IDisposable, IEnumerator
{
    new T Current { get; }
}

Aqui nós temos uma interface genérica onde o único uso de parâmetro está em uma posição de saída. Poderíamos, assim, considerar o parâmetro covariante. Isso significaria que seria válido atribuir um objeto que implementa IEnumerator<Girafa> para uma variável do tipo IEnumerator<Animal>. Desde que o usuário daquela variável irá sempre esperar um Animal, e a nossa implementação irá sempre produzir uma Girafa, fica tudo ok.

Então temos IEnumerator<+T>, então nós podemos perceber que IEnumerable<T> é definido como:

public interface IEnumerable<T> : IEnumerable
{
    new IEnumerator<T> GetEnumerator();
}

Novamente, o parâmetro aparece somente em uma posição de saída, então nós poderiamos ter IEnumerable<+T> covariante também.

Isto então abre uma janela de assassinatos de bons cenários. Hoje, este código deve falhar na compilação:

void AlimentarAnimais(IEnumerable<Animal> animals)
{
    foreach (Animal animal in animals)
        if (animal.Faminto)
            Alimentar(animal);
}
...
IEnumerable<Girafa> GirafasAdultas = from g in girafas where g.Age > 5 select g;
AlimentarAnimais(GirafasAdultas);

Porque GirafasAdultas implementa IEnumerable<Girafa>, não IEnumerable<Animal>. No C# 3.0 você tem que fazer um idiota e dispendiosa operação de conversão para fazer isto compilar, algo como:

AlimentarAnimais(GirafasAdultas.Cast<Animal>());

ou

AlimentarAnimais(from g in GirafasAdultas select (Animal)g);

Ou seja o que for. Esta declaração explícita não deveria ser necessária. Diferente de arrays (que são leitura-escrita) é perfeitamente seguro tratar uma lista de Girafas read-only como uma lista de Animais.

Do mesmo modo, poderíamos tornar:

public interface IComparer<-T>
{
    int Compare(T x, T y);
}

uma interface contravariante, desde que o tipo fosse usado somente em posições de entrada. Você poderia, então, implementar um objeto que compara dois Animais e usá-lo em um contexto onde você precisa de um objeto que compare duas Girafas sem se preocupar com problemas no sistema de tipos.