Q

Non si prosegua l'azione secondo un piano.

Tag: codi

Trencant un xifratge de substitució

Aquest estiu, la segona sessió de les vermutacions va ser sobre criptografia, i en Ramon ens va posar com a exercici desencriptar un text encriptat mitjançant un xifratge de substitució. Aquest xifrat es pot trencar amb un full i un llapis, i una mica de paciència. Per anar una mica més ràpid, jo vaig utilitzar un petit script en perl que havia fet fa un temps i que està només acabat a mitges, però és més o menys operatiu (però per exemple només agafa textos amb A-Z, sense Ç o lletres per l’estil). Al resoldre’l, em van demanar que pengés l’arxiu, i així ho he fet aquí (és el subsolve).

Subsolve llegeix un text encriptat de stdin o d’un arxiu de text, i llavors permet anar trencant interactivament el text (i la clau). Evidentment, va bé saber (o tenir-ne una suposició raonable) la llengua en què està escrit el text. En aquest cas, subsolve permet comparar les freqüències del text amb una taula de freqüències de l’idioma, si es té aquesta taula. Les taules han d’estar guardades en arxius amb el nom llengua.ngr, on llengua és el codi de la llengua (per exemple, jo utilitzo en per anglès, ca per català, etc.) i n és la longitud de la cadena de la que es recompta la freqüencia (1 per lletres, 2 per dígrams, etc.). L’arxiu ha de contenir a cada línia una lletra, un o més espais i un número (la seva freqüència). Per exemple, l’arxiu amb la llista de freqüències de lletres en català (ca.1gr) seria:

a 12.55
b 1.32
c 3.60
ç 1.06
d 3.94
e 13.89
f 1.00
g 1.28
h 0.72
i 6.99
j 0.30
k 0.00
l 7.74
m 3.16
n 6.40
o 5.71
p 2.72
q 1.35
r 6.76
s 8.43
t 6.11
u 4.18
v 1.40
w 0.00
x 0.52
y 0.00
z 0.01

Per analitzar un text català encriptat, guardat a l’arxiu exemple.txt, es crida l’script amb

./subsolve.pl -f exemple.txt --lang ca --spaces

L’opció --spaces separa les lletres en grups de cinc. Es poden posar menys caràcters per línia amb l’opció -w o --width (per exemple, -w 30).

Una vegada dins, l’opció help o ? ens llista les accions possibles, i help <acció> mostra ajuda específica per una acció (per exemple, help count). count n (o simplement n) compta les freqüències de grups de n lletres. add Ab afegeix la correspondència A->b, on A és una lletra del text encriptat i b la corresponent en el text original. remove Ab ho elimina. show text mostra el text (majúscules la part encriptada, minúscules la part ja resolta). show key mostra la clau. search <cadena> n busca cadena al text, i mostra els resultats envoltats de text a dreta i esquerra de llargada n. La cadena pot contenir majúscules i minúscules (i el programa entén què signifiquen), i també expressions regulars senzilles. Per exemple search A.d 2 busca cadenes que continguin la lletra encriptada A, seguida de qualsevol lletra, seguida de la lletra del text original d, i retorna els resultats amb dues lletres a l’esquerra i a la dreta; o search [AB]C busca la cadena AC o BC; o search [AB]{2} busca les cadenes AA, AB, BA o BB. Per a més informació, feu servir help, llegiu-vos el codi o pregunteu-ho aquí! Comentaris o extensions a l’script són més que benvinguts.

En Ramon també ens va posar un altre exercici: trencar el xifrat Vigenère. Però això ja és una mica més difícil…

Jugant amb la funció CountryData[] del Mathematica

