Dienstag, 26. Februar 2013

HTML in Blogger posten

Ich habe hier nun ein nettes kleines Tool gefunden, das mir HTML-Code in SimpleCode umwandelt, der in Blogger angezeigt werden kann. Problematisch scheinen dabei die Zeilenumbrüche zu sein und die eckigen Klammern, also < und >. Daraus ergibt sich für mich, dass sich das (bestimmt) auch einfach als Desktop-Tool mit GUI umsetzen lässt, denn die Korrekturen scheinen momentan nicht der Rede wert.

HTML-CODE Zeichen
< &lt;
> &gt;
\n <br />

Ferner muss oben und unten ein code-Tag ergänzt werden, wobei die Zeile ansonsten freibleibt. Auch das ist in Python nicht kompliziert umzusetzen.

Samstag, 23. Februar 2013

Zeilenumbruch in HTML

Es gibt aktuell drei Möglichkeiten einen Zeilenumbruch in HTML zu codieren, allerdings ist nur die erste Variante mit &shy; auch wirklich zu empfehlen, weil es erstens ein Trennstrich einfügt und zweitens nicht proprietär ist.

Freitag, 22. Februar 2013

Logelei

Im heutigen Zeit Magazin (21. Februar 2013, Nr. 9, S. 76) habe ich ein Rätsel in der Rubrik „Logelei“ gefunden.

Im Kern geht es darum die sechs Wörter TETRAEDER, WUERFELOKTAEDERDODEKAEDER, IKOSAEDER und KUGEL so in einem Gitter von 16 Zellen zu verteilen, dass sie darin Platz finden. Der Start eines Wortes im Gitter ist beliebig und der nächste Buchstabe kann dann waagerecht, senkrecht oder diagonal benachbart sein. Buchstaben dürfen dabei in einem Wort mehrfach verwendet werden. Die Lösung sei eindeutig, so die Erklärung.

Das Gitter ist vorstrukturiert und sieht wie folgt aus:

Das Gitter mit drei eingetragenen Buchstaben
Als Tipp ist formuliert, dass, kommt ein Buchstabe mehrfach vor, dann jedes Mal derselbe Buchstabe im Gitter verwendet werden soll.

Arbeit an einer Lösung

Ein erster Zugriff ergibt, dass es insgesamt 14 Buchstaben gibt, die verteilt werden müssen und zwar:

A, D, E, F, G, I, K, L, O, R, S, T, U, W.

Da das T bereits zweimal gesetzt ist, darf nur ein weiterer Buchstabe ebenfalls zweimal im Gitter vorkommen. Es stellt sich die Frage, ob T besonders häufig vorkommt oder es eine andere Besonderheit gibt.

Zu den Buchstabenhäufigkeiten:

A   4
D   6
E  13
F   1
G   1
I   1
K   4
L   2
O   3
R   6
S   1
T   3
U   2
W   1


Also T ist nicht so häufig, d. h. ADEK und R sind alle häufiger enthalten.

Andererseits kommt T nur in zwei Wörtern vor und zwar in TETRAEDER und OKTAEDER.

Ich habe mir einmal die Bindungen visualisiert, was folgendes Bild ergibt:
Ein Graph mit den Buchstaben und den Nachbarn
Problem ist hier aus meiner Sicht, dass T und E eigentlich doppelt eingetragen werden müssen. T ist bereits doppelt gesetzt und E hat laut Plan 8 Nachbarn, nämlich L, GUDATR und F, das E oben rechts in der Ecke hat aber nur 3 mögliche Nachbarn.


Lösung

Inzwischen ist die Lösung im Netz verfügbar, die wie folgt aussieht:

T
F
L
E
R
E
U
G
D
A
K
W
S
O
T
I

Donnerstag, 14. Februar 2013

CSS

Ich schaue mir augenblicklich etwas CSS an. Ich habe gestern mal eine Website in LibreOffice Draw entwickelt und Gestaltungselemente verbaut und somit ein Mockup gestaltet. Die Umsetzung in CSS und das Erlernen der notwendigen CSS-Elemente stelle ich mir momentan noch schwierig vor.

