terça-feira, 31 de dezembro de 2013


E depois de muito sofrimento eu cheguei a uma conclusão que muita gente já deve conhecer: 
Aprender dói, mas não dói pouco, dói muito!

Apesar disso, a boa notícia é que todo aprendizado é gratificante. Cheguei a esta conclusão depois que comecei a programar usando o editor Vim. Durante muito tempo eu evitei usá-lo porque achava que nada era mais cômodo que os outros editores, além de não entender a necessidade de digitar tantos comandos para alterar um simples arquivo!
Depois de muita resistência, decidi encarar o Vim e hoje posso dizer que foi umas das melhores coisas que eu fiz. No início, foi muito complicado, mas depois de uma semana eu já estava mais familiarizado com os comandos. Gostaria que outros programadores também conhecessem o Vim, por isso farei alguns tutorias e postarei aqui no blog. Espero que vocês gostem ou não!


@CompilouSemErro

Posted on terça-feira, dezembro 31, 2013 by Unknown

No comments

quinta-feira, 31 de outubro de 2013


O CompilouSemErro também está no Twitter, lá postamos diariamente várias dicas sobre Linux e programação, não deixem de conferir, sigam @CompilouSemErro e fiquem por dentro do mundo Linux.

Confiram as melhores da semana:






@CompilouSemErro

Posted on quinta-feira, outubro 31, 2013 by Unknown

No comments



O InductionCode possui uma série de posts sobre Torres de Hanói, com implementações em várias linguagens e uma abordagem super intuitiva. Vale a pena conferir! Acessem Torres de Hanói no InductionCode

@CompilouSemErro

Posted on quinta-feira, outubro 31, 2013 by Unknown

No comments


"To understand recursion, we first need to understand recursion." - Anonymous

Entender recursividade é algo fundamental para qualquer bom programador, pois diversas estruturas na computação são naturalmente recursivas, como exemplo, podemos citar a estrutura de diretórios em um sistema operacional.

Uma definição recursiva é mais que um simples trecho de código, é uma forma enxuta e eficiente de definir processos computacionais e expressar ideias. Mas o que vem a ser um procedimento recursivo?

Definição: "Um procedimento recursivo, é todo procedimento definido em termos dele mesmo".

Recursão é uma técnica muito poderosa em definições matemáticas. Como exemplo, podemos citar a função fatorial:
                                                                    F(0) = 1
                                                                    F(n) = n * F(n-1)
A definição acima mostra que para encontrarmos o fatorial de n, precisamos encontrar o fatorial de n-1, e para encontrar o fatorial de n-1, precisamos encontrar o fatorial de n-2, e assim sucessivamente, até alcançarmos o caso base F(0). Fazendo n = 5, temos:
                              F(5) = 5 * F(4)
                                               F(4) = 4 * F(3)
                                                                F(3) = 3 * F(2)
                                                                                 F(2) = 2 * F(1)
                                                                                                  F(1) = 1 * F(0)
                                                                                                                   F(0) = 1

Podemos perceber que em cada etapa precisamos da solução para um problema de tamanho menor.

Agora, vamos apresentar algumas implementações recursivas da função fatorial.

Implementação em Haskell
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial n-1
Implementação em C
#include <stdio.h>
#include <stdlib.h>

int factorial(int n) {
  if(n == 0)
    return 1;
  else
    return n * factorial(n-1);
}

int main() {
  int n;
  scanf("%i", &n);
  printf("%i", factorial(n));
  return 0;
}
Após essa explanação, é importante deixar claro que recursividade não serve apenas para calcular fatorial, que foi abordado nesse post inicial por ser um exemplo simples. No entanto, existem aplicações muito mais interessantes que abordaremos nos posts seguintes.

Posted on quinta-feira, outubro 31, 2013 by Unknown

No comments


A partir de hoje, vamos iniciar uma série de postagens sobre recursividade. Trataremos de problemas simples e avançados. O principal objetivo é mostrar o poder dessa técnica e incentivar os programadores e principalmente os iniciantes a usarem sem medo. É importante lembrar que a recursividade deve ser usada com cautela, mas a decisão de usar a recursão ou não, só pode ser tomada depois que analisarmos fatores como tempo de execução e alocação de memória.
Espero contar com a participação de todos os leitores, para que possamos discutir mais sobre esse tema. Por isso, interajam, comentem nos posts, assim todos ganham.

@CompilouSemErro

Posted on quinta-feira, outubro 31, 2013 by Unknown

No comments


O Inductioncode possui uma série de postagens sobre árvores binárias com diversas implementações. A seguir apresento algumas delas:

Posted on quinta-feira, outubro 31, 2013 by Unknown

No comments

quarta-feira, 30 de outubro de 2013

Não é difícil encontrar programadores que odeiam recursividade. Mas por quê tanto desprezo por uma técnica tão poderosa? Será que é difícil escrever funções recursivas? Códigos recursivos são sempre lentos?