Buscant coses per l’ajuda del Mathematica, avui he trobat la funció CountryData i hi he estat jugant una mica. Resulta que conté un munt d’informació sobre els països del món, i que a més hi ha funcions similars com CityData. Us en posaré un exemple senzill: construïm un graph on els vèrtexs són els països llistats a CountryData, i una aresta uneix dos països si aquests són veïns. Per fer-ho una mica més atractiu visualment, pintarem els vèrtexs en funció del continent al qual pertanyen d’acord amb els colors del Risk. Les arestes tindran també el color del continent si uneixen dos països del mateix continent, o gris si serveixen de pont entre dos continents.

Primer ens fem una funció per a assignar un color a cada continent:

RiskColorsList = {
 {"Africa", Darker[Brown]},
 {"Asia", Darker[Green]},
 {"Europe", Darker[Blue]},
 {"NorthAmerica", Darker[Yellow]},
 {"Oceania", Darker[Purple]},
 {"SouthAmerica", Darker[Red]}
 };

RiskColor[continent_] := If[MemberQ[RiskColorsList[[All, 1]], continent],
  Select[RiskColorsList, #[[1]] == continent &][[1, 2]]
  ,
  Black
  ]

Ara ja podem dibuixar el graf amb tots els països,

GraphPlot[
  Flatten[Thread[# -> CountryData[#, "BorderingCountries"]] & /@
     CountryData[]]~Join~Flatten[{# -> #} & /@ CountryData[]],
  VertexLabeling -> Tooltip, MultiedgeStyle -> None,
  SelfLoopStyle -> None,
  VertexRenderingFunction -> ({PointSize[Large],
      RiskColor[CountryData[#2, "Continent"]],
      Tooltip[Point[#1], #2]} &),
  EdgeRenderingFunction -> ({If[
       CountryData[#2[[1]], "Continent"] !=
        CountryData[#2[[2]], "Continent"], Gray,
       RiskColor[CountryData[#2[[1]], "Continent"]]], Line[#1]} &),
  ImageSize -> Large
  ]

Queden els continents força ben delimitats, oi? Oceania, de color lila, destaca poc perquè els països tenen pocs veïns. Podem situar els vèrtexs al que seria el centre geogràfic de cada país, a veure si el graf agafa una mica la forma dels continents:

GraphPlot[
 Flatten[Thread[# -> CountryData[#, "BorderingCountries"]] & /@
    CountryData[]]~Join~Flatten[{# -> #} & /@ CountryData[]],
 VertexLabeling -> Tooltip, MultiedgeStyle -> None,
 SelfLoopStyle -> None,
 VertexCoordinateRules ->
  Flatten[{# -> ({#2, #1} & @@
         CountryData[#, "CenterCoordinates"])} & /@ CountryData[]],
 VertexRenderingFunction -> ({PointSize[Large],
     RiskColor[CountryData[#2, "Continent"]],
     Tooltip[Point[#1], #2]} &),
 EdgeRenderingFunction -> ({If[
      CountryData[#2[[1]], "Continent"] !=
       CountryData[#2[[2]], "Continent"], Gray,
      RiskColor[CountryData[#2[[1]], "Continent"]]], Line[#1]} &),
 ImageSize -> Large
 ]

Prou bé. Posem-hi el mapa del món per sota:

Show[CountryData["World", "Shape"], %]

Ecco fatto. No queda del tot ben centrat, però aquesta és la idea. Hi ha moltes més dades, a més. Seria divertit per exemple fer el graf dels països relacionats per llengües, per importacions i exportacions, etc. Un altre dia.

otlcat: concatenate and print outline files

Aquest cap de setmana passat vaig escriure un petit script en perl que funciona de manera semblant al famós cat, però que està especialment orientat a outlines. Ho he fet més que res perquè últimament estic trastejant una mica amb The Vim Outliner, com ja vaig comentar fa alguna setmana. Entre altres coses he organitzat una mica alguns How To que tenia repartits entre l’ordinador, aquest blog i internet, i que intentaré penjar quan estiguin una mica més estructurats, i algunes receptes senzilles de cuina, entre les que destaca la paella de carn (dissabte passat va ser un èxit!), que potser també penjaré. Ja veurem.

L’script en qüestió, otlcat, serveix per a imprimir els continguts d’un arxiu a la sortida estàndard (stdout). Si es criden diversos arxius, el seu contingut es concatena. Fins aquí res diferent del cat. La gràcia és que si l’arxiu de text en qüestió és un outline amb el format que utilitza The Vim Outliner (tabuladors per a especificar les jerarquies, els títols comencen directament després dels tabuladors i el text està delimitat pel caràcter ‘|‘), otlcat té un cert control sobre l’output i pot imprimir només fins a una certa profunditat, només text o títols, o títols i text amb profunditats diferents. Per exemple,

$ otlcat -Th2 exemple.otl

imprimiria tots els títol de jerarquia 1 i 2, però cap bloc de text, de l’arxiu exemple.otl.

Com sempre, el codi es troba aquí. Si us mireu una mica el codi, podeu canviar fàcilment el delimitador de text ‘|‘ per algun altre caràcter. Crec, per exemple, que hi ha outliners que utilitzen la coma, o el punt i coma. Per a veure com utilitzar exactament el programa n’he escrit una documentació. N’hi ha prou amb escriure

$ otlcat --man

per obrir una pàgina a l’estil de les man. Instal·lar-la i poder-la consultar com qualsevol altre man és ben fàcil. Per exemple, per posar la pàgina man al vostre directori local:

$ pod2man path/to/otlcat > ~/share/man/man1/otlcat.1

Més endavant potser escriuré altres scripts (per exemple, per just el contrari, un otlsplit no estaria malament). Si teniu alguna suggerència serà benvinguda!

Com a exemple d’aplicació, otlcat es pot utilitzar directament des del vim. Per exemple, si ens volem carregar tot el text (però no els títols) d’un conjunt de línies, les podem seleccionar des del mode visual (s’hi entra amb v) i seguidament escriure

:!otlcat -T

(que en realitat quedaria com :'<'>!otlcat -T). Fàcil!

Més URLs al Vim: ara, ressaltades

Ahir comentava com obrir URLs directament des del Vim. Ja que hi som i que tenim l’expressió regular per detectar-les, no ens costa res ressaltar-les una mica però veure-les venir. Com sempre, al ~/.vimrc:

highlight HyperLink ctermbg=black ctermfg=darkcyan cterm=underline
match HyperLink _[a-z]\+://[^ \>,;:]\+_

La primera línia ens diu com hem de ressaltar el grup HyperLink. ctermbg i ctermfb determinen respectivament el color del fons i del tipus de lletra. cterm a seques, la decoració. La segona línia ens defineix el grup HyperLink (i ha d’anar per sota la primera). Per a més informació, :help highlight i :help match.

Vim: obrir URLs amb l’open de Mac

Doncs això. Estàs treballant amb un fitxer de text des del vim i de cop et trobes amb una adreça d’internet que vols obrir. Per no haver-la de copiar, obrir el navegador i enganxar-la, pots escriure la següent funció al teu ~/.vimrc:

function! OpenURI()
  let s:uri = matchstr(getline("."), '[a-z]\+://[^ \>,;:]\+')
  echo s:uri
  if s:uri != ""
    exec '!open "' . s:uri . '"'
  else
    echo "No URI found in line."
  endif
endfunction

Aquesta funció utilitza la comanda open de Mac, utilíssima. Suposo que adaptar-ho a un altre sistema operatiu és fàcil, sobretot si tot el que t’interessa és obrir una pàgina web. Ara, quan estiguem situats en una línia on hi ha una adreça de l’estil http://&#8230; (o …://…), n’hi ha prou amb escriure

:call OpenURI()

I ens obrirà la pàgina en el nostre navegador per defecte. Com que això és una mica pesat, al ~/.vimrc hi podem incloure també la línia

map ,o :call OpenURI()

i així només ens caldrà apretar la combinació de tecles ,o (o qualsevol altra que definim, això va a gustos).

Follow

Get every new post delivered to your Inbox.

Join 159 other followers