Im Prinzip stelle ich mir vor, dass CSS etwas wie die Formatvorlagen bei LibreOffice Writer sind. Mein Problem hierbei ist, dass ich noch nicht wirklich durchblicke, ob ich den Sachverhalt damit im ersten Schritt adäquat verstehe.

Ziel der ganzen Übung ist es ein eigenes Wordpress-Theme zu schreiben, dass ich dann später mit Inhalten füllen kann.

Literatur und Ressourcen

Folgende Ressourcen habe ich mir angesehen:

CSS

  • Kai Laborenz: CSS-Praxis. Browserübergreifende Lösungen. Bonn: Galileo Press 42006. ISBN 978-3-89842-765-4
  • Florence Maurice: Jetzt lerne ich CSS3. Modernes Webdesgin verstehen und anwenden. München: Markt+Technik Verlag 2012. ISBN 978-3-8272-4745-2

Wordpress-Theme


Erste Gehversuche

Hier muss noch Text hin.


Mittwoch, 13. Februar 2013

Ringworld

Ringworld (Problem 2, 2012) für 3 Punkte - bei manchen Aufgaben von HP Codewars versteht man die Punkteverteilung nicht. Ringworld ist eine der eher sehr einfachen Aufgaben:
pi = 3.14159265

for data in [(95000000,997000),(92955887.6,131072)]:

    ringworld_radius = data[0]
    ringworld_width = data[1]

    result = 2 * pi * ringworld_radius * ringworld_width

    result_earths = result / 196935000
        
    print("{} EARTHS".format(int(result_earths)))
Einzige Schwierigkeit bei der Aufgabe sind die verschiedenen Einheiten, die man leicht überließt, so dass es zu Fehlern im Programm kommen kann.

Während die Oberfläche der Erde in Millionen Quadratmeilen (million square miles) angegeben ist, werden der Radius und die Weite der Ringworld in Meilen angegeben (miles). Ist das erfasst, ist die Aufgabe mehr als simpel.

Montag, 11. Februar 2013

Secret Code

Eine einfache Verschlüsselungsübung, die ich mir noch einfacher gemacht habe. Das Skript ist zugleich Lösung für eine Aufgabenstellung des HP Codewars 2001:
data = """Hewlett-Packard Company, Year 2000 Financial Report
end"""

data = data.split("\n")

for line in data:
    ''' Das könnte man auch in eine Funktion
    packen, jedenfalls wird hier die Message
    verschlüsselt...

    '''
    # Um es mir einfach zu machen habe ich
    # zusätzlich zu den Großbuchstaben
    # auch die Kleinbuchstaben ins Code-
    # Wörterbuch aufgenommen...
    codes = {"A":"*",
             "a":"*",
             "E":"$",
             "e":"$",
             "I":"#",
             "i":"#",
             "O":"!",
             "o":"!",
             "U":"%",
             "u":"%",
             "Y":"^",
             "y":"^"}
    if line == "end":
        pass
    else:
        for key in codes.keys():
            line = line.replace(key,codes[key])        

        print(line)
Alternativ hätte man die Message Buchstabe für Buchstabe durchlaufen können und prüfen können, ob Buchstabe.upper() im Wörterbuch steht und die Daten dann entsprechend z. B. an eine Liste anhängen können. Das Ergebnis würde dann codiert zurückgegeben werden. Für 2 Punkte darf man es sich wohl einfacher machen.

Graphentheorie

Im Netz gibt es mehr oder weniger brauchbare Videos zum "kürzeste Wege-Problem", zu dessen Lösung der Dijkstra-Algorithmus genutzt wird.

Ein Graph sieht zu Beginn so aus:
Abb. 1: Gefunden werden soll die kürzeste Weg zwischen O und T.

Die Lösung sieht dann etwa so aus:
Abb. 2: Das Problem ist gelöst. Die kürzeste Route ist O, A, B, D, T.
Im Netz habe ich zu diesem Thema auf Anhieb ein Video gefunden:


Eine Beispielimplementierung in Python zum Algorithmus findet sich u. a. hier.

Password Analyzer

