Heute werde ich wieder einmal eine nützliche PHP-Funktion vorstellen. Genauer gesagt handelt es sich um eine Klasse, die CSS und JavaScript komprimieren kann. Bei diesem Minification (oder minify) genannten Prozess, werden unnötige Kommentare, Leerzeichen, Tabulatoren und Zeilenumbrüche entfernt, wodurch die Datei kleiner wird und so schneller an den Benutzer übertragen werden kann. Zusätzlich kann in der Klasse der „bereinigte“ Quellcode auch noch vor der Übertragung mit gzip oder Deflate komprimiert werden, damit er noch schneller übertragen werden kann.
<?php
class minifier {
public function minify_CSS($str, $zip = FALSE) {
$str = str_replace(array("\r", "\n", "\t"), '', $str);
$str = preg_replace('#/\*(.*)\*/#U', '', $str);
header('Content-Type: text/css; charset=UTF-8');
header('Cache-Control: public, max-age=1209600');
if($zip === TRUE)
$str = $this->zip($str);
echo $str;
}
public function minify_JS($str, $zip = FALSE) {
$str = preg_replace('#//.*#', '', $str);
$str = str_replace(array("\r", "\n", "\t"), '', $str);
$str = preg_replace('#/\*(.*)\*/#U', '', $str);
header('Content-Type: text/javascript; charset=UTF-8');
header('Cache-Control: public, max-age=1209600');
if($zip === TRUE)
$str = $this->zip($str);
echo $str;
}
protected function zip($str) {
if(isset($_SERVER['HTTP_ACCEPT_ENCODING']) === TRUE) {
if(stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') !== FALSE) {
header('Content-Encoding: deflate');
$str = gzdeflate($str, 9);
} elseif(stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE) {
header('Content-Encoding: gzip');
$str = gzencode($str, 9);
}
}
return $str;
}
}
?>
Die Klasse kann dann in einer beliebigen Datei so aufgerufen werden:
<?php
require_once('minifier.class.php');
$min = new minifier();
$min->minify_JS('[JavaScript-Quellcode]', TRUE);
$min->minify_CSS('[CSS-Quellcode]', TRUE);
?>
Im Gegensatz zu vielen anderen Minifiern habe ich versucht die Optimierungen „leichtgewichtig“ zu gestalten, also einen Kompromiss aus Bandbreiteneinsparung und Ressourcenschonung zu finden. Viele andere Minifier nehmen nämlich noch mehr Optimierungen vor (Variablenumbenennung, komplizierte RegEx-Konstrukte), die viel Rechenzeit benötigen und daher nur bedingt für die On-the-fly-Erstellung von komprimiertem Code geeignet sind. Sicherlich lassen sich damit die Dateigrößen teils erheblich weiter reduzieren aber auf Kosten der serverseitigen Performance.
Auf blogeum wird die Klasse in einer erweiterten Form auch eingesetzt, um CSS und JS vor der Übertragung zu verkleinern und die Übertragungszeiten zu vermindern.
Wie immer steht der Code unter einer Creative Commons-Lizenz.
Ein Leidensgenosse im Fach Informatik hat mich auf ein sehr witziges und einfaches Handbuch zur funktionalen ProgrammierspracheHaskell aufmerksam gemacht.
Learn You a Haskell for Great Good! beschreibt sehr einfach und anschaulich die Programmiersprache Haskell und zeigt, was man alles damit machen kann. Bereichert wird das Ganze durch witzige Illustrationen, die vom Autor, Miran Lipovača aus Slowenien, selbst gezeichnet wurden.

Für alle Haskell-Geplagten ein wirklich sehr schönes und einfaches Tutorial.
Danke an Ulli für den Tipp.
Auf seiner Website xkcd stellt Randall Munroe drei Mal wöchentlich einen neuen witzigen, handgezeichneten Comic ein. Die Themen sind unterschiedlich, meistens geht es um IT oder alltägliche Dinge, die mit einer gehörigen Portion Humor behandelt werden.



Auf jeden Fall ist die Site einen regelmäßigen Besuch mehr als wert.
Diese Frage beantwortet die Ranking-Liste von TIOBE Software. Die Liste wird auf Grund von Daten der beliebtesten Suchmaschinen erstellt.
The ratings are based on the number of skilled engineers world-wide, courses and third party vendors. The popular search engines Google, MSN, Yahoo!, Wikipedia and YouTube are used to calculate the ratings.
TIOBE Software: TIOBE Index

