Felipe Tonello » C++ http://felipetonello.com/blog Compartilhe, ajude e cresça Thu, 07 Jul 2011 04:13:08 +0000 en hourly 1 http://wordpress.org/?v=3.2.1 Desktop version of Kactoos http://felipetonello.com/blog/2011/07/07/desktop-version-of-kactoos/ http://felipetonello.com/blog/2011/07/07/desktop-version-of-kactoos/#comments Thu, 07 Jul 2011 04:13:08 +0000 Felipe Tonello http://felipetonello.com/blog/?p=390 Kactoos is a social buying website. In other words, you buy a product on the list and as many other people buy the same product the price decrease.

So, to make others know about their API, they are doing a challenge. The best application developed wins a Google TV and an iPad 2.

As I want a tabled so bad, I'm developing a version of Kactoos for desktop called KaQToos.

If you want to check the project out, take a look at github's KaQToos project website.

]]>
http://felipetonello.com/blog/2011/07/07/desktop-version-of-kactoos/feed/ 0
Awesome C/C++ auto-completion in Emacs http://felipetonello.com/blog/2011/06/07/awesome-c-cpp-auto-completion-in-emacs/ http://felipetonello.com/blog/2011/06/07/awesome-c-cpp-auto-completion-in-emacs/#comments Tue, 07 Jun 2011 12:42:53 +0000 Felipe Tonello http://felipetonello.com/blog/?p=370 Emacs is a great editor, no body doubts that. But there is no powerful auto-completion by default, like Eclipse or other IDE.

Parsing C++ is very hard and using tools like ctags works well for C but not so much for C++.
LLVM/Clang is a compiler architecture supported by Apple, Google, Adobe and others that seeks to become a serious alternative to GCC. The project started just a few years ago but it already provides a high quality C and Objective C compiler that performs better than GCC in several benchmarks. The C++ support is still not complete but good to compile boost. Clang is not just a compiler, it also has includes great tools for code analysis. Clang is BSD licensed which enables close interaction with third part applications without licensing issues.

Ok, so let's merge all these things. To accomplish that we need 3 Emacs extensions:

  • auto-complete-mode
  • yasnippet
  • auto-complete-clang

auto-complete-mode

