Sonntag, 26. Mai 2013

LibreOffice Draw: Kreise auf einem Kreis anordnen

In LibreOffice Draw gibt es zwar inzwischen eine verbesserte Funktion, um Elemente auszurichten und zu verteilen, aber kein Hilfsmittel, um Kreise vernünftig auf einem Kreis anzuordnen.

Folgende Anleitung schafft Abhilfe:
Der Trick ist, dass zunächst einmal vier Kreise (die hier rot markierten) an den Außenkanten eines Quadrats angeordnet (oben, rechts, unten, links ausrichten) und dort mittig bzw. zentriert ausgerichtet werden. Die Kreise werden anschließend gruppiert und kopiert. Anschließend einfügen und um eine bestimmte Gradzahl drehen. In diesem Fall wurde das Verfahren zwei Mal wiederholt und die Gruppe jeweils um 30 ° gedreht, so dass am Ende der Eindruck von auf einem Kreis ausgerichteten Kugeln entsteht. Das Quadrat zum Ausrichten wird am Ende herausgelöscht. Im Prinzip lässt sich dies auch mit einer abweichenden Gradzahl und mit kleineren Kreisen durchführen.

Freitag, 29. März 2013

SimpleCode 2

Ich habe eine eigene Version von SimpleCode in PHP programmiert. Das ging überraschend einfach, wenn auch der Aufwand es zu coden exorbitant war. Ganz verstanden habe ich das Problem noch nicht...
<?PHP

  echo("Hallo Welt!");

?>
Das eigentliche Problem ist, dass ich noch nicht weiß, ob meine Version wirklich schon völlig funktioniert. Der Test hier sagt: Es funktioniert. Wenn ich den PHP-Code direkt posten würde, dann würde er in Blogger nicht angezeigt werden.

Sonntag, 24. März 2013

Die Funktion header()

Ich fange gerade erst an das erste PHP-Tutorial durchzuarbeiten, bin aber in die Verlegenheit gekommen, eine Umleitung zu programmieren. Ich möchte verhindern, dass ein Benutzer auf ein PHP-Skript zugreift, dass Daten eines anderen Skripts verarbeitet und ausgibt.

Im Augenblick behelfe ich mir mit folgendem Code:

if (empty($_POST)){
  header('Location: skript_1.php');
 };

Wahrscheinlich ist das so nicht direkt im Sinne des Erfinders, aber es funktioniert erst einmal.

Sonntag, 10. März 2013

Morse Code Palindrome

Das „Morse Code Palindrome“-Problem gehört zum „HP Code wars“-Wettbewerb 2013 und war eher sehr einfach zu lösen. Einmal galt es eine Botschaft in Morsecode zu übersetzen und dann die Botschaft auf ihre Palindrom-Eigenschaft hin zu untersuchen:
# HP Code wars 2013
# problem 12
# Morse Code Palindrome
# 6 points


def botschaft_decodieren(botschaft):
    """ Bekommt eine Botschaft und setzt sie
    in Morsezeichen um. Leerzeichen und Satzzeichen
    werden ignoriert. Kleinbuchstaben werden nicht
    erwartet oder beachtet.

    """
    morsecode = {"A": "•-", 
                 "B": "-•••",
                 "C": "-•-•",
                 "D": "-••",
                 "E": "•",
                 "F": "••-•",
                 "G": "--•",
                 "H": "••••",
                 "I": "••",
                 "J": "•---",
                 "K": "-•-",
                 "L": "•-••",
                 "M": "--",
                 "N": "-•",
                 "O": "---",
                 "P": "•--•",
                 "Q": "--•-",
                 "R": "•-•",
                 "S": "••••",
                 "T": "-",
                 "U": "••-",
                 "V": "•••-",
                 "W": "•--",
                 "X": "-••-",
                 "Y": "-•--",
                 "Z": "--••"}
    codierte_botschaft = []
    for a in botschaft:
        codierte_botschaft.append(morsecode.get(a,""))
    return "".join(codierte_botschaft)


def palindrom_testen(datensatz):
    """ Testet auf ein Palindrom und
    schickt den Datensatz dazu zum decodieren

    """
    botschaft = botschaft_decodieren(datensatz)
    if botschaft == botschaft[::-1]:
        return True
    else:
        return False


data = """ELEGIZED 
QUIRKILY 
MERCURY 
FACE A WINE 
HAPPY DAY 
FEVER REBEL 
SOPRANOS 
EMIT OLD UFO TIME 
PROTEIN POWDER 
ANNEXING 
ENJOIN 
. """


datensaetze = data.split("\n")
for datensatz in datensaetze:
    datensatz = datensatz.strip(" ")

    if not datensatz == ".":

        if palindrom_testen(datensatz):
            print ("{} is a MCP".format(datensatz))
        else:
            print("{} is *not* a MCP".format(datensatz))
Anders als einige andere Aufgaben des diesjährigen Wettbewerbs eher keine Herausforderung.

Webcrawler zur Websitenanalyse

Bei einer gestrigen Besprechung kam das Problem der Website-Wartung, der Behandlung toter Weblinks, des Aufspürens inzwischen falscher E-Mail-Adressen und - ich ergänze - defekter (Bild–)Dateien auf die Tagesordnung. Das Problem scheint „ungelöst“, jedenfalls wenn man dem Wikipedia-Artikel zu „Toten Weblinks“ glauben darf.

Erste Überlegungen

Ich hatte mir gestern überlegt an drei Stellen ansetzen zu können:
  1. Datenbank-Dump zur Website als CSV-Datei oder als SQL-Datei.
    Vorteil: Die Prüfung erfasst alle Seiten und nicht nur die, die öffentlich zugänglich sind, sondern auch die, die einst zugänglich waren und vielleicht noch von jemandem über ein Lesezeichen besucht werden.

    Nachteil: Per Hand muss zunächst ein Datenbank-Dump erzeugt werden. 
  2. Website im Laufenden Betrieb parsen.
    Vorteil: Ich erfasst die vollständig zugängliche Website und brauche keinen Datenbankzugriff.
    Nachteil: Einige Seiten werden übersehen.
  3. Ich generiere spezielle 404-Seiten, die eine Meldung per E-Mail an den Webadmin absetzen und zeitnah über einen möglichen Fehler der Seite informieren.
Tja.

Ausgabe eines Protokolls
Prüfung der Bilddateien auf dem Rechner
Prüfung der E-Mail-Adressen durch Test-E-Mail und Information an den Empfänger.
Prüfung der Links über Protokoll (Liste) zur manuellen Prüfung und automatischen Prüfung über Test auf 404- oder weitere Fehlerseiten...

Samstag, 9. März 2013

Family tree

Eigentlich könnte „Family tree“ ein schönes Problem sein, müsste man nicht eine durchaus komplexe Datenstruktur aufbauen, die sowohl aufsteigend, als auch absteigend durchsucht werden kann. Ich denke daran die Datenstruktur in ein Dictionary zu packen und die Auf- bzw. Abwärtssuche dann gesondert zu implementieren.

Ein- und Ausgabe

Ich erhalte als Eingabe folgende Datensätze:
9 
A + B : C , D , E . 
F + G : H . 
I + J : K , L . 
C + H : M , N . 
D + K : O . 
L + E : P , Q , R , S . 
N + Q : T , U , V . 
O + S : W , X . 
Y + H : Z . 
7 
K > O ? 
F > W ? 
B ^ U ? 
O ^ V ? 
A > Z ? 
F > Z ? 
X ^ Z ?

Die Ausgabe soll folgendermaßen aussehen:
K > O ? TRUE 
F > W ? FALSE 
B ^ U ? FALSE 
O ^ V ? TRUE 
A > Z ? FALSE 
F > Z ? TRUE 
X ^ Z ? FALSE 

Das Problem

Eine Visualisierung dient der ersten Orientierung:

Ein Stammbaum erzeugt aus den Anweisungen

Also gehen wir es an.

Room for an argument

Room for an argument“ war Problem 11 bei HP Code wars 2013 und es gab hierfür insgesamt 5 Punkte, was mir recht hoch erscheint, wenn man sich das Problem vergegenwärtigt. Insgesamt galt es bei einer Reihe von Texten aus „is“ ein „is not“ zu machen und umgekehrt.

Aus meiner Sicht ließ sich das mit Stringoperationen erledigen ohne jede Zeile gesondert zu parsen, womit ich direkt einen Gedankenfehler gemacht habe, weil ich dabei z. B. „This“ übersehen hatte. Folglich muss doch jede Zeile gesondert geparst werden bzw. müssen die Ersetzungen angepasst werden.
data = """7 
This is not an argument. 
An argument is an intellectual process. 
It is fair if you do not go. 
The ferris wheel is not working. 
A butterfly is beautiful, but litter is not. 
A lady discerns that which is not elegant from that which is. 
A lemur is a monkey and a grivet is a monkey but a chimp is not. """

for i, line in enumerate(data.split("\n")):
    if not i == 0:

        print(line)
        
        line = line.strip(" ")
        line = line.replace(" is not"," ")
        line = line.replace(" is"," is not")
        line = line.replace(" "," is")
        
        print(line,"\n")
Ob die es sich so gedacht haben? Alternativ müsste man jede Zeile in eine Liste aufsplitten und dann jedes Element und ggf. sein Folgeelement einzeln parsen und Änderungen auf einer Liste vornehmen. Die Lösung hier scheint mit vertretbar.