An der Spitze steht aktuell (das bei mir unbeliebte) Java. Das altehrwürdige C kommt nur auf Platz 2. Interessant ist auch, dass sich, im Vergleich zum Oktober letzten Jahres, keine Veränderung ergeben hat. Das beweist wiederum, dass sich nur durchdachte und gut dokumentierte Programmiersprachen durchsetzen.
Ein wenig verwundert mich, dass PHP schon auf Platz 3 folgt. Ich hätte nicht gedacht, dass es derart weit verbreitet ist um gleich auf Java und C zu folgen wohingegen C++ erst nach PHP kommt.
[via SJMP]
In der Informatik (speziell bei Datenstrukturen) stößt man bei kantengewichteten Graphen auf ein besonderes Problem: Wie findet man die günstigste (auch billigste) Verbindung zwischen einem Startknoten und allen anderen Knoten im Graphen?
Edsger W. Dijkstra, ein niederländischer Informatiker, beschrieb im Jahr 1959 einen Algorithmus, mit dessen Hilfe man die günstigsten Verbindungen in einem solchen Graphen finden kann. Einzige Voraussetzung ist, dass die Kantengewichte nicht negativ sein dürfen.
In der Vorlesungen Datenstrukturen hier an der TU bekamen wir die Aufgabe, diesen Algorithmus in C++ umzusetzen, unter der Voraussetzung, dass der Graph in Form einer Adjazenzmatix gegeben ist.
Um anderen Informatik-Studenten das Leben zu erleichtern, möchte ich im Folgenden meine Implementation veröffentlichen.
C++ Implementation des Dijkstra-Algorithmus
#include <iostream>
// Unendlich "definieren"
#define INF INT_MAX
// Anzahl an Knoten muss "hart" festgelegt werden
#define nodenum 9
class dijkstra {
public:
void setMatrix(unsigned int matrix[nodenum][nodenum]);
void setSource(unsigned int source);
void calculate(bool step);
void trace();
private:
unsigned int matrix[nodenum][nodenum];
unsigned int source;
unsigned int distance[nodenum]; // Array für Entfernungen/Kosten
unsigned int predecessor[nodenum]; // Array für Vorgängerknoten
};
void dijkstra::setSource(unsigned int source) {
this->source = source;
}
void dijkstra::setMatrix(unsigned int matrix[nodenum][nodenum]) {
memcpy(this->matrix, matrix, nodenum * nodenum * sizeof(unsigned int));
}
void dijkstra::calculate(bool step = false) {
// Array für markierte Knoten
bool marked[nodenum];
// Initialisierung
for(int x = 0; x < nodenum; ++x) {
// Kein Knoten ist markiert
marked[x] = false;
// Kosten sind zunächst unendlich (INF = INT_MAX)
this->distance[x] = INF;
// Vorgänger sind nicht vorhanden
this->predecessor[x] = 0;
}
// Startknoten besitzt Kosten 0
this->distance[this->source] = 0;
bool flag = true;
while(flag) {
// minimale Kosten initialisieren
unsigned int minimum = INF;
// zugehöriger (minimaler) Knoten
int node = 0;
// Minimale Distanz ermitteln
for(int j = 0; j < nodenum; ++j) {
// Knoten schon markiert -> überspringen (Zyklen vermeiden!)
if(marked[j]) continue;
// Distance kleiner als Minimum -> neues Minimum gefunden
if(this->distance[j] < minimum) {
minimum = this->distance[j];
node = j;
}
}
// Distanz aktualisieren, wenn Zielknoten über den gefundenen Minimumknoten billiger erreichbar
for(int j = 0; j < nodenum; ++j) {
if(!marked[j] && this->matrix[node][j] != 0 && this->distance[node] + this->matrix[node][j] < this->distance[j]) {
this->distance[j] = this->distance[node] + this->matrix[node][j];
this->predecessor[j] = node;
}
// jeden einzelnen Verbesserungsschritt ausgeben?
if(step == true)
(this->distance[j] == INF) ? printf("INF\t") : printf("%3d\t", this->distance[j]);
}
if(step == true)
printf("\n\n");
// gerade bestimmten Minimumknoten markieren
marked[node] = true;
// sind noch Knoten unmarkiert?
flag = false;
for(int j = 0; j < nodenum && !flag; ++j) {
flag = !marked[j];
}
}
}
// Methode, die den günstigsten Weg vom angegebenen Startknoten zu den anderen Knoten aufzeigt
void dijkstra::trace() {
for(int x = 0; x < nodenum; ++x) {
// Wenn kein Vorgänger vorhanden und Knoten != Startknoten existiert keine Verbindung
if(this->predecessor[x] == 0 && x != this->source) {
printf("Keine Verbindung zwischen %d und %d gefunden\n\n", this->source, x);
continue;
}
printf("G\x81nstigste Verbindung von %d nach %d\n", source, x);
int j = x;
// Vorgänger verfolgen bis zum Ziel ("Rückwärtssuche")
while(this->predecessor[j] != 0) {
printf("%d <- ", j);
j = this->predecessor[j];
}
printf("%d\n\nKosten: %3d\n\n", j, this->distance[x]);
}
}
// Beispielaufruf
void main() {
unsigned int test[nodenum][nodenum] = {
{ 0, 15, INF, INF, INF, INF, INF, INF, INF },
{ 15, 0, INF, 30, 10, INF, 25, 10, 30 },
{ INF, INF, 0, 20, INF, INF, 15, INF, INF },
{ INF, 30, 20, 0, INF, INF, INF, INF, INF },
{ INF, 10, INF, INF, 0, 40, 10, INF, INF },
{ INF, INF, INF, INF, 40, 0, 20, INF, INF },
{ INF, 25, 15, INF, 10, 20, 0, INF, INF },
{ INF, 10, INF, INF, INF, INF, INF, 0, 10 },
{ INF, 30, INF, INF, INF, INF, INF, 10, 0 }
};
dijkstra *blubb = new dijkstra();
// Matrix setzen
blubb->setMatrix(test);
// Startknoten setzen
blubb->setSource(8);
// Algorithmus ausführen
blubb->calculate(true);
// Günstigste Wege aufzeigen
blubb->trace();
system("Pause");
}
Der Code ist dokumentiert, sodass man ihn mit Vorkenntnis des Algorithmus’ verstehen sollte.
Anwendungen
Der beschriebene Algorithmus findet unter anderem bei Routenplanern Anwendung, wenn die kürzeste Verbindung zwischen zwei Orten gesucht werden soll. Die Orte und Zwischenstationen stellen die Knoten des Graphen dar, die Entfernungen dazwischen sind die Kantengewichte.

Ein andere Anwendung wäre beispielsweise ein Freundschaftsnetzwerk, in dem die Verbindungen einer Person zu deren Freunden und Freundesfreunden dargestellt werden soll, etwa in der Art „Wer kennt wen über wen?“
Weitere Informationen gibt’s im entsprechenden deutschen und englischen Wikipedia-Artikel.