Robitex's Blog

Ideas in the web

Archivi Mensili: agosto 2010

Trailing spaces


Deblanking

Non è affatto semplice in TeX eliminare i caratteri spazio iniziali e finali rispetto ad un testo ed immessi come argomento ad un comando. Spesso vorremmo che il comportamento sintattico di classi e pacchetti fosse appunto quello di non considerare questi caratteri spazio, così da poter scrivere il codice più liberamente.
Per esempio scrivere \cool{ il mio nome è nessuno } in modo equivalente a \cool{il mio nome è nessuno}.

Soluzione in Lua

Provate questo codice:

function deblank(s)
local bs = string.match(s, "^%s*")
local es = string.match(s, "%s*$")
return string.sub(s,#bs+1,#s-#es)
end

io.write("string:")
local ans = io.read("*line")

print("<"..ans..">","<"..deblank(ans)..">")

Si tratta di codice Lua con cui si risolve il problema utilizzando i pattern della libreria standard string. Il pattern “^%s*”, significa trova gli eventuali primi caratteri spazio della stringa, mentre quello “%s*$”, sta per trova gli eventuali ultimi blank nella stringa.
L’uso dello script è semplice: salvate il codice in un file di testo chiamato per esempio “deblank.lua” ed eseguitelo con il comando lua deblank.lua in una finestra di console. Digitando una stringa il programma la stamperà prima intatta e poi priva dei fastidiosi caratteri spazio.
Leggete se vi interessa la documentazione della libreria string di Lua a questo link.

Aggiunta del 19/12/2010:
Il codice si può ulteriormente semplificare. In effetti la domanda generale è: qual’è il pattern che restituisce la stringa depurata degli spazi iniziali e finali?
Il pattern “^%s*(.*)%s*$” non funziona perché il punto rappresenta qualsiasi carattere ed unito all’asterisco significa una qualsiasi sequenza da zero a più caratteri così il pattern non esclude i trailing spaces appartenendo al pattern di ricerca “.*”.
La soluzione è utilizzare il pattern “.-“ che significa sempre da zero a più caratteri ma la ricerca si ferma alla prima corrispondenza del pattern successivo. In altre parole, la corrispondenza è ricercata per il minimo numero di caratteri.
La funzione precedente si semplifica quindi nella seguente:

function deblank(s)
return string.match(s,"^%s*(.-)*%s*$")
end

Il pattern giusto è stato trovato e così anche è stato raggiunto l’obbiettivo iniziale.

Epilogo

La conclusione è questa: il nuovo motore tipografico luatex, è uno strumento dalle enormi potenzialità che potrà portare la qualità tipografica di TeX in innumerevoli nuovi contesti, grazie al piccolo grande linguaggio Lua.

Alla prossima…

Promenade structural


Progetto di Caina

In questo breve video potete constatare come la rappresentazione 3D dei modelli strutturali sia un mezzo formidabile per la comprensione della geometria delle opere. Numerose indicazioni possono essere ottenute per risolvere le complesse relazioni tra aste, l’ottimizzazione dei telai, ed i rapporti con gli elementi architettonici.

Alla prossima!

Comandi mutanti


Mutazioni in LaTeX

Ammettiamo di voler creare un comando LaTeX mutante nel tempo, ovvero un comando che ha un effetto la prima volta che lo si esegue, e che ne ha un altro le volte successive.

Se pensate che un comando del genere non serva, ebbene sappiate che mi son trovato in una situazione in cui un comando del genere avrebbe migliorato la leggibilità del codice ed anche la velocità di esecuzione rispetto a soluzioni più tradizionali.

Codice geneticamente modificato

Definiamo semplicemente un comando che per esempio produce il testo “Pippo” e si auto-ridefinisce per produrre la parola “Topolino”:

\def\timecmd{Pippo%
   \def\timecmd{Topolino}}

Un interessante tentativo di comando mutante. La cosa sorprendente è che funziona perfettamente. Compilate con pdflatex il codice completo seguente e lo costaterete personalmente:

\documentclass{minimal}
\def\timecmd{Pippo%
   \def\timecmd{Topolino}}

\begin{document}
Invitiamo prima \timecmd, e poi \timecmd!

Sicuramente \timecmd{} arriver\`a in ritardo.
\end{document}

Incuriositi? Sappiate che gli annidamenti possono essere anche più di due:

\documentclass{minimal}
\def\timecmd{Pippo%
   \def\timecmd{Topolino%
      \def\timecmd{Pluto%
         \def\timecmd{Evviva}}}}

\begin{document}
Invitiamo prima \timecmd, e poi \timecmd!

Sicuramente \timecmd{} arriver\`a in ritardo, e \timecmd{} si presenter\`a con un bel regalo.

Grideremo pi\`u volte \timecmd, \timecmd, \timecmd.
\end{document}

Ciao!

Variabili dimensionali in LaTeX


Questa mi sembra una buona idea

Naturalmente non so se si tratta di una cosa utile, ma se per caso lo fosse? Meglio non correre rischi e parlarne ;-).

Variabili?

In LaTeX è possibile gestire registri dimensionali per rappresentare per esempio larghezza e altezza di pagina, valore dei margini, dell’interlinea del testo ecc…

La sintassi per la definizione e l’assegnazione di un nuovo registro dimensione è diversa in TeX ed in LaTeX, e noi, giusto per scrivere codice leggermente più veloce, useremo quella TeX:

\newdimen\mydim
\mydim=40pt
\advance\mydim by 5pt
Il registro vale \the\mydim.

Vorremmo invece poter lavorare in sintassi chiave=valore, come con un linguaggio di programmazione, implementando in LaTeX quello che lì avremmo chiamato espressione. Ci avvaremo di un nuovo comando che chiameremo \dim:

\dim{a=40pt}% nuova variabile inizializzata a 40pt
\dim{a=\a+5pt}% la variabile viene incrementata di altri 5pt

% oppure anche:
\dim{a=40pt,a=\a+5pt}

Ebbene si può fare, anche se si corre qualche rischio, utilizzando i pacchetti xkeyval e etextools.

Si, variabili!

Provate a compilare questo codice:

\documentclass{report}
\usepackage{etextools}
\usepackage{xkeyval}
\usepackage{tikz}

\makeatletter
   \DeclareCmdListParser{\parser@csv}{,}
   \def\dim#1{%
      \setkeys*{dimfam}{#1}
      \ifx\XKV@rm\empty
         \setrmkeys{dimfam}%
      \else
         \parser@csv[\definesingle@key]{\XKV@rm}
         \setrmkeys{dimfam}%
      \fi
   }
   %
   \def\definesingle@key#1{\make@newkey#1\@nil}
   \def\make@newkey#1=#2\@nil{%
      % creo la nuova dimensione
      \expandafter\newdimen\csname #1\endcsname
      %
      % creo la chiave ad essa associata
      \define@key{dimfam}{#1}{%
         \csname #1\endcsname=\dimexpr##1\relax
      }
   }
\makeatother

\begin{document}
\dim{a=10mm,b=30mm}a=\the\a;b=\the\b.

\dim{a=78mm,b=\a/2,c=\b/2}a=\the\a;b=\the\b;c=\the\c.

\tikz
\draw (0,0) -- (\c,0) -- (\c,\c)--(\b,\b)--(\b,0)--(\a,0)--(\a,\a);
\dim{a=38mm,b=\a/2,c=\b/2}

\tikz
\draw (0,0) -- (\c,0) -- (\c,\c)--(\b,\b)--(\b,0)--(\a,0)--(\a,\a);
\end{document}

Nel codice ho poi utilizzato PGF (comando \tikz), per mostrarvi come posso far dipendere un disegno dal valore di variabili (ex registri) dimensionali.

Alla prossima.

Il triangolo di Tartaglia (Pascal triangle)


Il triangolo di Tartaglia

Eravamo nel lontano 1983 (ricordo l’uscita dell’ultimo album “The final cut” dei Pink Floyd.), quando frequentai il mio primo corso di informatica.
Era da poco uscito l’avanzatissimo personal computer di Olivetti chiamato M20, ed il corso verteva sulla programmazione in linguaggio Basic in ambito gestionale con sessioni di pratica davanti ad alcuni M20 nuovi fiammanti. In altre parole, un’esperienza da ricordare.

Bé direte voi, cosa centra il Triangolo di Tartaglia?
Fatemi continuare!

Al corso ricevetti una serie di dispense sul Basic (che conservo ancora), e la possibilità di effettuare esperimenti reali su macchina.

Il docente era un giovane da non molto laureato in informatica, dai modi di fare gentili e pacati, che esponeva gli argomenti con molta precisione.
Ci faceva ragionare sulla sintassi del Basic disegnando alla lavagna dei diagrammi che rappresentavano vari percorsi alternativi che alla fine producevano l’espressione da inserire nel programma.

Il primo esercizio di programmazione, fu appunto il calcolo e la stampa del triangolo di Tartaglia.

Si doveva utilizzare una struttura dati chiamata array e riempirla della serie numerica del triangolo che, diciamolo, fornisce, tra le molte altre cose, i coefficienti binomiali dell’espressione algebrica (alla riga n):

\displaystyle (a+b)^n

All’epoca del corso non era quindi neanche immaginabile lo sviluppo informatico successivo, ad un corso dove i programmi dovevano essere inseriti ed editati con i numeri di linea, il processore girava a 4 MHz, e l’Hard Disk (quando c’era) poteva superare di poco i 10 MB. Il tutto al costo di ben 16.000.000 di Lire.

Poteva non entrare in Azione Metapost?

L’idea base di Metapost fu resa nota alcuni anni più tardi, nel 1989, e la prima release pubblica risale al 1994.
Questa è un occasione davvero imperdibile: scrivere oggi, con un salto nel tempo, il programma del Triangolo di Tartaglia in Metapost.

L’idea da implementare deve essere, per forza di cose, elegante, almeno per confrontarci con come eravamo allora… (ma anche con il tema del Blog che è “idee nel web”).

   1

  1 1

 1 2 1
 \/
1 3 3 1
...

Un numero nel triangolo si costruisce sommando i due numeri ad esso superiori. Per esempio alla riga quattro, che corrisponde al cubo del binomio, il secondo numero è la somma dei due numeri segnalati dagli slash.

Scartiamo la ricorsione per mantenerci semplici, e valutiamo la seguente idea:
ogni elemento del triangolo si compone di due informazioni: la prima è il valore numerico, la seconda è la coordinata per il posizionamento grafico.

Ogni valore numerico dipende da quelli della riga precedente, ed ad ogni nuova riga troviamo un elemento in più.

Basta dunque lavorare con un array (ancora un array…) chiamato values[], a cui aggiungiamo un elemento alla fine, e lo rielaboriamo tante volte quante sono le righe volute, per trasformarne i valori in quelli corretti di riga.

Abbiamo decritto dunque un classico, due cicli for nidificati, dove nel più interno a partire dalla fine, vengono modificati i valori sommando quelli attuali nell’array (che ancora detengono quelli della riga precedente), e disegnando gli elementi nei punti corretti.

L’informazione della posizione di tracciamento è mantenuta da una variabile punto chiamata pos, che localizza l’ultimo numero sulla riga corrente, mentre la posizione sulla stessa riga è ottenuta sottraendo da pos il vettore (xstep,0) il giusto numero di volte.

Regolando i valori di xstep ed ystep, è possibile aggiustare facilmente l’aspetto del triangolo.

outputtemplate:="tartaglia.mps";

beginfig(1);
   % Tartaglia array values
   numeric values[];
   values[0]=0;

   % triangle deep
   numeric deep;
   deep := 13;

   % position of the triangle top number
   pair pos;
   pos := origin;

   % step among row
   numeric ystep;
   ystep:= 18;
   % step among column
   numeric xstep;
   xstep := 36;

   % main loop
   for k:= 1 upto deep:
      values[k] := 1;
      label("1",pos);

      for i:= k-1 downto 1:
         values[i]:=values[i]+values[i-1];
         label(decimal values[i], pos - (k-i)*(xstep,0));
      endfor;

      pos := pos + (xstep/2,-ystep);
   endfor;
endfig;
end
Il triangolo di Tartaglia

Il triangolo di Tartaglia

Se avete compreso il codice, e quindi probabilmente l’avete anche eseguito (magari cambiando il numero di righe), e ne siete rimasti colpiti dall’eleganza, allora il merito andrà ad oggi, viceversa, andrà ad un magnifico giorno primaverile di 27 anni fa, quando alla lavagna cominciò a comparire un numero alla volta, il triangolo di Tartaglia.

Ciao, alla prossima.

METAPOST ed il prodotto scalare


Se la geometria aiuta

Recentemente riflettevo come raramente il grande pubblico televisivo sente parlare di matematica. Eppure è una scienza fondamentale per l’evoluzione della nostra specie. La tecnologia, dai telefonini alla robotica, la medicina, dagli scenari epidemici alla genetica, l’economia, dalla teoria dei giochi ai mercati finanziari, sono mosse dai numeri e dalle loro relazioni.

Prodotto scalare

Dunque, appena oltre la geometria elementare fatta di triangoli e circonferenze, si trova l’algebra lineare, ovvero il mondo dei vettori.
Una delle prime operazioni che si imparano dei vettori è quella del prodotto scalare, detto così perché riceve due vettori per fornire un numero, che è una grandezza scalare in distinzione da quelle vettoriali.

Si tratta di moltiplicare le lunghezze dei due vettori per il coseno dell’angolo da essi formato. Esiste anche una forma algebrica che consiste nella somma dei prodotti delle corrispondenti componenti dei vettori.

In formule, l’espressione geometrica è:

\displaystyle u \cdot v = uv\cos{\theta}

mentre quella algebrica è:

\displaystyle u \cdot v = u_1v_1+u_2v_2+u_3v_3

L’equazione della retta ed il prodotto scalare

Se l’angolo formato dai vettori è l’angolo retto, il coseno sarà zero e quindi anche il loro prodotto scalare.

Noto quindi un vettore n, i punti Q della retta ortogonale ad n e passante per il punto P soddisfano l’equazione:

\displaystyle n \cdot PQ=0

Se nel piano le componenti di n sono (a,b), quelle di PQ sono (x-x_p,y-y_p), l’equazione della retta si può scrivere nella forma lineare standard (assegnando a c la parte costante dell’espressione):

\displaystyle n \cdot PQ= a(x-x_p)+b(y-y_p)= ax+by+c=0

Applicazione in Metapost

La domanda è già nell’aria: perché non utilizzare le capacità di Metapost di risolvere sistemi lineari per rappresentare una retta a partire da un vettore?

(xpart r - x.P) * xpart n + (ypart r - y.P) * ypart n = 0;
 xpart r = 150;

Il codice completo è il seguente, in cui si è definito una funzione chiamata drawline, che prende un vettore (ed un colore), risolve il sistema come prodotto scalare e disegna il risultato con tanto di etichette.

outputtemplate:="scalar.mps";
beginfig(1);

% solve function to draw the line
def drawline(expr n, col)=
  pair r;

  % linear system
  (xpart r - x.P) * xpart n + (ypart r - y.P) * ypart n = 0;
   xpart r = 150;
  
  drawoptions(withcolor col withpen pencircle scaled 1.4);
  draw (-1.5)[z.P, r] -- 1.28[z.P, r];
  drawarrow origin -- n;
  drawoptions(withcolor black);
  
  % labels
  dotlabel.bot(btex $R$ etex, r);
  label.lft(btex $n$ etex,0.5[origin,n]);
enddef;

% punto di aggancio rette
z.P = (50,100);

pair a;
a := (0,75);

drawline(a rotated  20, blue);
drawline(a rotated -20, 0.7red);
drawline(a rotated -45, green);

dotlabel.bot(btex $P$ etex, z.P);

% ascissa limite
draw (150,-30)--(150,160) dashed evenly;

% draw axis
dim := 200;
dim1 := 12;

drawarrow origin -- (dim,0); % x
drawarrow origin -- (0,dim); % y

label.bot(btex $x$ etex,(dim-dim1,0));
label.lft(btex $y$ etex,(0,dim-dim1));
label.llft(btex $O$ etex,origin);

endfig;
end;
Scalar product: a Metapost example

Scalar product: a Metapost example

Punti e semipiani

Se pensiamo all’equazione della retta nella forma vista del prodotto scalare, è facile rendersi conto che è possibile determinare a quale dei due semipiani appartenga un punto qualsiasi.

Un punto al di sopra della retta (rispetto al vettore (a,b) chiamiamolo “generatore”), formerà un angolo con il vettore generatore inferiore all’angolo retto, per cui il prodotto scalare risulterà positivo. Viceversa se il punto è sotto la retta l’angolo è superiore all’angolo retto pertanto il prodotto scalare sarà negativo.

In definitiva, un punto di coordinate (x,y) sarà sopra o sotto la retta a seconda del segno del valore dell’espressione lineare ax+by+c.

Nello spazio

In “3D” l’espressione lineare ax+by+cz+d=0 è l’equazione del piano ortogonale al vettore (a,b,c), e sottoforma di prodotto scalare permette di capire come assegnare ad un punto qualsiasi il semispazio di appartenenza.
Non male per una banale moltiplicazione.

Ciao, alla prossima.

%d blogger hanno fatto clic su Mi Piace per questo: