Tuesday, August 30, 2011

Mal schnell ein Wahrheitstabelle mit Phython erzeugen

Wenn man alle Ergebnisse einer logischen Verknuepfung sehen will muss man eine Wahrheitstabelle aufstellen. Bei zwei oder drei Operanden mag das ja noch mit Papier und Bleistift funktionieren, danach wird es aber laestig.

Warum also nicht "Programmieren"?

Hier eine schnelle Loesung in Python.


>>> from pprint import pprint
>>> pprint([
[a,b,c,int(
not(a or b and c)
)]
for a in 0,1
for b in 0,1
for c in 0,1
])
[[0, 0, 0, 1],
[0, 0, 1, 1],
[0, 1, 0, 1],
[0, 1, 1, 0],
[1, 0, 0, 0],
[1, 0, 1, 0],
[1, 1, 0, 0],
[1, 1, 1, 0]]


Erzeugt wird dabei Liste aus Listen deren jeweils letztes Element das Ergebnis der logischen Verknuepfung (hier: /(a + bc)) ist.

Benoetigt man weitere Parameter, wird einfach das Tupel in Zeile 2 der Anweisung erweitert und weitere 'for ... in 0,1' Elemente hinzugefuegt (diese duerfen auch in einer Zeile stehen).

Ist man nur an den Kombinationen von Eingangsparametern interessiert, deren Funktionsergebnis Wahr ist, sieht die Sache noch einfacher aus:


>>> from pprint import pprint
>>> pprint([
[a,b,c]
for a in 0,1
for b in 0,1
for c in 0,1
if not(a or b and c)
])
[[0, 0, 0], [0, 0, 1], [0, 1, 0]]


... oder doch wieder etwas komplizierter:


>>> from pprint import pprint
>>> pprint([L for L in [
[a,b,c,int(
not(a or b and c)
)]
for a in 0,1
for b in 0,1
for c in 0,1
] if L[-1] == 1])
[[0, 0, 0, 1], [0, 0, 1, 1], [0, 1, 0, 1]]

Saturday, August 20, 2011

Viele Digitalbilder in einer handlichen PDF-Datei unterbringen

Aus einer Sammlung von 108 Digitalbildern mit einer Aufloesung von 2816 x 2112 Punkten und einer durchschnittlichen Groesse von 2.4MB soll eine handliche PDF-Datei mit Seiten im A5-Querformat erstellt werden. Jedes Bild sei dabei auf einer eigenen Seite mit einem Seitenrand von 1 cm untergebracht.

Das Konvertierungswerkzeug meiner Wahl ist ImageMagick-convert (auf einer Linux-Kiste).

1 Zoll entspricht 2.54 Zentimeter.
Ich verwende hier die Standardaufloesung von 72 Punkten pro Zoll.

Die Breite des Randes laesst sich wie folgt ermitteln:
1 cm * 72 pt/in / 2.54 cm/in = 28 pt

Die Ermittlung der Parameter fuer die Seitenlaengen ist entweder einfach, wenn man hier nachschaut:
oder etwas komplizierter, wenn man es selber berechnet:

Das Format A0 hat einen Flaecheninhalt vom 1qm und ein Seitenverhaeltnis von lang : kurz = wurzel(2) : 1. Zum naechst kleineren Format halbiert sich der Flaecheninhalt (die Laenge der kurzen Seite ist dabei gleich der Laenge der langen Seite des naechst kleineren Formats).

1 qm = l * k = (wurzel(2) * k) * k = wurzel(2) * k^2
k^2 = 1 qm / wurzel(2)
k = wurzel(1 qm / wurzel(2)) = wurzel(1 qm / 2^0.5)
k = wurzel(2^-0.5 qm) = 2^(-0.5 * 0.5) m
k = 2^(-0.25) m = 841 mm
l = wurzel(2) * k = 2^0.5 * 2^(-0.25) m = 2^(0.5+(-0.25)) m
l = 2^0.25 m = 1189 mm

Um den Flaecheninhalt des Formates An zu erhalten halbiert man 1 qm n-mal (1, 1/2, 1/4, 1/8, 1/16, ...).
F = 1 qm * 2^(-n)

Fuer k und l ergeben sich nun folgende Berechnungsvorschriften:
kn = 2^(-0.25) * wurzel(2^(-n)) m = 2^(-0.25) * 2^(0.5*(-n)) m
kn = 2^(0.5*(-n) - 0.25) m
ln = 2^(0.25) * wurzel(2^(-n)) m = 2^(0.25) * 2^(0.5*(-n)) m
ln = 2^(0.5*(-n) + 0.25) m

k5 = 2^(0.5*(-5) - 0.25) m = 2^(-2.75) m = 149 mm
k5 = 2^(-2.75) m * 72 pt/in / 0.0254 m/in = 421 pt
l5 = 2^(0.5*(-5) + 0.25) m = 2^(-2.25) m = 210 mm
l5 = 2^(-2.25) m * 72 pt/in / 0.0254 m/in = 596 pt

Abzueglich des Randes bleiben fuer das Bild also noch 568 x 393 Punkte. Damit beim Zoomen am Bildschirm noch ein paar Reserven da sind, werden diese Werte noch auf 1136 x 786 verdoppelt.