Agora a verdade:
Só fala mal da recursividade quem NÃO sabe usar recursividade!

Durante a fase de projeto de um programa, é importante descobrir inicialmente qual problema estamos tentando resolver. Ou seja, precisamos inicialmente descobrir "O QUE DEVE SER FEITO", e só depois nos preocuparemos com o "COMO FAZER".

Na fase de projeto, o programador deve abstrair o problema, ou seja, deve evitar se preocupar com detalhes irrelevantes. Por exemplo, decidir se o programa será recursivo ou iterativo é irrelevante durante o projeto, é um mero detalhe de implementação!

Infelizmente, alguns programadores nunca escrevem códigos recursivos, e sabem qual a justificativa? Dizem que recursividade é lenta. E isso tem um motivo: Aprenderam recursividade com fatorial e fibonacci! E todos sabem que não devemos usar recursividade nesses casos.

Existem inúmeras situações onde a recursividade é indispensável. Basta pensar em árvores binárias, que são estruturas naturalmente recursivas. Já imaginaram manipular árvores binárias sem recursividade? Até dá para fazer, mas o esforço é desnecessário. Vamos analisar uma implementação recursiva que realiza o caminhamento pré-ordem em uma árvore binária:
void preOrdem(struct tnode *t)
{
  if(t != NULL)
  {
    printf("%d ", t->value);
    preOrdem(t->left);
    preOrdem(t->right);
  }
}
Podemos perceber que de forma clara e enxuta resolvemos o problema em poucas linhas.
Mas ainda tem quem se preocupe com o "estouro da pilha" de execução dos programas! E com isso, não quero dizer que o estouro não possa acontecer, mas será que na maioria das vezes o problema é mesmo o tal "estouro da pilha"?

Posted on quarta-feira, outubro 30, 2013 by Unknown

7 comments

terça-feira, 29 de outubro de 2013

Uma habilidade fundamental que todo programador deve ter é a de resolver problemas com um computador. Por isso, é importante treinar essa habilidade constantemente, não é difícil encontrar bons materiais na internet, mas quero chamar a atenção para dois sites muito famosos e que são sem dúvida excelentes fontes de aprendizado. Estou me referindo aos sites Spoj e Uva, que disponibilizam uma grande variedade de problemas computacionais. Só o fato de tentar resolver os problemas já ajuda você a raciocinar e não ficar com a mente "enferrujada". A seguir, apresento um mapa mental com os links. Espero que gostem e divirtam-se.


Posted on terça-feira, outubro 29, 2013 by Unknown

2 comments



Neste post, trago uma sugestão de leitura do blog parceiro. Diariamente, o Inductioncode trás postagens com uma abordagem bem intuitiva, e não poderia ser diferente com o post "Paridade: Quantos bits são iguais a 1?". Para conferir o post acesssem Inductioncode.

@CompilouSemErro

Posted on terça-feira, outubro 29, 2013 by Unknown

No comments


Vamos implementar em Python um jogo popularmente conhecido como Torres de Hanói. O jogo consiste em mover todos os discos de um pino para outro, mas com as seguintes regras:

       1 - Devemos mover um disco de cada vez.
       2 - Não podemos colocar um disco maior sobre um disco menor.

A implementação recursiva é bem simples. Inicialmente, moveremos os n-1 primeiros discos para um pino auxiliar, em seguida, moveremos o último disco para o pino de destino. E concluímos movendo os n-1 discos do pino auxiliar para o pino de destino.
def hanoi(n, A, B, C):
  if(n > 0):
    hanoi(n-1, A, C, B)
    print "Mova o disco " + str(n) + " de " + A + " para " + B
    hanoi(n-1, C, B, A)

Posted on terça-feira, outubro 29, 2013 by Unknown

No comments

segunda-feira, 28 de outubro de 2013

Neste mapa mental, apresento um resumo das sintaxes utilizadas para declarar arrays em várias linguagens. Lembrando que para um pleno entendimento, é necessário estudar os detalhes e entender o significado de cada declaração apresentada no mapa.



Posted on segunda-feira, outubro 28, 2013 by Unknown

4 comments

Os mapas mentais ajudam no aprendizado de qualquer assunto, além de facilitarem a memorização. Por isso, estamos trazendo um mapa mental com os principais comandos envolvidos na manipulação de ponteiros em C. Em breve, teremos mais mapas mentais sobre programação.


Confiram também nosso post sobre compilação em várias linguagens de programação clique aqui

Posted on segunda-feira, outubro 28, 2013 by Unknown

No comments

domingo, 27 de outubro de 2013


