Sonntag, 30. Dezember 2012

Erste objektorientierte Gehversuche

Die Aufgabe bei Programmieren.ch verlangt, dass ein Skript geschrieben wird, das 2 Brüche addieren kann. Unter Rückgriff auf den Wikipedia-Artikel „Bruchrechnung schien es mir recht einfach die nötige Funktion zu schreiben:
class Bruch(object):
    ''' Eine Bruch-Klasse, die einen Bruch darstellt
    '''
    
    def __init__(self, zaehler, nenner):
        self.zaehler = zaehler
        self.nenner = nenner

    def __add__(self, bruch):
        # Ueberlaedt den +-Operator
        self.zaehler = self.zaehler * bruch.nenner + bruch.zaehler * self.nenner
        self.nenner *= bruch.nenner
        
        return Bruch(self.zaehler, self.nenner) 
Mit dem Python-Modul fractions war die Aufgabe allerdings einfach zu lösen - danke nochmals für den Hinweis von +Marc Rintsch - und ich muss mir mal was anderes suchen, um daran Objektorientierung zu lernen. Die Lösung mit Python nun:
from fractions import Fraction
b1 = Fraction(2,3)
b2 = Fraction(1,3)
print(b1 + b2)
Python bringt die Batterien mit.

Eisenbahn optimieren

Die Programmieraufgabe „Eisenbahn optimieren“ von Programmieraufgaben.ch finde ich ganz spannend.

Im Kern ließe sich hier wohl der Dijkstra-Algorithmus (Graphentheorie) zur Anwendung bringen, wenn auch diese Lösung überdimensioniert sein könnte. Ich habe bei Wikibooks eine ganz brauchbar erscheinende Sammlung von Algorithmen gefunden, die von pberndt betreut wird.


Samstag, 29. Dezember 2012

Teilbarkeit

Manchmal ist es sinnvoll alle Teiler einer Zahl zu ermitteln, etwa um sich an dieser Aufgabe zu versuchen. Ein ganz erster Versuch, eine Funktion zu schreiben, die alle Teiler einer Zahl liefert, ist:
def teiler_ermitteln(zahl):
    ''' Soll alle Teiler einer ganzen Zahl ermitteln
    und als Liste zurueckgeben.
    
    '''
    liste = []
    liste.extend([1,zahl])
    
    ende = zahl
    i = 1
    
    while i < ende:
        
        i += 1

        if i == ende:
            break
        
        if (zahl / i) % 1 == 0.0:
            
            liste.append(i)
            
            if int(zahl/i) != i:
                liste.append(int(zahl/i))
                
            ende = int(zahl/i)

    return liste 


ergebnis = teiler_ermitteln(72)

ergebnis.sort()

print(ergebnis)
Das Skript arbeitet so nur für natürliche Zahlen größer 0. Da aber a \mid b gilt, so gilt auch -a \mid b und a \mid -bMan kann sich also bei der Untersuchung des Teilbarkeitsbegriffs auf natürliche Zahlen beschränken.

Um die Programmieraufgabe allerdings zu lösen, reicht diese Version vollkommen aus:
def teiler_ermitteln(zahl):
    ''' Soll alle Teiler einer ganzen Zahl ermitteln
    und als Liste zurueckgeben.
     
    '''
    liste = []
    liste.extend([1,zahl])
     
    ende = zahl
    i = 1
     
    while i < ende:
         
        i += 1
 
        if i == ende:
            break
         
        if (zahl / i) % 1 == 0.0:
             
            liste.append(i)
             
            if int(zahl/i) != i:
                liste.append(int(zahl/i))
                 
            ende = int(zahl/i)
            
    liste.sort()
    return liste 
 

for i in range(1,10000):

    teiler = teiler_ermitteln(i)
    teiler.pop()
    summe = sum(teiler)
    
    if summe > i and i % 2 != 0:
        print("{} ist abundant.".format(i))
    elif summe == i:
        print("{} ist vollkommen.".format(i))
Ich denke allerdings, dass in der eigentlichen Funktion noch deutliches Optimierungspotential steckt.

Eine Spielerei mit einer Liste

Bei dieser Aufgabe auf Programmieren.ch geht es diesmal darum in einem ersten Schritt eine neue Liste für alle die Werte zu erzeugen, die größer als 10 sind und dann in einem zweiten Schritt das Produkt aller Zahlen im Array auszugeben.
liste = [2, 17, 10, 9, 16, 3, 9, 16, 5, 1, 17, 14]
print(sum(liste))
print(eval(" * ".join([str(i) for i in liste])))

print()

liste2 = [i for i in liste if i > 10]
print(sum(liste2))
print(eval(" * ".join([str(i) for i in liste2])))
Von den weiteren Python-Lösungen bei der Aufgabe halte ich nicht viel. Das kann man mit list comprehensions und eval() sehr elegant formulieren.

