Archive for March, 2007

Adsense-Zahlung: es ist noch möglich

In der Deutschen AdSense-Group und diversen Foren liest man immer wieder Horrorgeschichten davon, dass Google AdSense-Konten mit der lapidaren Begründung “ungültige Klicks” schließt, die Publisher sehen natürlich keinen Cent der Einnahmen.

Der Vorwurf des Klickbetrugs wird in keiner Weise mit Logdateien belegt, der Publisher hat keine Möglichkeit sich zu wehren - alles in allem ein ziemlich unmögliches Verhalten von Google. Tatsächlich könnte man einfach bei einem unliebsamen Konkurrenten auf die Seite gehen, und mehrere Tage in Folge wie wild auf die Anzeigen klicken, und schon wird er aus AdSense gekickt.

Nachdem meine Seiten AdSense nur sehr dezent anzeigen, nicht optimiert sind und nicht so viele Besucher haben, hat es acht Monate gedauert, bis ich die 100 Dollar Auszahlungsgrenze zusammen hatte, und in der Zeit habe ich immer wieder um meine Einnahmen gebangt.

Heute habe ich die erste Auszahlung tatsächlich bekommen, und will damit allen anderen AdSense-Publishern von wenig frequentierten Seiten sagen: Es ist noch möglich AdSense zu betreiben ohne herausgekickt zu werden, und tatsächlich Geld zu verdienen. Viel ist es nicht bei mir, was unter anderem daran liegt, dass Sudoku als Thema nicht so viel her gibt.

Technorati Tags: , , , ,

Comments (2)

Open Directory Project-Erfahrungen

Das Open Directory Project ist ohne Zweifel der renomierteste Webkatalog, und Größen wie Google replizieren es für ihre Zwecke.

Nach dem es für eine Weile quasi tot war werden inzwischen wieder neue Links und Editoren aufgenommen, und meine Sudoku-Seite ist seit etwa zwei Wochen in der entsprechenden Kategorie gelistet.

Und das sind meine Erfahrungen: pro Tag kommen im Durchschnitt ein bis zwei Besucher pro Tag, also nicht so wirklich viele.

Besonders in den USA gibt es viele Seiten, die dmoz.org replizieren, und google listet schon etwa zehn Seiten, die die Links übernommen haben, aber von diesen Replikaten kommen so gut wie keine Besucher.

Ob sich das Listing auf die Suchergebnis-Listings auswirkt kann man noch nicht sagen.

Alles in allem lohnen sich Links von anderen guten Seiten zum Thema wie diese hier sehr viel mehr als das ODP.

Technorati Tags: , , ,

Comments

Huffman-Codierung mit Perl 6

Im SVN-Repository von pugs gibt es viele Testcases, unter anderem ein Verzeichnis mit “99 Problems”.

Diese Probleme beziehen sich auf eine Liste von Programmieraufgaben, ursprünglich für die Programmiersprache Logo vorgesehen.

Etwa zwei Drittel dieser Probleme sind schon in Perl 6 gelöst, ein paar interessante sind noch übrig.

Gestern habe ich mich an den Huffman-Code (Problem 50) gemacht.

Das Problem

Der Huffman-Code dient der Komprimierung, und zwar hat man einige Zeichen und ihre Häufigkeiten in einem Text gegeben, und soll anhand dessen für jeden Buchstaben eine Bitsequenz erstellen, sodass die Länge des ganzen Textes minimiert wird.

Tendenziell gilt also, dass häufigere Zeichen eine kürzere Sequenz bekommen. Das führt zu einem Problem: die Sequenzen müssen “präfixfrei” sein, d.h. keine Sequenz darf eine andere als ihern Anfang enthalten.

Wenn ‘a’ also z.B. als ‘10′ kodiert wird, darf kein anderes Zeichen mit ‘10′ anfangen - sonst wüsste man beim lesen der kodierten Daten nicht, ob das ein ‘a’ ist oder eines der Zeichen, die mit ‘10′ anfangen.

Wie geht man also vor?

Der Algorithmus

Der Algorithmus ist erstaunlich einfach. Wenn man ihn mit Stift und Papier nachvollzieht, malt man einfach für jeden Buchstaben eine Box um den Buchstaben, und schreibt die Häufigkeit des Buchstabens hinein:

Dann schreibt man über die beiden Buchstaben mit den niedrigsten Werten für die Häufigkeiten die Summe der Häufigkeiten, und verbindet die Summe und die beiden Werte mit Geraden:

Der Übersichtlichkeit wegen wurden die beiden Buchstaben nach unten verschoben.

Das ganze wiederholt man, wobei man ab dem zweiten Schritt die beiden ersetzten Buchstaben nicht mehr betrachtet, sondern nur noch ihre Summe:

Damit fährt man fort, bis alle Buchstaben verbunden sind:

Und am Ende:

Jetzt fehlt nur noch ein Schritt: an jede Verbindungslinie eine 0 oder eine 1 einzeichnen, und zwar immer zu dem niedrigeren Wert eine 0 und zum höheren eine 1. Umgekehrt ginge es genau so, man muss sich nur auf eine Art festlegen.

Wenn man jetzt die Kodierung eines Buchstaben wissen will, folgt man dem Baum von der Wurzel (oben) bis zu dem Buchstaben, und notiert sich die an den Verbindungen stehenden Nullen und Einser. Ein ‘a’ wird in diesem Beispiel also als ‘0′ kodiert, ein ‘e’ als ‘1101′.

Mit den verwendeten Häufigkeiten kommt man in Summe auf 100 Zeichen. Wenn man diese “ganz normal” mit einer festen Anzahl an Bits pro Zeichen kodiert, benötigt man 4 Bit pro Zeichen, und damit 300 Bit. Mit dieser Huffmankodierung benötigt man nur 224 Zeichen, man hat also etwa ein Viertel der Datenmenge eingespart.

Perl6-Implementierung

Und hier kommt die Implementierung in Perl 6:

use v6-alpha;
use Test;
plan 1;

# die Häufigkeiten
my @fr = (
        ['a', 45],
        ['b', 13],
        ['c', 12],
        ['d', 16],
        ['e', 9 ],
        ['f', 5 ],
         );

# Das erwarten wir, wird später zum Testen verwendet
my %expected = (
        'a' => '0',
        'b' => '101',
        'c' => '100',
        'd' => '111',
        'e' => '1101',
        'f' => '1100'
        );

my @c = @fr;

# hier wird der Baum aufgebaut
while @c.elems > 1 {
    # nach dem zweiten Element der Arrays sortieren:
    @c = sort { $^a[1] < => $^b[1] }, @c;
    my $a = shift @c;
    my $b = shift @c;
    unshift @c, [[$a[0], $b[0]], $a[1] + $b[1]];
}

my %res;

# diese Funktion durchläuft rekursiv den Baum und speichert die
# Ergebnisse im Hash %res ab
sub traverse ($a, Str $code = “”){
    if $a.WHAT eq “Str” {
        %res{$a} = $code;
    } else {
        traverse($a[0], $code ~ ‘0′);
        traverse($a[1], $code ~ ‘1′);
    }
}

traverse(@c[0][0]);

# und jetzt der Vergleich mit dem erwarteten:

is(%res, %expected, “Huffman tree builds correctly”);

Der schwierigste Teil ist erledigt: Der Baum ist gebaut, und aus dem Baum wurde die Kodierung extrahiert. Wenn man jetzt tatsächlich Text kodieren will, muss man ihn Zeichen für Zeichen durchlaufen, und jedes Zeichen $c durch %res{$c} ersetzen. Um es binär darzustellen, müsste man das Ergebnis noch durch die Funktion pack jagen.

Comments

Perl 6: Design by Contract

Perl 6 bringt als eine der vielen Neuerungen ein ausgefeiltes Objektmodell (das man zum Teil in Perl 5 auch schon mit Moose genießen kann).

Eines der neuen Features ist “Design By Contract” (siehe z.B. Bertrand Meyer: Object-oriented Software Construction für eine sehr ausführliche Beschreibung der Idee).

Die Idee ist, Vorbedingungen, “Preconditions” in Methoden zu deklarieren, die beim Aufruf der Funktion sichergestellt sein müssen, und die vom Compiler oder Interpreter zur Laufzeit überprüft werden:

class Math {
    method sqrt(Num $x) {
        PRE {
            $x > 0
        }
        # hier die Wurzel berechnen
        return $wurzel;
    }
}

Ähnlich kann eine Methode mit Postconditions dem Aufrufer versichern kann, dass bestimmte Bedingungen nach dem Aufrufen der Methode erfüllt sind:

