blogeum
 

Archiv für den Tag ‘programmieren’

CSS und JavaScript-Minifier

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
/* minifier.class.php */

class minifier {

    public function minify_CSS($str, $zip = FALSE) {
        # Zeilenumbrüche und Tabulatoren entfernen
        $str = str_replace(array("\r", "\n", "\t"), '', $str);

        # Kommentare entfernen
        $str = preg_replace('#/\*(.*)\*/#U', '', $str);

        # Header setzen
        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) {
        # Einzeilige Kommentare entfernen
        $str = preg_replace('#//.*#', '', $str);

        # Zeilenumbrüche und Tabulatoren entfernen
        $str = str_replace(array("\r", "\n", "\t"), '', $str);

        # Mehrzeilige Kommentare entfernen
        $str = preg_replace('#/\*(.*)\*/#U', '', $str);

        # Header setzen
        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) {

            # Welche Verfahren werden unterstützt?
            if(stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') !== FALSE) {

                # Komprimieren mit Deflate-Verfahren
                header('Content-Encoding: deflate');
                $str = gzdeflate($str, 9);
            } elseif(stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE) {

                # Komprimieren mit gzip-Verfahren
                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();

# JavaScript komprimieren
$min->minify_JS('[JavaScript-Quellcode]', TRUE);

# CSS komprimieren
$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.

Haskell ganz einfach

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.

Learn You a Haskell for Great Good!

Für alle Haskell-Geplagten ein wirklich sehr schönes und einfaches Tutorial.

Danke an Ulli für den Tipp.

Witzige und originelle Webcomics

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.

I Know You're Listening

Can't Sleep

Exploits of a Mom

Auf jeden Fall ist die Site einen regelmäßigen Besuch mehr als wert.

Welche Programmiersprache ist gerade in?

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

Hitliste der Programmiersprachen

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]

Algorithmus von Dijkstra

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.

Beispielkarte von Deutschland

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.

Was’n das?

blogeum ist das persönliche Weblog von Christian Gürtler – seines Zeichens begeisterter Webworker und Programmierer. Er studiert gegenwärtig Angewandte Informatik an der TU Chemnitz.

 

Abonnieren

RSS-IconImmer auf dem Laufenden mit den Einträgen aus dem Weblog als Atom-Feed. Nunmehr 72 Abonnenten!

Folge mir auf Twitter

 

Neue Kommentare

Christian: Hallo, interessante Funktion. Ich denke ich werde das Beispiel für JavaScript…

Tobias Neumann: Hallo, interessante Funktion. Ich denke ich werde das Beispiel für JavaScript…

Christian: OK, den Zugriff auf "superglobale" Objekte wie window habe ich nicht bedacht.…

ChrisB: Auf diese Weise haben wir auch JSON geparsed, aber ohne Sicherheitsbedenken.…

Martha: Das wundert mich auch. Rot ist doch eine Warnfarbe. Ich kann mir das auch nur…

 

Neue Einträge

 

Lesenswert

Werbung

Wikio - Top Blog - High-tech

 

© 2009–2010 Christian Gürtler

Die Blog-Inhalte stehen unter einer Creative Commons-Lizenz.

XHTML · CSS

BlogPingR.de - Blog Ping-Dienst, Blogmonitor Blogverzeichnis - Blog Verzeichnis bloggerei.de