Ein Passwort hinsichtlich seiner Qualität zu prüfen, wie es bei HP Codewars 2007 (Problem 7) gefordert war, ist keine Herausforderung. Die Funktion war sehr schnell gecodet:
def passwort_pruefen(passwort):
    ''' Prüft die Qualität eines passworts
    und kann 4 Qualitätsstufen als String
    zurückgeben; die Prüfung umfasst folgende
    Punkte:
    * Länge korrekt len(pw) >= 8?
    * wenigstens ein Großbuchstabe enthalten?
    * wenigstens eine Ziffer enthalten?
    
    '''
    qualitaet = 0
    
    # Ist die Länge korrekt, d. h. >= 8?
    if len(passwort) >= 8:   
        qualitaet += 1
    # Ist wenigstens ein Großbuchstabe enthalten?
    for a in passwort:       
        if a.isupper():
            qualitaet += 1
            break
    # Ist wenigstens eine Zahl enthalten?
    for a in passwort:       
        if a.isdigit():
            qualitaet += 1
            break
    
    # Rückgabe
    if qualitaet == 0:
        return "WEAK"
    elif qualitaet == 1:
        return "ACCEPTABLE"
    elif qualitaet == 2:
        return "GOOD"
    else:
        return "STRONG"


passwoerter = ["lizard","aardvark","Aardvark","Aardvark77"]

for passwort in passwoerter:
    
    # eingabe = input("Enter your password: ")
    print("Enter your password: {}".format(passwort))
    print("This password is {}.\n".format(passwort_pruefen(passwort)))
Auch wenn ich aus Bequemlichkeit auf die Eingabe von Passwörtern verzichtet habe und sie aus einer Liste beziehe, bleibt mein Fazit: Keine Herausforderung. Einige andere Aufgaben aus dem Jahr sind schon eine härtere Nuss.

Sonntag, 10. Februar 2013

Minelayer

Bei HP Codewars war 2010 als Problem 7 ein Minelayer zu coden. Ich habe damit jetzt einige Zeit verbracht das Problem zu verstehen und einen tüchtigen Ansatz zu entwickeln. Hauptproblem bei meinem Skript ist m. E. momentan die Funktion (minenfeld_zahlen_eintragen(felder)), die die Zahlen einträgt, weil ich es persönlich als umständlich wahrnehme, wie das codiert ist.

Ein großer Fortschritt gegenüber meinen bisherigen Ansätzen ist jedenfalls, dass das Spielfeld als eine Liste von Elementen codiert ist und erst in der Ausgabe als Feld (Höhe x Breite) erscheint. Die Repräsentation als Liste ist m. E. einfacher als eine Liste bestehend aus einzelnen Listen zu verwalten.

Hier das Skript:
import random

def minenfeld_erzeugen(breite,hoehe,minen):
    ''' Diese Funktion erzeugt das Spielfeld
    '''
    felder = minen * "*" + (breite * hoehe - minen) * "0"
    felder = [a for a in felder]
    random.shuffle(felder)
    return felder


def minenfeld_ausgeben(felder,breite):
    ''' Das Minenfeld ausgeben
    '''
    
    for position,feld in enumerate(felder,1):
        if feld == "0":
            print(".",end=",")
        else:
            print(feld,end=",")
        if position % breite == 0:
            print()


