quarta-feira, 25 de setembro de 2013

Desafio: bolas brancas e pretas

Os primeiros posts têm de ser um pouco mais genéricos para dar alguma base para o futuro.
Para quebrar um pouco esta rotina inicial, sugiro um desafio inspirado num problema do SPOJ e que pode ser feito a qualquer pessoa.

Desafio: bolas brancas e pretas

Imaginem que têm uma caixa de mágico com um certo número de bolas brancas e pretas.
Enquanto a caixa contém mais do que uma bola, retiram aleatoriamente 2 bolas da caixa:

  • Se as 2 bolas retiradas têm a mesma cor, então colocam uma bola branca na caixa 
  • Se as 2 bolas tiverem cores diferentes, então colocam uma bola preta

Em ambos os casos, as 2 bolas retiradas não voltam para a caixa. Assim, dado o número inicial de bolas brancas e bolas pretas, qual é a cor da bola que resta na caixa?

Exemplos:

  • 1 bola branca e 1 bola preta. As 2 bolas retiradas têm cores diferentes, é colocada uma bola preta. Só sobra 1 bola preta.
  • 2 brancas e 0 pretas. Retiram-se 2 bolas brancas e coloca-se 1 bola branca na caixa.
  • 2 brancas e 1 preta. Se retirarmos primeiro as 2 bolas brancas, ficamos com 1 bola branca e 1 preta na caixa. Como vimos acima, o resultado é uma bola preta. Se começarmos por retirar 1 branca e 1 preta, adiciona-se 1 preta e voltamos a ter 1 branca e 1 preta. Em qualquer caso, o resultado é ficarmos com 1 bola preta.

E se fossem 5555555 bolas brancas e 5555555 pretas? Ou 10000000 brancas e 10000000 pretas?
Conseguem descobrir o truque para responder a qualquer caso? :-)



quinta-feira, 19 de setembro de 2013

Sou o maior da minha aldeia, mas.. isso significa alguma coisa?

Já conheço o CodeChef há bastante tempo, mas só nas últimas férias, em Agosto, decidi participar no seu concurso mensal. Estes concursos mensais decorrem no inicio de cada mês, contêm 10 problemas que os concorrentes podem tentar resolver durante os 10 dias de prova.

Após 2 concursos, Agosto e Setembro, já sou o #1 português do ranking de concursos longos (os de 10 dias). Sim, sou o maior da minha aldeia, mas.. na prática .. isso significa alguma coisa?

Por um lado, a minha participação é puramente por hobby, for fun. No concurso de Setembro, dediquei algumas horas (de 1 dos 10 dias) ao concurso e resolvi 6 dos 10 problemas.
Por outro lado, e mais importante do que isso, só há 14 portugueses a participar no CodeChef. Além disso, não se sabe se eles estão a dedicar-se mais ou ainda menos do que eu. Mais ainda, não se sabe se são muito bons, medianos ou medíocres.

Este é apenas um exemplo do quão enganosos os números podem ser. Na prática, estes números não significam nada.
Eu cheguei a ter colegas na escola que só decidiam se ficavam satisfeitos ou tristes com uma nota depois de saber as notas dos outros. Esta mentalidade é muito comum e é um grande erro. Nós devemos aproveitar o contacto com as pessoas à nossa volta para aprender o máximo possível, mas estas pessoas não devem nunca definir os nossos limites ou os nossos objectivos.

Por todos estes motivos, o meu lema nunca foi tentar ser o melhor da turma ou da minha aldeia, mas sim tentar sempre aprender mais e melhorar as minhas competências. Usando uma analogia do futebol, o que acham melhor: ser o melhor jogador a actuar nos campeonatos distritais ou fazer parte da equipa campeã nacional?

Citando William Faulkner,

Always dream and shoot higher than you know you can do. 
Don't bother just to be better than your contemporaries or predecessors.
Try to be better than yourself.

quarta-feira, 18 de setembro de 2013

Preparação para concursos de programação

Estamos no início do ano lectivo e isso também significa que a nova temporada de concursos de programação (mais escolares) também está prestes a iniciar-se.

Os alunos do ensino básico e secundário são elegíveis para as Olimpíadas Nacionais de Informática (ONI) e têm a hipótese de serem seleccionados para representar Portugal nas Internacionais, International Olympiad in Informatics (IOI) 2014, em Taiwan. Por seu turno, os alunos universitários poderão competir na Maratona Inter-Universitária de Programação (MIUP) já em Outubro, de modo a qualificarem-se para o South Western European Regional Contest (SWERC), concurso da nossa zona europeia que permite o acesso à final mundial do International Collegiate Programming Contest (ICPC) da ACM.

Independentemente do nível de ensino, a pré-condição fundamental para participar é saber programar. A maioria dos concursos suportam as linguagens C, C++, Java e Pascal. Assim, o primeiro passo é escolher uma delas, estudá-la e praticar para se ser tão proficiente quanto possível.
O C++ é a linguagem mais popular e é a minha linguagem favorita. No entanto, um dos "erros" mais comuns é a falta de conhecimento da Standard Template Library, particularmente os diversos algoritmos já disponíveis na biblioteca algorithm (sort, lower_bound, upper_bound, next_permutation, etc).

