Oh Tannenbaum, oh Tannenbaum...

Code-Stücke können hier veröffentlicht werden.
Antworten
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hallo zusammen,

inspiriert durch diesen Artikel habe ich mir zwei Möglichkeiten erarbeitet, wie man so einen Baum in Python erstellen kann. Ich beziehe mich auf die dritte Variante.

Ich will eine Funktion `xmastree` haben, der man einen beliebigen Text übergeben kann, und dieser dann in folgender Form ausgegeben wird:

Code: Alles auswählen

....|....
...t|t...
..st|ts..
.est|tse.
test|tset
....|....
Die erste und die letzte Zeile sind bei mir der Einfachheit halber identisch. Es wird also in jeder Zeile ein Teil des Textes ausgegeben, links und rechts beginnend mit dem letzten Zeichen. In jeder Zeile kommt ein Buchstabe mehr vom Text dazu, bis das Text in der vorletzten Zeile komplett vorhanden ist. Der Stamm wird durch das Zeichen "|" symbolisiert. Die Funktion soll einen zusätzlichen Parameter bekommen, der den Füll-Character¹ enthält.

Hier mal meine erste Variante mit Python Standardfunktionen:

Code: Alles auswählen

def itree_traditional(text, fill):
    space = fill * len(text)
    first = lambda : u"{}|{}".format(space, space)
    yield first()
    for index, _ in enumerate(text, 1):
        line = []
        for count, char in enumerate(text):
            if count < len(text)-index:
                line.append(fill)
            else:
                line.append(char)
        yield u"{}|{}".format("".join(line), "".join(reversed(line)))
    yield first()

def xmastree(text, fill="."):
    print u"\n".join(itree_traditional(text, fill))
Dann hab ich mal in den `itertools` gewühlt und bin auf folgendes gekommen:

Code: Alles auswählen

from itertools import islice, chain

def itree_islice(text, fill):
    space = fill * len(text)
    first = lambda : u"{}|{}".format(space, space)
    yield first()
    for index, _ in enumerate(text, 1):
        offset = len(text) - index
        left = "".join(chain(islice(space, offset), 
                             islice(text, offset, len(text))))
        yield "{}|{}".format(left, "".join(reversed(left)))
    yield first()

def xmastree(text, fill="."):
    print u"\n".join(itree_islice(text, fill))
Beide Funktionen ergeben folgendes Ergebnis:

Code: Alles auswählen

In [220]: xmastree("HappyChristmas", ".")
..............|..............
.............s|s.............
............as|sa............
...........mas|sam...........
..........tmas|samt..........
.........stmas|samts.........
........istmas|samtsi........
.......ristmas|samtsir.......
......hristmas|samtsirh......
.....Christmas|samtsirhC.....
....yChristmas|samtsirhCy....
...pyChristmas|samtsirhCyp...
..ppyChristmas|samtsirhCypp..
.appyChristmas|samtsirhCyppa.
HappyChristmas|samtsirhCyppaH
..............|..............
Wer hat noch etwas zu bieten? Egal ob pythonisch(er), kompakter oder spaßig? Oder evtl. in einer anderen Sprache?

Bin gespannt auf andere Lösungen :-)

¹ Wieso kann man in Code-Tags keine führenden Leerzeichen angeben? Diese werden in einigen Zeilen ignoriert :-(
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
0x1cedd1ce
User
Beiträge: 31
Registriert: Sonntag 3. Oktober 2010, 12:21

Code: Alles auswählen

def itree(text, fill, reverse=True):
    length = len(text)
    line = fill*length + '|' + fill*length
    yield line
    for i in range(length):
        if reverse:
            line = line[:length-i-1] + text[i] + line[length-i:length+i+1] + text[i] + line[length+i+1:2*length]
        else:
            line = line[:length-i-1] + text[-i-1] + line[length-i:length+i+1] + text[-i-1] + line[length+i+1:2*length]
        yield line
    yield fill*length + '|' + fill*length

def xmastree(text, fill='.', reverse=True):
    print('\n'.join(itree(text,fill,reverse)))
Man kann den Baum auch rückwärts ausgeben, dann steht die Spiegelschrift links und nicht rechts. Find ich schöner.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Code: Alles auswählen

def xmastree(string, fill='.'):
    def make_reversed_left_side(string, fill):
        empty = fill * len(string)
        yield empty
        for i in xrange(len(string)):
            yield fill * i + string[i:]
        yield empty
    left_side = list(reversed(list(make_reversed_left_side(string, fill))))
    right_side = map(lambda x: u''.join(reversed(x)), left_side)
    print u'\n'.join(map('{0}|{1}'.format, left_side, right_side))

if __name__ == '__main__':
    xmastree('HappyChristmas')
Das geht jetzt sicherlich noch wesentlich eleganter aber dafür bin ich zu faul.
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Code: Alles auswählen

def christmas_tree(string, fill="."):
    format = "{:%s^%d}" % (fill, len(string) * 2 + 1)
    return "\n".join(format.format(string[len(string)-i:]+'|'+"".join(reversed(string[len(string)-i:]))) for i in range(len(string)+1))
Die Zeile wird leider etwas lang und unübersichtlich, allerdings wollte ich es mit "".join() und einer List-Comprehension machen.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hab mal was zum Golfen geschrieben:

Code: Alles auswählen

for i in range(len(s),-1,-1):print s[i:].rjust(len(s),'.')+'|'+s[i:][::-1].ljust(len(s),'.')
Dummerweise fehlt die letzte Zeile. :lol:
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

Mit Spitze. ;)