class Math {
    method sqrt(Num $x) {
        PRE {
            $x > 0
        }
        # hier die Wurzel berechnen
        return $wurzel;
        POST {
            abs($wurzel**2 - $x) < 0.00001
        }
   }
}

Wenn eine Klasse davon erbt, erbt sie automatisch auch die PRE- und POST-Blöcke. Allerdings kann eine erbende Klasse die Preconditions schwächen (d.h. mit einer neuen ODER-verknüpfen) und Postconditions verstärken (also mit bisheren UND-verknüpfen):

Class ComplexMath is Math {
    method sqrt(Num $x) {
        PRE {
            1;
        }
        # hier kommt die Berechnung
    }
}

Da man aus beliebigen komplexen Zahlen die Wurzel ziehen kann, braucht man die Vorbedingung nicht mehr, sie liefert hier immer 1, also True, zurück.

Dann sollte man noch anmerken, dass das Beispiel hier natürlich überflüssig ist, weil Perl 6 von Haus aus eine sqrt()-Funktion hat, die auch mit komplexen Zahlen umgehen kann.

Technorati Tags: , , , , ,

Comments

Nie wieder Matlab

Für mein “Research-Project” musste ich einiges in Matlab programmieren, und
habe dabei gelernt, die Sprache gründlich zu hassen.

Für viele Aufgaben, die man so als Wissenschaftler häufig braucht, gibt es
sehr schön einfache Lösungen in Matlab.

Das Problem ist, dass die Sprache zu einfach gehalten ist.

Das größte Problem ist, dass man keine Variablen deklarieren kann.

Das schleppt eine Reihe von Problemen mit sich:

  • Keine statischen Checks, ob Variablen deklariert sind
  • Keine statischen Typ-Checks
  • Vermehrte Laufzeitfehler, die man anderweitig zur Kompilezeit
    hätte abfangen können

Ein signifikanter Anteil der Fehler, die ich beim Matlab-Programmieren mache,
sind einfach Vertipper, falsch geschriebene Variablen und Funktionen.

Ein Check zur Laufzeit hat zwei Nachteile gegenüber Kompilezeit:

  1. Vergeudete Rechenzeit
  2. Man weiss nie, ob man in den Testfällen alle Programmpfade
    abgelaufen hat

Nummer 1 hört sich anfangs trivial, ist aber bei numerischen Problemen, die
mehrere Stunden Rechenzeit benötigen, ein erheblicher Frustrationsfaktor: das
Programm rechnet vier Stunden, und stirbt dann mit der Fehlermeldung
“Undefined Variable”. Toll.

Sogar Visual Basic hat die Möglichkeit, mit “Option Explict” die
Deklaration von Variablen zu erzwingen.

Und noch etwas komplett anderes stört mich an Matlab: es ist langsam. Ich habe
ein Programm geschrieben, dass relativ große binäre Dateien ausliest (so
etwa 250MB), und in C braucht es etwa 10 mal weniger Zeit
als in Matlab.

Jetzt werden sicher einige Leser denken: “I/O-Operationen sind nicht unbedingt
Matlabs Stärke, das sind doch mathematische Operationen”. Stimmt, aber auch da
ist Matlab nicht unbedingt schnell.

So kann man zum Beispiel die Faltung (convolution) entweder direkt nach der
Defintion in O(n2) berechnen, oder über den Faltungssatz als
invers Fouriertransformierte des Produkts der Fouriertransformierten der
Argumente (also conv(a, b) = ifourier(fourier(a) * fourier(b))), in
O(n*log(n)). Und was benutzt Matlab? natürlich die langsamer Variante.

Technorati Tags: , ,

Comments (8)

AdSense-Änderung auf meinen Seiten

Auf http://moritz.faui2k3.org/ bin ich dazu übergegangen, AdSense-Werbung nur noch Besuchern zu zeigen, die den Internet Explorer verwenden. Dazu habe ich eine Serverseitige Browserweiche mit SSI verwendet:

<!--#if expr="${HTTP_USER_AGENT} = /MSIE/" -->
Hier ist dann die Werbung
<!--#endif-->

Wenn mich das Ergebnis überzeugt, werde ich das ganze auch noch auf Sudokugarden.de anwenden - mal sehen.

Technorati Tags: , , ,

Comments