W3log de Tiago Charters de Azevedo (Comentários para: tca@diale.org)
# | 2008-02-29
Tenho andado a implementar o algoritmo de Porter para português em Emacs Lisp. Está quase todo pronto. Pelo caminho encontrei o SNOBOL e teve como consequência imediata a reescrita quase total do código original em termos de funções em Lisp que implementam as instruções em SNOBOL. O prazo que impus a mim mesmo, o dia de hoje, para acabar o código acabou. É pena.
Referências:
# | 2008-02-26
Num artigo do passado mês de Outubro sobre a evolução da linguagem (Quantifying the evolutionary dynamics of language,Nature 449, 713-716 (11 October 2007) ver link no fim do texto), e em particular sobre a evolução dos verbos irregulares em regulares, podia ler-se:
"To quantify the dynamics of language evolution, we studied the regularization of English verbs over the past 1,200 years. (...) Here we describe the emergence of this linguistic rule amidst the evolutionary decay of its exceptions, known to us as irregular verbs. We have generated a data set of verbs whose conjugations have been evolving for more than a millennium, tracking inflectional changes to 177 Old-English irregular verbs. Of these irregular verbs, 145 remained irregular in Middle English and 98 are still irregular today. We study how the rate of regularization depends on the frequency of word usage. The half-life of an irregular verb scales as the square root of its usage frequency: a verb that is 100 times less frequent regularizes 10 times as fast. (...)"
Uma das maneiras de pensar no problema seria estudar a evolução temporal da
probabilidade de encontrar um verbo irregular num texto num dado instante. Seja
a probabilidade de encontrar n verbos num instante t. Se se
admitir que parte destes verbos se tornam regulares com uma probabilidade
, então um texto com n verbos irregulares teve origem num
texto com n ou n+1 verbos irregulares, e logo
.
Definindo a função geradora
e passando ao limite
obtém-se uma equação às derivadas
parciais com a forma
Admitindo que inicialmente se tem N verbos irregulares a solução da equação anterior é
Se esta abordagem permite fazer mais qualquer coisa não sei...
Ref: Erez Lieberman, Jean-Baptiste Michel Joe Jackson1, Tina Tang & Martin A. Nowak Quantifying the evolutionary dynamics of language, Nature 449, 713-716 (11 October 2007)
# | 2008-02-26
Quer calcular-se o valor do polinómio de grau
. Para
isso é necessário efectuar 5 operações 2 somas + 3 produtos. Uma maneira simples
de reduzir o número de operações, reduzindo a 4 operações (2 somas e 2
produtos), é factorizar o polinómio na forma
. A coisa engraçada é se implementar o cálculo de
em Lisp fica
(defun P (x a b c) (+ c (* (+ (* a x) b) x))) (P 1 1 2 3); 6que é a forma factorizada anterior que tem o numero mínimo de operações.
# | 2008-02-23
Código em GNU/Octave que calcula a decomposição em wavelets (Haar).
function c=haar(y,n)
ly=length(y)-1;
x=[0:1/ly:1];
for i=0:n
for j=0:2^i-1
c(i+1,j+1)=2^(i)*trapz(x,y.*mf(2^(i).*x-j));
endfor;
endfor;
endfunction
# | 2008-02-23
As rotações espaciais podem ser parametrizadas pelos ângulos de Euler
e por quaterniões unitários
. Um
quaternião unitário é descrito por um vector unitário num espaço 4D com a forma