def minenfeld_zahlen_eintragen(felder):
    ''' Beispiel

    ....    ..11
    ...*    111*
    *...    *322
    *.*.    *3*1

    1 2 3
     \|/ 
    4-X-6
     /|\ 
    7 8 9
    
    '''
    for position,feld in enumerate(felder):

        if feld == "*":
            pass   # Da ist eine Mine drauf
        else:
            
            feld = int(feld)
            '''
            1 2 3
             \|/ 
            4-X-6
             /|\ 
            7 8 9
            '''

            positionen = []
            
            ''' Problem

            Im Augenblick werden Sachen fälschlich ausgewertet,
            m. E. gibt es 5 Sonderfälle, die abgefangen werden müssen

            B CCCC D
            
            A XXXX E
            A XXXX E

            '''
            
            # Fall B
            if position == 0:
                positionen = [position + 1,             # 6
                              position + breite,        # 8
                              position + breite + 1]    # 9
            # Fall A
            elif position % breite == 0:
                positionen = [position - breite,        # 2
                              position - breite + 1,    # 3
                              position + 1,             # 6
                              position + breite,        # 8
                              position + breite + 1]    # 9
            # Fall D
            elif position == breite -1:
                # Muss hier stehen, weil sonst die Bedingng
                # bei Fall C das hier 'überschreibt'
                # War zuvor Ursache für einen Bug
                positionen = [position - 1,             # 4
                              position + breite - 1,    # 7
                              position + breite,]       # 8
            # Fall C
            elif position < breite:
                positionen = [position - 1,             # 4
                              position + 1,             # 6
                              position + breite - 1,    # 7
                              position + breite,        # 8
                              position + breite + 1]    # 9
            # Fall E
            # Hier hatte ich Pkt. (%) vor Strich uebersehen
            elif (position + 1) % breite == 0:
                positionen = [position - breite - 1,    # 1
                              position - breite,        # 2
                              position - 1,             # 4
                              position + breite - 1,    # 7
                              position + breite]        # 8
            # Fall X
            else:
                positionen = [position - breite - 1,    # 1
                              position - breite,        # 2
                              position - breite + 1,    # 3
                              position - 1,             # 4
                              position + 1,             # 6
                              position + breite - 1,    # 7
                              position + breite,        # 8
                              position + breite + 1]    # 9

            for item in positionen:
                try:
                    # print(item,felder[item])
                    if felder[item] == "*":
                       feld += 1
                except IndexError:
                    pass
        
        felder[position] = str(feld)
        
    return felder


# Eigentlich

breite = 30
hoehe = 15
minen = 60

felder = minenfeld_erzeugen(breite,hoehe,minen)

felder = minenfeld_zahlen_eintragen(felder)

minenfeld_ausgeben(felder,breite)
Hauptprobleme in der Entwicklung waren:

  1. Die Abhandlung der verschiedenen Fälle war problematisch, weil ich die if-Bedingungen zunächst von A nach E aufgelistet habe und somit einzelne Bedingungen nicht geprüft wurden, weil eine Bedingung zuvor erfüllt war. Dies führte zu Fehlern beim Minen legen.
     
  2. Die verschiedenen Fälle zu umgehen ist mir nicht gelungen. Ich hätte gerne gehabt, dass die Fälle einfacher abzufangen gewesen wären, um mir unnötige Tipparbeit zu ersparen. Eine sinnvolle Lösung habe ich hier aber nicht gefunden.
     
  3. Eine objektorientierte Umsetzung drängt sich hier m. E. auf. Die drei Funktionen scheinen alle von einer anzulegenden Klasse Spielfeld abhängig.
     
Abschließend müsste eine Spielroutine implementiert werden, dass leere Felder und angrenzende Zahlen aufdeckt und so ein Spielen ermöglicht.

Nachtrag

Ich habe mir gerade die offizielle Musterlösung in Java angesehen, die von Don Brace stammt. Im entsprechenden Code-Abschnitt, der gewisse Ähnlichkeiten zu meinem Ansatz aufweist, schreibt er:
/*
  * This could be better optimized, but I leave it up to you :) */

Zumindest kommt er zum gleichen Ergebnis wie ich.

Freitag, 8. Februar 2013

QWERTY Sort

Bei Problem 7 bei HP Codewars war 2011 ein „QWERTY Sort“ zu implementieren, wofür die Teilnehmer damals 7 Punkte bekamen. Die Besonderheit bei diesem Sortieralgorithmus ist, dass eine Liste von Elementen nicht alphabetisch sortiert wird, sondern die Sortierung der Buchstabenfolge auf einer Tastatur mit US-amerikanischem Layout (Z und Y sind vertauscht) folgen soll.

Die Begründung für diese abwägige Aufgabenstellung ist ziemlich schräg, aber das Problem ist lösbar, wenn es auch etwas länger gedauert hat:
# URL http://www.hpcodewars.org/past/cw14/problems/ProblemSet2011Final.pdf
# Problem: 7. QWERTY Sort (7 P)

# Sortierschluessel
ordnung = [a for a in "QWERTYUIOPASDFGHJKLZXCVBNM"]

data = """ARREST
SUBDIVISION
DISCONTENT
SUPERIOR
TOPOLOGY
DEBUNK
APPENDIX
SUBDUE
TRUNK
."""


def liste_sortieren(liste,ordnung):
    ''' Diese Funktion erledigt die Sortierung
    und gibt die sortierte Liste zurueck

    '''
    while True:
        # Wenn die Liste sortiert ist,
        # bleibt das beim Durchlauf auf True
        sortiert = True
        
        # Iterier über die Liste
        for i in range(len(liste)):
            # Prüfe 2 benachbarte Listenelemente,
            # ihre Buchstaben von vorn nach hinten,
            # wenn die Buchstaben gleich, dann weiter
            # sonst
            # a.) bekomme für den Buchstaben1 den Listenindex,
            # b.) bekomme für den Buchstaben2 den Listenindex,
            # wenn a > b, dann tausche
            # sonst bleibt es so
            try:
                for id in range(len(liste[i])):
                    
                    if liste[i][id] == liste[i+1][id]:
                        pass
                    else:
                        if ordnung.index(liste[i][id]) > ordnung.index(liste[i+1][id]):
                            # print("Tausche!",liste[i],liste[i+1])
                            # print("Pruefe gerade:",liste[i][id],liste[i+1][id])
                            # Dreh die beiden Elemente in der Liste um
                            liste[i], liste[i+1] = liste[i+1], liste[i]
                            # print("Getauscht:",liste[i],liste[i+1])
                            # Liste war noch nicht sortiert (!)
                            sortiert = False
                        break  
            except IndexError:  # Ende der Liste erreicht
                pass
            # gehe zum nächsten Listenpaar

        if sortiert == True:
            return liste             # Brich ab!!!
            # Normal break, dann Ausgabe, hier return,
            # weil in eine Funktion gepackt


# Bekomm die Werte
data = data.split("\n")
liste = []
for zeile in data:
    if not zeile == ".":
        liste.append(zeile)


# Liste soll sortiert werden
# Da es nur "eine" Liste gibt,
# brauche ich die nicht an die Funktion zu binden,
# also nicht liste = liste_sortieren(liste,ordnung)
liste_sortieren(liste,ordnung)

# Elemente der Liste werden ausgegeben        - - - Ausgabe
for item in liste:
    print(item)
Naja, noch frage ich mich, ob ein alternatives Sortierverfahren die Aufgabe performanter lösen könnte. Im Kern kopiere ich hier eine Abwandlung des Bubblesort-Algorithmus, wobei meine Implementierung nicht sehr performant ist, weil - wie mir scheint - nicht jeder mögliche Tausch vorgenommen wird.

Dirt Simple Calculator

Für HP Codewars war 2009 als Problem 4 ein schmutziger, einfacher Rechner zu programmieren. Simple, weil die Division nicht unterstützt wird und schmutzig, weil die Punkt-vor-Strich-Rechnung zu ignorieren war:
def term_auswerten(zeile):
    ''' Die Funktion wertet den Term aus,
    Problem hierbei ist,
    a.) dass die Punkt-vor-Strich-Regel
        ausgeklammert ist, d. h.
    b.) der Term von links nach rechts
        auszuwerten ist
    eval() scheidet aus erst einmal aus;
    ein komplexerer Zugriff ist erforderlich
    

    '''
    zeile = zeile.replace(" =","")  # = brauche ich nicht
    zeile = zeile.split(" ")
    term = ""
    
    for a in zeile:

        if a in ["*","+","-"]:
            term = str(eval(term))
            term += a            
        else:
            term += a


    print(eval(term))


data = """28 - 7 * 3 =
13 * 4 + 8 * 2 + 1 =
4 + 3 * 52 =
0 ="""

zeilen = data.split("\n")

for zeile in zeilen:

    if zeile == "0 =":
        pass
    else:
        term_auswerten(zeile)
Die Aufgabe ließ sich schnell lösen, wenn ich auch für die Möglichkeit zur interaktiven Entwicklung dankbar bin. Ich mache noch zu viele Fehler...

Donnerstag, 7. Februar 2013

Card Counting