Com a função malloc, podemos alocar memória dinamicamente, ou seja, durante a execução de um programa. A função malloc recebe como argumento um número inteiro que indica a quantidade de bytes que serão alocados na memória. Se a alocação ocorrer com sucesso, malloc retorna um ponteiro para o primeiro byte do bloco alocado, caso contrário, retorna NULL.
Assinatura da função:
void *malloc(size_t n)
Exemplo: Alocando memória para números inteiros
int *p;
p = (int *) malloc(sizeof(int));
A função malloc é muito útil quando estamos implementado estruturas que poderão crescer em tempo de execução, como por exemplo, listas, pilhas e árvores binárias. Um nó em uma lista encadeada poderia ser declarado a partir da seguinte struct
struct no {   
  int value;
  struct no* prox;
};
Durante a execução do programa, podemos criar novos nós na memória fazendo:
(struct no *)malloc(sizeof(struct no));
@CompilouSemErro

Posted on domingo, outubro 27, 2013 by Unknown

No comments

 A maioria das distribuições Linux já possuem o Python instalado. Por isso, executar programas escritos em Python é uma tarefa muito simples. Como exemplo, vamos inicialmente criar um programa em Python que escreve uma mensagem na tela.  O nome do arquivo será test.py:
print "Compilou sem Erro!"
Agora, basta abrir o terminal e digitar
python test.py
Caso queira executar o programa sem chamar diretamente o compilador python, você precisa dar ao seu arquivo permissão de executável. Para isso, devemos no shell o seguinte:
chmod +x test.py
Além disso, devemos adicionar uma linha especial ao arquivo test.py. Essa linha indicará o caminho do interpretador Python
#!/usr/bin/python
print "Compilou sem Erro!"
Caso não saiba qual o caminho do interpretador em seu sistema use o comando which, como podemos ver abaixo
which python
E para ver o resultado do programa, basta dar dois cliques ou chamar o executável fazendo
./teste.py

Posted on domingo, outubro 27, 2013 by Unknown

No comments


Hoje, vamos mostrar como contar a quantidade de vezes que determinado caractere apareceu em uma string. Como exemplo, vamos usar a string "Dicas de programação e Python é no Compilou sem Erro".
msg = "Dicas de programacao e Python e no Compilou sem Erro"
Agora, vamos varrer nossa string em busca do caractere "o". Vamos usar um loop "for" para varrer a string, e toda vez que o caractere "o" for encontrado, incrementaremos o contador.
msg = "Dicas de programacao e Python e no Compilou sem Erro"
inc = 0
for c in msg:
  if(c == 'o'):
    inc = inc + 1
print inc

Posted on domingo, outubro 27, 2013 by Unknown

No comments


Neste post, vamos mostrar como compilar programas na linha de comandos do Linux. Mas antes, quero dar as boas vindas aos nossos leitores, principalmente os seguidores do Twitter que já acompanham nossas dicas diárias. Agora com este espaço, poderemos conversar mais e discutir de forma mais ampla temas referentes a programação e Linux. Espero que vocês gostem.

Vamos abrir o shell e começar a diversão:

1) Compilando programas em Pascal

Para compilar programas escritos em pascal, podemos usar o compilador fcp. Para gerar o executável, digite
fcp  .pas
e para executar o programa, digite
./programa

2) Compilando programas em C

Para compilar programas escritos na linguagem C, podemos usar o famoso GCC. Após escrever o seu programa, abra o shell e digite
gcc programa.c -o prog
A flag -o permite que o programador dê um nome ao executável. Caso ela seja omitida, o nome do executável será a.out. Para executar o programa digite
./prog

3) Compilando programas em C++

O processo de compilação e execução de programas em C++, se dá de forma similar ao da linguagem C. A diferença é que usamos o compilador g++. Para compilar e executar, digite
g++ programa.cpp -o prog 
./prog

4) Compilando programas em Java

A linguagem Java é compilada, mas os programas escritos nesta linguagem não são executados diretamente pelo computador, pois o código gerado durante o processo de compilação, conhecido como bytecodes, será executado pela JVM (Java Virtual Machine). Para gerar um executável fazemos
javac Programa
e em seguida
java Programa
É importante lembrar que "Programa" é o nome da classe Java definida pelo programador.

5) Interpretando programas em Python

Python é uma linguagem interpretada, ou seja, para executar um programa .py basta digitar
python programa.py
A maioria das distribuições Linux trás o Python instalado.

6) Compilando programas em Haskell

A linguagem Haskell pode ser compilada ou interpretada. Para gerar um executável podemos usar o compilador ghc. Já para interpretar os comandos e visualizar o resultado imediatamente podemos usar o interpretador ghci. Após abrir o shell Linux, digite
ghci
e pressione ENTER para iniciar o interpretador. Em seguida, carregue o seu arquivo .hs fazendo
:load programa.hs
Caso o programa não possua erros de sintaxe, você já poderá chamar suas funções, caso contrário, uma mensagem de erro será exibida.

Posted on domingo, outubro 27, 2013 by Unknown

No comments