É possível relacionar os ângulos de Euler com os quaterniões através das expressões
A matriz de rotação fica com a forma
forma mais simpática relativamente à matriz de rotação usando ângulos de Euler.
Ref: James Diebel, Representing Attitude: Euler Angles, Quaternions, and Rotation Vectors, http://ai.stanford.edu/~diebel/attitude/attitude.pdf
# | 2008-02-23
function mavgv=mavg(x,m)
n=length(x);
mavgv=ones(1,m);
for j=m+1:n;
mavgv(j)=mean(x(j-m:j));
endfor;
endfunction
Claro que esta não é a maneira mais rápida de as calcular.
# | 2008-02-22
(defun list-to-string (l)
"Return a STRING which is the concatenation of the elements of
L."
(if (not l)
nil
(if (stringp (car l))
(concat (car l) (list-to-string (cdr l)))
(list-to-string (cdr l)))))
(defun join-string(xs &optional sep)
(cond ((null xs) "")
((null (cdr xs)) (car xs))
(t (concat (car xs) (or sep "") (join-string (cdr xs) sep)))))
(defun mistura (frase)
"Faz o cut-up de uma dada frase, isto é, retorna uma
frase com os mesmo elementos mas com ordem aleatória"
(setq frasecu ())
(setq listafrase (split-string frase))
(random t)
(while listafrase
(setq palavra
(nth (random (length listafrase)) listafrase))
(setq frasecu (cons palavra frasecu))
(setq listafrase (delq palavra listafrase)))
(insert (join-string frasecu " "))
)
# | 2008-02-22
(defun string-to-strings (s)
"Convert a string into a list of strings."
(let ((i (- (length s) 1)) (l '()))
(while (<= 0 i)
(setq l (cons (aref s i) l)
i (- i 1)))
(mapcar (lambda (x) (char-to-string x)) l)))
(string-to-strings "Rosa Limão") ; ("R" "o" "s" "a" " " "L" "i" "m" "ã" "o")
# | 2008-02-20
Ao contrário do que sucede na entrada anterior o binómio de Newton tem uma regularidade bem definida no que toca à distribuição dos números pares, múltiplos de 3, etc.
![]() |
| Distribuição dos números múltiplos de: 2, 3, 4, e 5 no binómio de Newton, respectivamente, de cima para baixo. |
Deixo aqui o código que o calcula assim como a imagem que se obtém no fim. Claro que usei o Octave para fazer estas coisas.
split_long_rows=0;
function a=onetozero(a)
n=length(a);
for i=1:n
for j=1:n
if a(i,j)>0
a(i,j)=0;
else
a(i,j)=1;
endif;
endfor;
endfor;
endfunction;
n=60;
a=zeros(n,n);
a(1,1)=1;
a(2,1)=1;a(2,2)=1;
a(:,1)=ones(n,1);
for j=2:n
for i=3:n
a(i,j)=a(i-1,j-1)+a(i-1,j);
endfor;
endfor;
#a;
a2=onetozero(mod(a,2));
a3=onetozero(mod(a,3));
a4=onetozero(mod(a,4));
a5=onetozero(mod(a,5));
sp=ones(10,n);
imshow([a2;sp;a3;sp;a4;sp;a5],"truesize");
# | 2008-02-20
A régua de Golomb é constituída por uma série de marcas, com posição dada por um inteiro, de modo a que qualquer distância entre duas marcas sucessivas quaisquer nunca se repete.
Se as arranjar numa matriz (as linhas indexam a ordem da régua), ficam (usei o
Octave para estes cálculos),
A=[
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 4 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 4 9 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 4 10 12 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 4 10 15 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 8 11 13 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 8 12 14 17 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 4 10 18 23 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 7 11 20 23 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 11 16 19 23 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 2 3 10 16 21 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 2 7 13 21 22 25 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 4 9 15 22 32 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 5 12 25 27 35 41 44 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 6 10 23 26 34 41 53 55 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 4 13 28 33 47 54 64 70 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 1 9 19 24 31 52 56 58 69 72 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 2 6 24 29 40 43 55 68 75 76 85 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 2 5 25 37 43 59 70 85 89 98 99 106 0 0 0 0 0 0 0 0 0 0 0 0;
0 4 6 20 35 52 59 77 78 86 89 99 122 127 0 0 0 0 0 0 0 0 0 0 0;
0 4 20 30 57 59 62 76 100 111 123 136 144 145 151 0 0 0 0 0 0 0 0 0 0;
0 1 4 11 26 32 56 68 76 115 117 134 150 163 168 177 0 0 0 0 0 0 0 0 0;
0 5 7 17 52 56 67 80 81 100 122 138 159 165 168 191 199 0 0 0 0 0 0 0 0;
0 2 10 22 53 56 82 83 89 98 130 148 153 167 188 192 205 216 0 0 0 0 0 0 0;
0 1 6 25 32 72 100 108 120 130 153 169 187 190 204 231 233 242 246 0 0 0 0 0 0;
0 1 8 11 68 77 94 116 121 156 158 179 194 208 212 228 240 253 259 283 0 0 0 0 0;
0 2 24 56 77 82 83 95 129 144 179 186 195 255 265 285 293 296 310 329 333 0 0 0 0;
0 1 9 14 43 70 106 122 124 128 159 179 204 223 253 263 270 291 330 341 353 356 0 0 0;
0 3 7 17 61 66 91 99 114 159 171 199 200 226 235 246 277 316 329 348 350 366 372 0 0;
0 9 33 37 38 97 122 129 140 142 152 191 205 208 252 278 286 326 332 353 368 384 403 425 0;
0 12 29 39 72 91 146 157 160 161 166 191 207 214 258 290 316 354 372 394 396 431 459 467 480]
Para tentar perceber se existe alguma regularidade nestes números fiz
mod(A,2), substituindo os 0 por um espaço em branco. Obtém-se
1
1 1
1
1 1 1
1 1
1 1 1
1 1 1 1
1 1
1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1
1 1 1 1
1 1 1
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
Ou retirando as réguas repetidas numa mesma ordem:
1
1 1
1
1 1 1
1 1
1 1 1
1 1 1
1 1 1 1 1 1
1 1 1 1 1
1 1 1 1
1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
Aparentemente, olhando para a distribuição de 1's, não há nenhuma regularidade.
# | 2008-02-19
Já está colocada a primeira pedra: Métodos numéricos em Emacs Lisp.
# | 2008-02-14
(defun inner (x y)
"Inner product of two vectors x and y."
(let ((i 0) (aux 0))
(while (< i (length x))
(setq aux (+ aux (* (nth i x) (nth i y))))
(setq i (1+ i)))
aux))
(defun sum (x)
"Sum of element of x."
(let ((i 0) (aux 0))
(while (< i (length x))
(setq aux (+ aux (nth i x)))
(setq i (1+ i)))
aux))
(defun sumsq (x)
"Sum of squares of elements x."
(let ((i 0) (aux 0))
(while (< i (length x))
(setq aux (+ aux (* (nth i x) (nth i x))))
(setq i (1+ i)))
aux))
# | 2008-02-12
(defun fixedpoint (f x &optional tol)
"Find the fixed point of f, i. e., f(p)=p."
(when (null tol)
(setq tol 0.00001))
(let*
((oldx x)
(x (funcall f x))
)
(if (< (abs (- x oldx)) tol) x (fixedpoint 'f x tol))
))
(defun f (x) (cos x)) (fixedpoint 'f 1 .001) ; 0.7387603198742113
# | 2008-02-11
(defun bisection (f a b &optional tol)
"Solve the function f(x)=0 with bounds a and b and tolerance tol. a
and b need to bracket the solution."
(when (null tol)
(setq tol 0.00001))
(let*
((m (/ (+ a b) 2.0))
(fm (funcall f m))
(fa (funcall f a))
)
(if (< (abs fm) tol)
m
(if (> (* fa fm) 0.0)
(bisection 'f m b tol)
(bisection 'f a m tol)))))
(defun f (x) (- 2 (* x x))) (bisection 'f 1 3) ; 1.414215087890625
# | 2008-02-09
Jason H. SteffenUsing a Markov Chain Monte Carlo optimization algorithm and a computer simulation, I find the passenger ordering which minimizes the time required to board the passengers onto an airplane. The model that I employ assumes that the time that a passenger requires to load his or her luggage is the dominant contribution to the time needed to completely fill the aircraft. The optimal boarding strategy may reduce the time required to board and airplane by over a factor of four and possibly more depending upon the dimensions of the aircraft. I explore some features of the optimal boarding method and discuss practical modifications to the optimal. Finally, I mention some of the benefits that could come from implementing and improved passenger boarding scheme.
# | 2008-02-06
A abordagem usual quando se fala em computação, e em particular o que me agora interessa, no ensino da matemática e no uso de computadores, é usar-se uma abordagem imperativa. Foi a que aprendi. Qual a vantagem, se alguma existe, em usar uma análise, um paradigma, funcional?
# | 2008-02-06
O cálculo
é mais pequena, e universal, linguagem de
programação. Consiste apenas numa única regra de transformação (substituição de
uma variável) e um modo de definir funções. Foi construída por Alonzo Church em
1930 como um modo de formalizar o conceito de computabilidade.
O cálculo
é universal no sentido em que qualquer função
computável pode ser expressa e calculada (evaluated) usando este formalismo. É
pois equivalente a uma máquina de Turing. No entanto, este cálculo enfatiza o
uso de regras de transformação e não considera em muito detalhe qual a possível
máquina em que tais transformações poderiam ter lugar. Pode dizer-se que é uma
abordagem que se aproxima mais do software do que do hardware.
Algumas funções matemáticas são computáveis, outras não. Em geral nas linguagens de programação é possível escrever um programa que implementa toda e qualquer função computável em principio. Por outro lado o limite da computabilidade, ou daquilo que é computável, também limita o tipo de coisas que uma linguagem de programação pode fazer.
Uma função parcial é uma função que está definida para alguns valores do seu argumento e não definida para outros, isto é, partilha da definição de função apenas a unicidade da imagem dado um objecto.
Intuitivamente uma função é computável se existe um programa que a calcula (computa). Mais especificamente, uma função é computável se existe um algoritmo que para um dado x o programa pára (halt), ao fim de um tempo finito, e dá a resposta y=f(x).
O que é mais estranho é que, apesar de se poder escrever programas que implementam o cálculo de funções, muitas vezes nem sempre é possível responder à pergunta simples: dado um input x será que um dado programa nos dá a resposta y. Em geral, o problema de determinar se um dado programa pára, ou não, é não computável! Ou seja, não é possível, em geral, dado um programa, construir um outro programa que nos diz se o primeiro nos dá a resposta.
# | 2008-02-05
Tomei hoje a decisão, e tenho consciência de ser contra corrente, de não colocar nenhum menu nestas páginas. Tenho alguma dificuldade em complementar as especificações de um dado browser, sim aquela coisa que usa para ler estas linhas, com devaneios de navegabilidade própria.
# | 2008-02-04
Eric RaymondSome computer languages simply amplify the kind of thinking that you already do. Some computer languages teach you fundamentally new ways of looking at problems. Python is like Lisp in that it tends to teach you new ways of thinking about problems to broaden your mental horizons.
# | 2008-02-01
Sobre o bom senso (Descartes, O discurso do método).
Não existe no mundo coisa mais bem distribuída que o bom senso, visto que cada indivíduo acredita ser tão bem provido dele que mesmo os mais difíceis de satisfazer em qualquer outro aspecto não costumam desejar possuí-lo mais do que já possuem. E é improvável que todos se enganem a esse respeito; mas isso é antes uma prova de que o poder de julgar de forma correta e discernir entre o verdadeiro e o falso, que é justamente o que é denominado bom senso ou razão, é igual em todos os homens; e, assim sendo, de que a diversidade de nossas opiniões não se origina do fato de serem alguns mais racionais que outros, mas apenas de dirigirmos nossos pensamentos por caminhos diferentes e não considerarmos as mesmas coisas. Pois é insuficiente ter o espírito bom, o mais importante é aplicá-lo bem. As maiores almas são capazes dos maiores vícios, como também das maiores virtudes, e os que só andam muito devagar podem avançar bem mais, se continuarem sempre pelo caminho recto, do que aqueles que correm e dele se afastam.
1999-2008 (c) Tiago Charters de Azevedo São permitidas cópias textuais parciais/integrais em qualquer meio com/sem alterações desde que se mantenha este aviso.