Code: Alles auswählen

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def xmas_tree(message, fill='.'):
	def tree(message, padding):
		if message:
			tree(message[1:], padding)
			print('{0}|{1}'.format(message, message[::-1]).center(padding, fill))
		else:
			print('\\ /'.center(padding, fill))
			print('--O--'.center(padding, fill))
			print('/ \\'.center(padding, fill))
			print('|'.center(padding, fill))
	tree(message, len(message)*3)
	print('|||'.center(len(message)*3, fill))
	print('/|\\'.center(len(message)*3, fill))

def main():
	xmas_tree("Weihnachten")

if __name__ == '__main__':
	main()
Zuletzt geändert von nezzcarth am Donnerstag 22. Dezember 2011, 21:24, insgesamt 1-mal geändert.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

So, jetzt ist auch die letzte Zeile drin... :) (wie konnt ich meinen Freund Modulo nur übesehen ^^)

Code: Alles auswählen

for i in range(len(s),-2,-1):print s[i%(len(s)+1):].rjust(len(s),'.')+'|'+s[i%(len(s)+1):][::-1].ljust(len(s),'.')
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich unterbiete nochmal ein bißchen meine letzte Version:

Code: Alles auswählen

for i in range(len(s),-2,-1):print'{:.^{}}'.format(s[i%(len(s)+1):]+'|'+s[i%(len(s)+1):][::-1],len(s)*2+1)
(ab Python 2.7)

Und dann noch was mit GC und Semikolon:

Code: Alles auswählen

l=len(s);print'\n'.join('{:.^{}}'.format(s[i%(l+1):]+'|'+s[i%(l+1):][::-1],l*2+1)for i in range(l,-2,-1))
Zuletzt geändert von snafu am Donnerstag 22. Dezember 2011, 20:22, insgesamt 1-mal geändert.
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Glaube wir haben schonmal einen vorläufigen Gewinner :wink:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

webspider hat geschrieben:Glaube wir haben schonmal einen vorläufigen Gewinner :wink:
Zumindest fürs Golfen ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
0x1cedd1ce
User
Beiträge: 31
Registriert: Sonntag 3. Oktober 2010, 12:21

Code: Alles auswählen

for i in list(range(len(s)+1))+[0]:print('.'*(len(s)-i)+s[:i][i::-1]+'|'+s[:i]+'.'*(len(s)-i))
oder wenn die liste andersherum läuft

Code: Alles auswählen

for i in list(range(len(s),-1,-1))+[len(s)]:print('.'*i+s[i:][::-1]+'|'+s[i:]+'.'*i)
Edit: Leerzeichen und überflüssige Klammern entfernt
Zuletzt geändert von 0x1cedd1ce am Donnerstag 22. Dezember 2011, 21:27, insgesamt 2-mal geändert.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Aufbauend auf der letzten Lösung:

Code: Alles auswählen

for i in range(len(s),-1,-1)+[len(s)]:print'.'*i+s[i:]+'|'+s[i:][::-1]+'.'*i
0x1cedd1ce
User
Beiträge: 31
Registriert: Sonntag 3. Oktober 2010, 12:21

Der Baum in einer Liste

Code: Alles auswählen

['{0}{1}|{2}{0}'.format('.'*i,s[::-1],s) for i,s in [(i,s[i:]) for i in range(len(s),-1,-1)]+[(len(s),'')]]
Version 2 noch schöner

Code: Alles auswählen

['{0:.>{2}}|{1:.<{2}}'.format(p[::-1],p,len(s)) for p in [s[i:] for i in range(len(s),-1,-1)]+['']]
Antworten