mkdir sm
find -maxdepth 1 -type f -name '*.JPG' -print -exec convert {} -scale 1136x786 sm/{} \;
convert -page 596x421 -density 72 -border 28 -bordercolor white sm/* Zusammenfassung.pdf
rm -r sm

Die resultierende Datei ist ca. 25 MB gross (10% der Bildersammlung).

Immer auf die Grossen

Kuerzlich lud ich zu einer Versammlung an der frischen Luft, bei der leckere Speisen direkt vom Grill verzehrt und Fruchtsaefte und -extrakte, die einen Gaerungsprozess durchlaufen haben, getrunken werden konnten. Bereitgestellt habe ich dafuer wie ueblich auch Teller aus nachwachsenden Rohstoffen und Sammelbehaelter fuer "den Muell" - fuer Pappe und Papier eine Papiertuete und fuer Folien, Kronkorken und andere Ressourcen mit einem Gruenen Punkt eine Tuete mit einem Gruenen Punkt drauf, in der vorher hier verwendete Lebensmittel hermetisch verpackt waren.

Im Grossen und Ganzen verlief alles wie geplant und die bereitgestellten Behaelter wurden wie vorgesehen benutzt.

Als es dem Ende zuging, gab es sogar freiwillige HelferInnen, die sich an den Aufraeumaktionen beteiligten. Ein Ereignis dabei erregte mein Gemuet und veranlasste mich letzendlich dazu, diesen Text zu schreiben. Da wurden doch tatsaechlich die beiden Ressourcentueten vereinigt und mit den Worten "wir trennen den Muell jetzt nicht erst" fast einer Restmuellentsorgung zugefuehrt. Dem konnte ich vorbeugen, indem ich mich dann letztendlich selber um den Abtransport kuemmerte. Papier in die Blaue, Gruener Punkt in die Gelbe und am Ende war nichts uebrig fuer die schwarze Tonne.

Sicherlich habe ich dadurch nicht das Weltklima gerettet oder unsere Deponien vor Ueberfuellung bewahrt. Was mich an der Sache masslos ankotzt ist, dass wir uns aufregen ueber "die Grossen". Oelkonzerne, die Meer und Land verseuchen. Energiekonzerne, die strahlenden Atommuell irgendwo lagern. Chemieunternehmen, die mit Giften unsere Umwelt belasten.

Aber wir Kleinen sind selber nicht in der Lage, das geringste zum Schutz der Umwelt beizutragen. Warum koennen wir nicht einfach den Muell trennen? Warum haben wir keine Steckdosenleiste mit Schalter vor unseren HiFi- und EDV-Geraeten? Warum lassen wir den Kuehlschrank eine halbe Ewigkeit offen und betrachten uns den Inhalt aus der Ferne?

Es muss jemand damit Anfangen - und das koennen nur die Kleinen sein. Wer genau hinschaut, erkennt, das es gar keine Grossen gibt. Das sind viele kleine, die zusammen gross erscheinen. Ich kenne keinen Herrn Shell (aus aktuellem Anlass ist mir gerade dieser Name eingefallen - es koennte hier auch Herr ThyssenKrupp oder Herr Vattenfall oder Herr Bayer oder ... stehen). Ich kenne aber viele Mueller, Meier und Schulze, die dort angestellt sind und Shell zu etwas grossem machen.

Also: FANGEN WIR AN und machen nicht fuer alles die "Grossen" verantwortlich.

Wednesday, August 10, 2011

Pfadseparator unter Windows (und DOS) - "\" oder "/"

Immer und immer wieder sehe ich in Quelltexten, Frameworks, Bibliotheken und Anwendungen fuer Windows, dass Pfadangaben ueberprueft und vorwaerts gerichtete Schraegstriche automatisch in rueckwaerts gerichtete umgewandelt werden. In ganz schlechten Implementierungen passiert das sogar auf mehreren Ebenen, also fuer ein und die selbe Zeichenkette mehmals. Und das alles, um "Plattformunabhaengingkeit" zu schaffen.

Die Wahrheit ist aber, dass sowohl Windows als auch MS-DOS im Kern mit beidem umgehen koennen. Das Problem ist die Shell (und andere Programme). COMMAND.COM und CMD.EXE benutzen (aus historischen Gruenden, CP/M) den Vorwaertsschraegstrich fuer die Einleitung von Programmoptionen. Sieht der Interpreter also einen vorwaerts gerichteten Schraegstrich, so ist das fuer ihn keine Pfadangabe sondern eine Programmoption.

Note File I/O functions in the Windows API convert "/" to "\" as part of converting the name to an NT-style name, except when using the "\\?\" prefix as detailed in the following sections.
Das heisst, der Kern tut's eh, also lasst es bleiben. Um wirklich plattformunabhaengig zu sein, benutzt der vorwaerts gerichteten Schraegstich als Pfadtrennzeichen, wie es auch im POSIX-Standard geschrieben steht und warnt den Benutzer, wenn er einen rueckwaerts gerichteten verwenden will.

Die daraus resultierenden Vorteile sind einerseits die Steigerung der Performance - Zeichenkettenoperationen sind teuer - und andererseits die Vermeidung von Inkompatibilitaeten mit Systemen, die einen rueckwaerts gerichteten Schraegstrich nicht akzeptieren (wahrscheinlich alle anderen ausser Windows und DOS). Letztere auch sind der Anlass fuer diesen Artikel. Dabei normalisiert eine in Python geschriebene Anwendung mit FTP-Server-Komponente einen vom Benutzer eingegeben Pfad. Alle "/" werden von Python automatisch durch "\" ersetzt und damit ein vorher wahrscheinlich gueltiger FTP-Pfad in einen ungueltigen ueberfuehrt.

Eine Moeglich waere es, die Python-Quellen zu modifizieren und selber zu uebersetzen; dann funtioniert es bei mir und bei allen die "meinen" Python-Interpreter verwenden. Die andere Moeglichkeit ist es, nach der Normalisierung wieder alle "\" durch "/" zu ersetzen. Und somit wird aus dem urspruenglichen Ziel, plattformunabhaengig zu sein, ein echtes Laufzeitproblem.