Harshad- bzw. Niven-Zahlen

Es gibt hier auf Programmieraufgaben.ch eine Aufgabe zu Harshad- oder auch Niven-Zahlen. das sind natürliche Zahlen, die durch ihre Quersumme, „das heißt die Summe ihrer Ziffern (im Dezimalsystem), teilbar sind“ (Quelle). Hierbei sollen für alle natürlichen Zahlen bis n getestet werden, ob es sich um eine Harshad-Zahl handelt.
def harshad_zahl_testen(i):
    ''' Testet die natuerliche Zahl dahingehend,
    ob es sich um eine Harshad-Zahl handelt. Das ist dann
    der Fall, wenn die Zahl natuerlich und durch
    ihre Quersumme teilbar ist.
    '''
    if i != 0 and i % 1 == 0 and i % sum([int(a) for a in str(i)]) == 0:
        return True
    else:
        return False


def main():
    # Mainschleife
    for i in range(0,1000):
        if harshad_zahl_testen(i) == True:
            print(i,end=", ")


if __name__ == "__main__":
    main()
Das Skript scheint zu funktionieren.

Das erste Problem

Die Aufgabenstellung zum ersten Problem bei Projekt Euler lautet, dass die Summe aller natürlichen Zahlen < 1000 gefunden werden soll, die ein Vielfaches von 3 oder 5 ist. Das Problem habe ich bereits vor einiger Zeit gelöst und kann inzwischen auch eine einzeilige Lösung formulieren:
print(sum([i for i in range(1000) if i % 3 == 0 or i % 5 == 0]))
Da gibt es noch ganz viele - sehr schöne - Probleme, die gelöst werden wollen.

Caesar-Verschlüsselung

Zum Zeitvertreib habe ich gerade einmal die Caesar-Verschlüsselung implementiert. Im Python-Forum gibt es dazu einen eigenen Thread und eine Reihe sehr interessanter Skripte und Ansätze. An sich eine einfache Geschichte:
import string


def verschluesseln(text,verschiebung):
    ''' Verschluesselt nach der 'Caesar-Verschiebung'
    http://de.wikipedia.org/wiki/Caesar-Verschlüsselung
    
    '''
    abc = string.ascii_lowercase
    geheim = []
    
    for a in text.lower():
        if a in abc:
            letterIndex = (abc.index(a) + verschiebung) % 26
            geheim.append(abc[letterIndex])
        else:
            geheim.append(a)
    
    return "".join(geheim)


def entschluesseln(text,verschiebung):
    ''' Soll den verschluesselten Text und die
    urspruenglische Verschiebung erhalten. Gibt dann
    den entschluesselten Text zurueck.
    '''
    return verschluesseln(text,-1 * verschiebung)



text = "Das ist ein Text, der das Verfahren verdeutlichen soll."

whaw = verschluesseln(text,3)
print(whaw)

print(entschluesseln(whaw,3))
Spannend ist nun eigentlich an dieser Sache, ob man den Quelltext des eigentlichen Skripts noch reduziert bekommt. Augenblicklich benötige ich 9 Codezeilen und frage mich, ob es noch deutlich kürzer auszudrücken geht bei gleichzeitiger Lesbarkeit.

Solving Every Sudoku Puzzle

Ich habe mir inzwischen schon einige Male den Artikel "Solving Every Sudoku Puzzle" von Peter Norvig angesehen, um jetzt festzustellen, wer das eigentlich ist. Ganz verstehe ich die Lösungsstrategie noch nicht, aber ich habe ja noch Zeit mir den Lösungsansatz einmal anzusehen.

Als ich mich daran einmal versuchte, war allein der Parser für das Sudoku und die Repräsentation eines jeden Rätsels im Programm sehr aufwendig gecodet. Gefühlt ist sein Ansatz sehr viel einfacher...

Freitag, 28. Dezember 2012

Hallo Welt

Hallo Welt :D
print("Hallo Welt :D")
Gerade habe ich mir die Syntaxhervorhebung für meinen Blog aktiviert. Es handelt sich um SyntaxHighlighter von Alex Gorbatchev. In der HTML-Ansicht kann der SyntaxHighlighter genutzt werden, indem

<pre class="brush:py">
...
</pre>

eingefügt werden und der Quelltext zwischen diesen Tags platziert wird.

Unschön ist, dass keine Buttons hinzugefügt werden, über die man - wie bei Wordpress - den Quellcode direkt in die Zwischenablage kopieren oder drucken kann.

Ich bin nach einem Blogger-Blog über einen Wordpress-Blog nun zu Blogger zurückgekehrt, weil ich das Bloggen hier einfacher finde. Gefühlt ist die Software schneller und wirkt so auf mich robuster.