„Card Counting“ für 7 Punkte als Teil von HP Codewars 2012. Das Lösungsskript - weder funktional noch objektorientiert lautet:
data = """13
5D KC 3C 3D
10C 7D 4C AH
10S JH 6C 10D
7S 2H JS QH
2C 7C KD 8C
QD QS KH 2S
3H 4S 5H JD
3S 4H 5S 6H 
8H 6S 7H QC
9C 8S 9H 6D
2D 8D AS 5C
JC AH 4D KS
AH 9S 10H 9D"""

# Erste Zeile der Daten auswerten
zeilen, data = data.split("\n",1)

# Daten in Zeilen zerlegen
datenzeilen = data.split("\n")

# Karten aufbauen
ranks = ["2","3","4","5","6","7","8","9","10","J","Q","K","A"]
suits = ["S","H","D","C"]

kartenset = {}  # Das ist ein normales Kartenspiel
kartenkeys = [] # Darueber wird die Ausgabe gesteuert

for suit in suits:
    for rank in ranks:
        karte = rank + suit
        kartenset[karte] = 0
        kartenkeys.append(karte)

# Die Daten auswerten
for zeile in range(int(zeilen)):
    kartenzeile = datenzeilen[zeile].strip(" ").split(" ")
    # print(kartenzeile)
    for karte in kartenzeile:
        kartenset[karte] += 1

# Ausgabe
print("Missing cards: ")
for karte in kartenkeys:
    if kartenset[karte] == 0:
        print(karte,end=" ")

print("\n")

print("Extra cards: ")
for karte in kartenkeys:
    if kartenset[karte] > 1:
        print("{} ({})".format(karte,kartenset[karte]-1),end=" ")   # - 1

print()
Die erwartete Ausgabe stimmt. Es ist zu beachten, dass bei den zusätzlichen Karten die Anzahl der Karten im Deck um 1 verringert wird, weil ja eine Karte im Deck enthalten sein soll.

Mittwoch, 6. Februar 2013

List maker

Eine nette kleine Aufgabe bei HP Codewars aus dem Jahr 2010 und die Lösung:
def abarbeiten(data):
    ''' Bekommt als data eine Reihe von Befehlen
    und fuehrt Aufgaben auf einer Liste aus

    '''
    liste = []
    zeilen = data.split("\n")
    for line in zeilen:

        line = line.strip(" ")
        
        if line == "SHOW":
            print(" ".join(liste))
        else:
            befehl, inhalt = line.split(" ",1)

            if befehl == "ADD":
                # ADD X – puts item X at the end of the list
                liste.append(inhalt)
            elif befehl == "INSERT":
                # INSERT X N – puts item X into the list just before item N
                item, item_alt = inhalt.split(" ")
                position = liste.index(item_alt)
                liste.insert(position,item)
                
            elif befehl == "REMOVE":
                # REMOVE X – removes item X from the list
                liste.remove(inhalt)

                
data = """ADD NEVER
ADD COLLAR 
INSERT CAT COLLAR 
ADD DOG 
ADD SCARES
INSERT ANYTHING CAT
REMOVE CAT
INSERT THAT SCARES
REMOVE COLLAR 
INSERT WEAR ANYTHING
REMOVE DOG  
ADD CAT
INSERT YOUR CAT
SHOW"""

abarbeiten(data)
Eine eher einfache Aufgabe. Neu für mich der Befehl insert() bei einer Liste.

Secure the Perimeter

Hier soll lediglich der Umfang eines Rechtecks berechnet werden. Es war eine Aufgabe (Problem Nr. 1) bei HP Codewars 2010. Die Formel zur Berechnung des Umfang eines Rechtecks lautet:

U = 2 * H + 2 * B

Das ist keine Herausforderung und die Verarbeitung der Eingabewerte ist auch kein Problem:
def umfang_berechnen(breite,hoehe):
    ''' Berechnet den Umfang eines
    Rechtecks

    '''
    return 2 * hoehe + 2 * breite


beispiele = ["4 6","8 5"]
for wertepaar in beispiele:

    breite, hoehe = map(int,wertepaar.split(" "))
    print(umfang_berechnen(breite,hoehe))