Os problemas colocados nestas provas devem ser resolvidos com um programa desenvolvido pelos concorrentes. Para além destes programas serem obrigados a dar as respostas correctas, existem também restrições quanto ao tempo disponível para calcular as respostas e à memória (do computador) disponível.
Assim, os concorrentes devem encontrar as ideias certas para resolver os problemas de forma eficiente, isto é, encontrar o Algoritmo certo para resolver os problemas e implementá-lo usando uma linguagem de programação.

Infelizmente, não conheço muitos recursos em português apropriados para a aprendizagem de algoritmos. As ONI criaram um espaço chamado Academia ONI que contém alguns artigos: "Noções Básicas de Análise de Algoritmos", "Tipos de Problemas" comuns em concursos e "Pesquisa Completa" de soluções. O forum Portugal-a-Programar contém uma secção de Algoritmia e Lógica, da qual recomendo um artigo sobre Grafos.

Dada esta escassez, convém dominar o inglês e explorar tanto os livros como a internet.
A Ciência da Computação é uma área muito vasta. Existem diversos tipos de algoritmos diferentes. Este conhecimento está tipicamente melhor estruturado nos bons livros:

  • O meu preferido é o Introduction to Algorithms. Este pode ser considerado uma bíblia e é um pouco difícil de seguir mas é um recurso fenomenal.
  • Programming Challenges é um livro escrito especialmente para concursos e é encontrado facilmente online. 
  • Na disciplina de algoritmos na faculdade, era recomendado o Data Structures and Algorithm Analysis in C++, este não é tão completo mas o autor é bastante claro nas suas explicações. 
  • Outro livro muito recomendado é o Algorithm Design Manual, mas não o conheço.

Contudo, muitas vezes, quem está a começar nestas coisas não tem ainda vontade de estudar um livro, especialmente os mais jovens (eu também não tinha!). Existem outros tipos de recursos:

  • programa de treino da USACO é uma plataforma de treino para as olimpíadas de informática. Não conheço melhor recurso online para aprender algoritmos e estruturas de dados. Está dividido por módulos que contêm tanto textos de apoio como exercícios para aplicar os conhecimentos transmitidos nesses textos.
  • Tutoriais curtos e objectivos. Eu recomendo vivamente os artigos referidos anteriormente em português, assim como os tutoriais do TopCoder.
  • Existem cada vez mais cursos online. A disciplina de desenho e análise de algoritmos da Universidade de Stanford é oferecida no Coursera, estando dividida em parte 1 e parte 2.

À medida que os conhecimentos são adquiridos e fortalecidos, é importante exercitar estes conhecimentos. Existem diversos judges online como o Sphere Online Judge. Estes judges disponibilizam um conjunto vasto de problemas e os utilizadores podem resolve-los livremente como treino.
Além dos judges, existem outros sites como o TopCoder, o Codeforces e o CodeChef que organizam competições de treino (normalmente há pelo menos 1 por semana) e é publicado um editorial depois de cada concurso que explica como se poderiam resolver os exercícios.

O post já vai longo, mas já deu certamente para perceber uma coisa: é preciso trabalho, trabalho, trabalho. Tal como em tudo na vida, não existem fórmulas mágicas. No entanto, quem corre por gosto, não cansa :-)

sábado, 14 de setembro de 2013

Olá Mundo

Cara world wide web,

Tal como em outras situações na minha vida, aqui estou eu a fazer algo que nunca pensei que faria: a iniciar um blog. O meu nome é Miguel Oliveira, tenho um mestrado em engenharia informática e sou aluno de doutoramento na Faculdade de Engenharia da Universidade do Porto.

Desde cedo que as aulas foram um aborrecimento - tudo demasiado fácil - as quais culpo, em parte, pelo meu vício de roer as unhas :-) No entanto, no 10º ano aprendi a programar e surgiu desde logo a paixão pela resolução de desafios com recurso à programação. Desde então ganhei vários concursos, medalhas de ouro e bronze nos concursos da nossa zona europeia do International Collegiate Programming Contest e fiquei entre o top 500 do Google Code Jam 2009.

Pelo caminho, já resolvi mais de 1000 problemas online (na verdade, já perdi a conta mas dá para ter uma ideia), sendo neste momento o 29º do ranking mundial do Sphere Online Judge (em mais de 100 000 utilizadores). Estes desafios continuam a ser um hobby e continuo a participar em forums online como o Portugal-a-Programar ou o do TopCoder, onde procuro ajudar quem está com dificuldades em algum exercício.

No ano passado fiz um estágio como Software Engineer na Google e foi uma experiência muito enriquecedora. Há algumas semanas, um rapaz que estava em entrevistas para a Google pediu-me umas dicas e lançou a ideia de criar um blog com conteúdos em português. De facto, foi algo que me fez muita falta quando estava a começar nestas coisas. Ele tinha em mente algo mais a sério, mas este blog pretende transmitir alguns dos conhecimentos que fui adquirindo ao longo do tempo, assim como apresentar desafios que considere interessantes quer para participantes em concursos, quer para desafiar os amigos em conversa de café :-)

Miguel Oliveira

PS: espero que este blog também ajude a melhorar a proficiência na escrita, que é algo que bem preciso...