auto-complete-mode is an awesome extension for Emacs. It provides an intelligent auto-completion. To install, just follow these steps:

  1. Download it at http://cx4a.org/software/auto-complete/
  2. Copy all .el to ~/.emacs.d or other personal folder that you keep your Emacs extensions
  3. Add the following code to your ~/.emacs:
    (require 'auto-complete-config)
    (add-to-list 'ac-dictionary-directories "~/.emacs.d/ac-dict")

    Note: change the ac-dictionary-directories as specified in step 2.

yasnippet

yasnippet is a template system for Emacs. Installation process:

  1. Download the yasnippet-bundle at http://code.google.com/p/yasnippet/
  2. Uncompress it at ~/.emacs.d or other personal folder that you keep your Emacs extensions
  3. Add the following code to your ~/.emacs:
    (require 'yasnippet-bundle)

auto-complete-clang

auto-complete-clang unites the power of auto-complete, clang and yasnippet.

  1. Download the .el file at https://github.com/brianjcj/auto-complete-clang
  2. Copy it at ~/.emacs.d or other personal folder that you keep your Emacs extensions
  3. Add the following code to your ~/.emacs:
  4. (require 'auto-complete-clang)
  5. Since auto-complete-clang calls clang to every auto-complete command, we need to trigger it with some key. In my example here I'm using C-Tab
  6. (setq ac-auto-start nil)
    (setq ac-quick-help-delay 0.5)
    (define-key ac-mode-map  [(control tab)] 'auto-complete)
  7. Setting some properties:
  8. (defun my-ac-config ()
    (setq ac-clang-flags (split-string "-I/path/to/headers"))
    (setq-default ac-sources '(ac-source-abbrev ac-source-dictionary ac-source-words-in-same-mode-buffers))
    (add-hook 'emacs-lisp-mode-hook 'ac-emacs-lisp-mode-setup)
    (add-hook 'c-mode-common-hook 'ac-cc-mode-setup)
    (add-hook 'ruby-mode-hook 'ac-ruby-mode-setup)
    (add-hook 'css-mode-hook 'ac-css-mode-setup)
    (add-hook 'auto-complete-mode-hook 'ac-common-setup)
    (global-auto-complete-mode t))
    (defun my-ac-cc-mode-setup ()
    (setq ac-sources (append '(ac-source-clang ac-source-yasnippet) ac-sources)))
    (add-hook 'c-mode-common-hook 'my-ac-cc-mode-setup)
    (my-ac-config)

    There is basically one important thing here, the ac-clang-flags. You must pass all your include paths in order to clang parses everything correctly. Even the stdc++ headers. For example:

    (setq ac-clang-flags (split-string "-I/usr/include/c++/4.5 -I/usr/include -I/usr/local/include -I/usr/local/qt4/include -I/usr/local/qt4/include/QtCore -I/usr/local/qt4/include/QtGui"))
  9. Since my background color is black, I had to change the ac-cursor-color in auto-complete.el. To do that find the first occurrence of ac-cursor-color and change nil to the desired color. For example:
  10. (defvar ac-cursor-color "blanched almond"
    "Old cursor color.")

Troubleshoot

If you get some error with bits/c++config.h in *clang error* buffer, like:
fatal error: 'bits/c++config.h' file not found
You might need to create a symbolic link from the machine hardware name(i686, etc) c++ bits includes to the c++ bits:
# ln -s /usr/include/c++/4.5/`uname -m`-linux-gnu/bits/* /usr/include/c++/4.5/bits

To inspire you, here is my .emacs file:

; auto-complete-mode
; --------------
(require 'auto-complete-config)
(add-to-list 'ac-dictionary-directories "~/Dropbox/elisp/ac-dict")
 
; yasnippet
; --------------
(require 'yasnippet-bundle)
 
; auto-complete-clang
; --------------
(require 'auto-complete-clang)
 
(setq ac-auto-start nil)
(setq ac-quick-help-delay 0.5)
;; (ac-set-trigger-key "TAB")
(define-key ac-mode-map  [(control tab)] 'auto-complete)
(defun my-ac-config ()
  (setq ac-clang-flags (split-string "-I/usr/include/c++/4.5 -I/usr/include -I/usr/local/include -I/usr/local/kdchart4/include -I/usr/local/rog/include -I/usr/local/qt4/include -I/usr/local/qt4/include/QtCore -I/usr/local/qt4/include/QtGui"))
  (setq-default ac-sources '(ac-source-abbrev ac-source-dictionary ac-source-words-in-same-mode-buffers))
  (add-hook 'emacs-lisp-mode-hook 'ac-emacs-lisp-mode-setup)
  (add-hook 'c-mode-common-hook 'ac-cc-mode-setup)
  (add-hook 'ruby-mode-hook 'ac-ruby-mode-setup)
  (add-hook 'css-mode-hook 'ac-css-mode-setup)
  (add-hook 'auto-complete-mode-hook 'ac-common-setup)
  (global-auto-complete-mode t))
(defun my-ac-cc-mode-setup ()
  (setq ac-sources (append '(ac-source-clang ac-source-yasnippet) ac-sources)))
(add-hook 'c-mode-common-hook 'my-ac-cc-mode-setup)
;; ac-source-gtags
(my-ac-config)

Working with Qt 1

 

Working with Qt 2

 

It also works with the C++ Standard Library

 

That's it.

]]>
http://felipetonello.com/blog/2011/06/07/awesome-c-cpp-auto-completion-in-emacs/feed/ 3
6º Encontro da comunidade de C e C++ Brasil http://felipetonello.com/blog/2010/01/21/6%c2%ba-encontro-da-comunidade-de-c-e-c-brasil/ http://felipetonello.com/blog/2010/01/21/6%c2%ba-encontro-da-comunidade-de-c-e-c-brasil/#comments Fri, 22 Jan 2010 00:56:03 +0000 Felipe Tonello http://felipetonello.com/blog/?p=252 Pessoal, dia 6 de Março de 2010 haverá o 6º encontro da comunidade brasileira de C e C++ em São Paulo.

Eu tive o privilégio de ser convidado para palestrar sobre o RobotQt. O título da palestra é: Simulador de robótica com Qt Framework.

Não perca esse evento. Faça a inscrição aqui!

]]>
http://felipetonello.com/blog/2010/01/21/6%c2%ba-encontro-da-comunidade-de-c-e-c-brasil/feed/ 0
Analisando Número de Fibonacci e Recursividade http://felipetonello.com/blog/2009/01/30/analisando-numero-de-fibonacci-e-recursividade/ http://felipetonello.com/blog/2009/01/30/analisando-numero-de-fibonacci-e-recursividade/#comments Fri, 30 Jan 2009 04:54:47 +0000 Felipe Tonello http://felipetonello.com/blog/?p=191 O número de Fibonacci é bem conhecido no mundo da computação. Ele é representado por uma função recursiva:
Fibonacci e Proporção áurea

Calculando

Tendo isso em mente é bem fácil criar um algoritmo que calcule o número de Fibonacci, certo?
Na internet normalmente encontramos um algoritmo usando um método de recursão simples. Algo parecido com:

Felipe: Esse artigo usa apenas exemplos em C++

fibo1.cpp

#include <iostream>
#include <cstdlib>
 
int F(int n)
{
    if (n == 0) return 0;
    if (n == 1) return 1;
    return F(n - 1) + F(n - 2);
}
 
int main(int argc, char *argv[])
{
    int n = atoi(argv[1]);
    std::cout << F(n) << std::endl;
    return 0;
}

código no pastebin

Compilando:

g++ -o fibo1 fibo1.cpp

Rodando:

./fibo1 8

Deu 21, certo? Isso mesmo.

Analisando a Função

Mas digo para você: Não use esse programa! É totalmente ineficiente. O número de chamadas para calcular F_{N} é exatamente F_{N+1}. A função calcula recursivamente o mesmo número quantas vezes a chamar. Como podemos ver, a taxa de crescimento do número de Fibonacci tende a Proporção áurea:
Fibonacci e Proporção áurea

Lembrando que a razão áurea é definida por:
Razão áurea

Sim, fibo1.cpp é uma função exponencial com Big Theta Notation, em função do tempo, de:
Big Theta Notation 1

O tempo de execução para computar F_{N+1} é \phi \approx 1,6 vezes mais demorado que para calcular F_{N}. Por exemplo, já que \phi^{9} > 60 e percebemos que nosso computador leva um segundo para calcular F_{N}, então levará mais de um minuto para calcular F_{N+9} e mais de uma hora para calcular F_{N+18}.

Podemos verificar isso calculando F_{36} e F_{45}

pet@felipe-opensuse:~/Projetos/C++/algoritmos> time ./fibo1 36
14930352

real 0m1.077s
user 0m1.040s
sys 0m0.008s
pet@felipe-opensuse:~/Projetos/C++/algoritmos> time ./fibo1 45
1134903170

real 0m54.927s
user 0m54.547s
sys 0m0.092s

Em contraste, usando o método de programação dinâmica temos um tempo proporcional a N.

Programação dinâmica

Esse método consiste em guardar os valores dos números já calculados em um array. Fazendo isso, apenas checamos se o array já foi memorizado, e então retornamos o número, caso contrário calculamos recursivamente e assim por diante.
Lembrando que para um int de 32 bits, F_{46} = 1836311903 será o maior numero a ser calculado.

fibo2.cpp

#include <iostream>
#include <cstdlib>
 
namespace Fibonacci {
    int *memory;
    int F(int n)
    {
        // int inicializa como 0
        if (memory[n] != 0) return memory[n];
        int aux = n;
        if (n < 0) return 0;
        if (n > 1) aux = F(n-1) + F(n-2);
        return memory[n] = aux;
    }
}
 
int main(int argc, char *argv[])
{
    int n = atoi(argv[1]);
    Fibonacci::memory = new int[n+1];
    std::cout << Fibonacci::F(n) << std::endl;
    delete [] Fibonacci::memory;
    return 0;
}

código no pastebin

Compilando:

g++ -o fibo2 fibo2.cpp

Rodando:

./fibo2 8

Deu 21, de novo? =)

Aplicamos aqui uma técnica chamada bottom-up dynamic programming. Se aplica em uma função recursiva que podemos salvar tempo por armazenar valores anteriores que serão usados depois. Essa técnica tem sido usada para uma gama grande de algoritmos e aplicações. E essa simples mudança fez com que nosso algoritmo passasse de exponencial para linear.

Agora temos uma função, em relação ao tempo, proporcional ao N.
Big Theta Notation 2

Comparando

Fazendo vários testes, podemos chegar em uma tabela de resultados, em função do tempo:

arquivo F_{8} F_{36} F_{45} F_{46}
fibo1.cpp 0m0.009s 0m1.156s 0m54.927s 1m29.403s
fibo2.cpp 0m0.007s 0m0.007s 0m0.006s 0m0.007s

fibo2.cpp é constante? Sim! Para N relativamente pequeno fibo2.cpp calcula em tempo constante.

Será interessante ver até quanto esse algoritmo agüenta(ta errado né? hehe ¬¬) fazer em tempo constante. Alguém se habilita?

]]>
http://felipetonello.com/blog/2009/01/30/analisando-numero-de-fibonacci-e-recursividade/feed/ 12
Josephus Problem, resolvendo-o de maneira simples http://felipetonello.com/blog/2009/01/08/josephus-problem-resolvendo-o-de-maneira-simples/ http://felipetonello.com/blog/2009/01/08/josephus-problem-resolvendo-o-de-maneira-simples/#comments Thu, 08 Jan 2009 18:40:28 +0000 Felipe Tonello http://felipetonello.com/blog/?p=156 Josephus Problem é um problema bem legal que estudei no livro Concrete Mathematics.

Josephus foi um historiador judeu do primeiro século. A lenda conta que ele e 40 de seus homens estavam presos em uma caverna pelos Romanos. Eles decidiram suicidar-se à ser capturados. Formaram um circulo e começaram a se matar, da 3ª à 3ªa pessoa em ordem da fila. Como Josephus não queria morrer, ele foi capaz de escolher o melhor lugar, afim de sobreviver, e juntar-se os Romanos que o capturaram.

O Problema

Na prática o problema teria N pessoas em um círculo, iria ser percorrido M - 1 pessoas e o M iria ser morto, assim por diante, até sobrar uma única pessoa.

A Solução

Podemos representar a solução por uma função recursiva, para N par e M = 2:

e para N ímpar e M = 2, temos:

Não vou postar a solução genérica aqui pois exige uma grande explicação e esse não é o objetivo do post. Você pode ver na wikipedia ou então comprar o livro, caso queria saber mais.

O interessante é que o algoritmo para solução genérica é bem simples em C++. Usando listas ligadas(linked lists) é simples, fácil de entender e super rápido a execução do programa.

Josephus.cpp

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
#include <iostream>
#include <cstdlib>
 
struct Pessoa {
	int num;
	Pessoa *prox;
	Pessoa(int x, Pessoa *p) {
		num = x;
		prox = p;
	}
};
 
int main(int argc, char *argv[]) {
	//'a' recebe primeira pessoa criada
	//e 'a' é linkado para si mesmo
	//depois 'b' é criado apontado para 'a'
	int N = atoi(argv[1]), M = atoi(argv[2]);
	Pessoa *a = new Pessoa(1, 0);
	a->prox = a;
	Pessoa *b = a;
 
	// Aloca na memória todas as pessoas
	// e 'b' recebe a última(enésima pessoa)
	// pois a contagem começa pela primeira('a')
	for (int i = 2; i <= N; ++i)
		b = (b->prox = new Pessoa(i, a));
 
	// Loop enquanto 'b' não estiver apontado
	// o próximo para ele mesmo
	while (b != b->prox) {
		// 'b' recebe a emésima pessoa
		for (int i = 1; i < M; ++i)
			b = b->prox;
		a = b->prox;
		b->prox = a->prox;
		delete a; // 'a' é morto =/
	}
 
	// O sobrevivente _o/
	std::cout << b->num << std::endl;
}

Ou então se preferir um link para o pastebin.

Analisando o Resultado

após compilar

g++ -o Josephus Josephus.cpp

rode o programa com N = 10 e M = 2

./Josephus 10 2

O valor deu 5? Verifique com a função. Bateu os valores?
Agora vá testando para 1 <= N <= 16 e M = 2.

for n in `seq 16`; do echo -n "$n: "; ./Josephus $n 2; done

Saída do loop:

1: 1
2: 1
3: 3
4: 1
5: 3
6: 5
7: 7
8: 1
9: 3
10: 5
11: 7
12: 9
13: 11
14: 13
15: 15
16: 1

Perceberam um certo padrão entre as respostas? A função genérica usa justamente esse padrão binário para solução.

Ultimamente eu estou mais dedicado ao estudo de algoritmos, C++, C e Python(é claro). Depois pretendo postar uma analise desse algoritmo passo a passo.

]]>
http://felipetonello.com/blog/2009/01/08/josephus-problem-resolvendo-o-de-maneira-simples/feed/ 0