Man könnte vielleicht eine Klasse Rechteck schreiben und um weitere Methoden ergänzen.

Queueing Theory (HP Codewars)

Die Lösung des Problems 15 „Queueing Theory“ von HP Codewars 2012 war nicht so kompliziert, sieht man von einigen Details ab. Problematisch vielleicht lediglich, dass eigentlich eine objektorientierte Umsetzung erwartet worden wäre:
''' HP codewars 2012 - problem 15
Queueing Theory, 9 points

Es hatte etwas gedauert sich wieder etwas in die Stringoperationen
hineinzufinden und die Queue aufzubauen. Ansonsten eher Tipparbeit.

'''

def data_verarbeiten(data):
    ''' Bekommt die Daten und soll sie verarbeiten und
    das Ergebnis als String zurueckgeben...

    '''

    # Variablen
    queue = [[] for i in range(9)]    # Liste zum Abarbeiten 
    queueLen = 0                      # Laenge der Queue
    string = ""                       # Nimmt das Ergebnis auf
    stringLen = 0                     # Laenge des Strings
    ablaufplan = []                   # Regelt die Entnahme aus den Schlangen

    # Variablen uebernehmen
    data = data.split("\n")
    stringLen, queueLen = map(int,data[0].split(" "))
    ablaufplan = [int(a[1]) - 1 for a in data[-1].split(" ")]

    # Einrichten der Queue
    string = " " * stringLen

    for zeile in range(1,queueLen+1):
        # Der range ist so gewaehlt, dass die erste Zeile (0)
        # mit den Metadaten und auch die letzte Zeile (queueLen+2)
        # mit dem Ablaufplan nicht geparst wird
        queue_id, position, content = data[zeile].split(" ")
        queue_id = int(queue_id[-1]) - 1
        queue[queue_id].append([position,content])

    # Wir arbeiten die queue ab
    for id in ablaufplan:
        # Ueber die id wird auf die jeweilige Zeile zugegriffen
        start, content = queue[id].pop(0)

        # Start und Ende festlegen
        start = int(start)
        ende = start + len(content)
            
        if start == 0:
            # z. B.
            # 0123456789
            # WORT
            #     456789
            string = content + string[ende:]
        else:
            # z. B.
            # 0123456789
            #    WORT
            # 012    789
            string = string[:start] + content + string[ende:]
            
    return string
    

data = """44 13
Q1 35 KNOWN
Q1 20 IMPORT
Q3 24 GRANT
Q1 4 IN
Q1 15 MADE
Q1 32 AN
Q2 39 LEDGE
Q2 5 NOTION
Q2 6 A
Q2 16 OR
Q3 0 IMAGE
Q3 12 IS
Q3 30 THIS
Q1 Q3 Q3 Q3 Q2 Q1 Q2 Q1 Q3 Q1 Q2 Q2 Q1"""

print(data_verarbeiten(data))
Zumindest wird das Problem so gelöst.

Dienstag, 5. Februar 2013

Return of Spell Binder

Für die Erledigung der Problemstellung 4 „Return of Spell Binder“ (HP codewars 2012) benötigte ich wenige Sekunden:
def reparieren(string):
    ''' Die Funktion repariert die von einem
    speelbot misshandelten Woerter

    word -> das zu reparierende Wort
    a    -> der zu tauschende Buchstabe
    b    -> der richtige Buchstabe
    
    '''
    word, a, b = string.split(" ")
    
    return word.replace(a,b)


for wort in ["MUSTARD M C","JUNK J TR","MONSTER ON A"]:
    print(wort,"-->",reparieren(wort))
Hier ist im Kern nur eine einfache Ersetzung erforderlich; trügt der Eindruck, den die Problembeschreibung macht, nicht, dann richtet sich diese Aufgabe eher an jüngere Semester. Immerhin gab es 4 Punkte für die Erledigung der Aufgabe.

X Liters of Ginger Soda

Eine relativ einfache, weil nicht aufwendige Aufgabe - lediglich soll Liter in Gallonen umgerechnet werden. Missverständlich vielleicht nur, dass der „nearest integer“ als Ergebnis verlangt wird - zumindest die Musterlösung legt ein Aufrunden nicht nahe und es macht ja wohl auch in diesem Zusammenhang keinen Sinn.
def umrechnen_liter_gallonen(liters):
    ''' Erledigt die Umrechnung.

    '''    
    return int(liters / 3.785)

liters = 144

print(umrechnen_liter_gallonen(liters))
Ob die Funktion für die Umrechnung berechtigt ist, darüber ließe sich wohl streiten.

Samstag, 2. Februar 2013

Indexseite aufbessern

Manchmal macht man sich etwas zu viel Arbeit. Die index-Seite fand ich zu umständlich, weil ich nicht direkt einzelne Buchstaben ansteuern konnte, sondern erst einmal scrollen musste. Ich habe mir überlegt die einzelnen Überschriften mit einem Anker zu versehen, um sie ansteuern zu können. SELFHTML hat hier geholfen, weil hier die projektinternen Anker vorgestellt werden.

Im Kern muss man eine Überschrift oder einen Text auf der Seite mit einem Anker der Form

<a name="NAME_DES_ANKERS">TEXT_ZUM_ANKER</a>

versehen, den man anschließend direkt ansteuern kann und zwar in der Form:

http://www...de/seite.html#NAME_DES_ANKERS

Ich habe jetzt für meine Indexseite einen Parser erstellt, der auf den Seiteninhalt in einer Textdatei zugreift und die Seite um die Anker ergänzt. Schöner wäre sicherlich, wenn das Skript direkt auf die Indexseite zugreifen und die nötigen Änderungen dort direkt vornehmen und speichern könnte.

Das Skript in der aktuellen Fassung:
liste = []
item = ""

with open("indexseite.txt") as f:

    for line in f:


        if item != "":
            line = item + line
            liste.append(line.replace("\n",""))
            item = ""
            
        elif line.startswith("<h2>"):
            item = line
            
        else:
            liste.append(line.replace("\n",""))


for item in liste:

    if item.startswith("<h2>"):
        ''' da soll ein Anker rein!
        http://de.selfhtml.org/html/verweise/projektintern.htm#anker
        z. B.

        <h2><a name="kapitel2">Kapitel 2</a></h2>

        also Element zwischen den h2-Tags ermitteln
        und daraus den Anker basteln...
        
        '''

        # <h2>Ziel</h2>
        ziel = item.rsplit("<")
        # ['', 'h2>A', '/h2>']
        ziel = ziel[1].split(">")
        # ['h2', 'A']
        ziel = ziel[1]
        # 'A'
        zeile = '<h2><a name="{0}">{0}</a></h2>\n'.format(ziel)
        
    else:
        zeile = item + "\n"

    with open("zieldatei.txt","a") as g:
            print(zeile)
            g.write(zeile)
Das Skript funktioniert und speichert in die zieldatei.txt die gewünschten Inhalte. Ein weiteres Skript erzeugt ein Inhaltsverzeichnis, das ich oben auf der Seite einfügen kann. Da bereits alle Buchstaben angelegt sind, muss ich nicht erst prüfen, ob die Buchstaben auf der Seite vorhanden sind.
import string


def inhaltsverzeichnis_erzeugen():
    ''' Die Links haben die Form
    http://pixewakb.blogspot.de/p/index.html#C

    '''

    abc = string.ascii_uppercase
    url = '{0}'
    
    for a in abc:
        
        print(url.format(a), end=" • " if not a == abc[-1] else "")


inhaltsverzeichnis_erzeugen()
Wünschenswert wäre noch ein Zurücklink bei jedem Anker, aber erst einmal läuft das so.

Nachtrag 2. Februar 2013


Ich habe gerade manuell einen Anker auf der Seite ergänzt und die Links in den Überschriften dahingehend angepasst, dass die Links jetzt auf diesen Seitenkopf-Anker verweisen. Anscheinend ändert blogger.com die Links der Anker auf die Blog-ID um, was zu Fehlern führt. Das Skript müsste das noch beachten...

Lambda, filter, reduce und map

Der Python-Kurs.eu bietet eine nette Übersichtsseite zu lambda, filter, reduce und map in Python.