Mississippi

Code-Stücke können hier veröffentlicht werden.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

In Haskell gibt es eine Funktion group, mit folgendem Effekt:
"Mississippi" => ['M', 'i', 'ss', 'i', 'ss', 'i', 'pp', 'i']
Habs mal in py nachgebaut. Vielleicht kanns jemand gebrauchen. Interessieren würde mich, ob man das auch mit einer Regexp schaffen kann. Habs versucht. Leider ohne Erfolg.

Code: Alles auswählen

def group(s):
    o = list()
    t = list(s[0])
    for c in s[1:]:
        if c == t[0]:
            t.append(c)
        else:
            o.append(''.join(t))
            t = list(c)
    return o + [''.join(t)]
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

Hi

Das kannst du auch mit itertools.groupby lösen:

Code: Alles auswählen

import itertools

s = "Mississippi"
print list(key*len(list(group)) for key,group in itertools.groupby(s))
Gruss

*edit* Gerolds Lösung ist definitiv schöner ... so weit hab ich wieder mal nicht gedacht.
Zuletzt geändert von rayo am Freitag 6. November 2009, 19:47, insgesamt 1-mal geändert.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo!

Ich mag solche Ein-/Zweizeiler eigentlich nicht, aber ausnahmsweise... :-)

Code: Alles auswählen

>>> import itertools
>>> [ "".join(value) for key, value in itertools.groupby("Mississippi") ]
['M', 'i', 'ss', 'i', 'ss', 'i', 'pp', 'i']
>>>

mfg
Gerold
:-)


Edit: Ohhh, zu spät. ;-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Hier eine Lösung mit ``itertools``, die nicht ganz so magisch ist:

Code: Alles auswählen

from itertools import tee, izip
def group2(s):
    a, b = tee(s)
    b.next()
    o = [s[0]]
    i = 0
    for a0, b1 in izip(a, b):
        if a0 == b1:
            o[i] += b1
        else:
            o.append(b1)
            i += 1
    return o
Geht aber bestimmt noch besser.

Edit: OK, geht deutlich besser ^^
Als LC find ich das am besten, das mit list und * ist das auch nicht so elegant.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Jup, das geht auch mit re

Code: Alles auswählen

>>> [m[0] for m in re.findall('((?P<char>.)(?P=char)*)','Mississippi')]
['M', 'i', 'ss', 'i', 'ss', 'i', 'pp', 'i']
Bottle: Micro Web Framework + Development Blog
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Ich habe noch einen... diesmal ganz ohne Magie. :-) Ziemlich ähnlich der Lösung von hendrikS.

Code: Alles auswählen

dest_list = []
prev_char = None
for char in "Mississippi":
    if char == prev_char:
        dest_list[-1] += char
    else:
        dest_list.append(char)
    prev_char = char
print dest_list
lg
Gerold
:-)

PS: @Defnull: Tolle Lösung! 8)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

wow. Jede menge Alternativlösungen.
Wenn ich gewußt hätte, daß es groupby gibt, hätte ichs vielleicht auch so gemacht.
Zur RegexpLösung. Erst habe ich gedacht, daß ist uneffizient. Beim zweiten Hinsehen finde ich es doch ziemlich smart.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Ähnlich wie Gerolds Lösung:

Code: Alles auswählen

def group(cs):
    def groups(a, b):
        if b in a[-1]:
            a[-1] += b
        else:
            a += b
        return a
    return reduce(groups, cs[1:], [cs[:1]])
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo!

Nur mal kurz darüber nachgedacht...

Wir amüsieren uns hier köstlich mit diesen Quellcode-Abschnitten! :D
Aber stellt euch mal vor, ihr zeigt diesen Thread euren Freunden/Eltern/Verwanden...
Was sind wir wohl in deren Augen? :mrgreen:

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

gerold hat geschrieben:Wir amüsieren uns hier köstlich mit diesen Quellcode-Abschnitten! :D
Aber stellt euch mal vor, ihr zeigt diesen Thread euren Freunden/Eltern/Verwanden...
Was sind wir wohl in deren Augen? :mrgreen:
So etwas KANN man nicht zeigen, wenn man es im "echten Leben" auch mit "normalen" Menschen zu tun hat. Ansonsten setzt man sich der Gefahr einer Zwangseinweisung aus ...
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Noch einer, diesmal lazy:

Code: Alles auswählen

def _group(s, *ss):
    for c in ss:
        if c in s:
            s += c
        else:
            yield s
            s = c
    yield s

def group(cs):
    if cs == '':
        return iter('')
    return _group(*cs)
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

numerix hat geschrieben:So etwas KANN man nicht zeigen, wenn man es im "echten Leben" auch mit "normalen" Menschen zu tun hat. Ansonsten setzt man sich der Gefahr einer Zwangseinweisung aus ...
Ich fand es immer schon ziemlich punkig, ein Nerd zu sein. :twisted:

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

pillmuncher hat geschrieben:Noch einer, diesmal lazy:

Code: Alles auswählen

def _group(s, *ss):
    ...
def group(cs):
    ...
    return _group(*cs)
Hallo!

Dieses Beispiel nehmen wir jetzt um Python-Anfängern die Übergabe von Parametern zu erklären. ;-)

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

gerold hat geschrieben:Wir amüsieren uns hier köstlich mit diesen Quellcode-Abschnitten! :D
Aber stellt euch mal vor, ihr zeigt diesen Thread euren Freunden/Eltern/Verwanden...
Was sind wir wohl in deren Augen? :mrgreen:
Wenn wir schon blödeln, dann steuere ich eine Scheme-Lösung bei. Wäre gespannt was man mit Factor zaubern könnte :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Hallo!

Weiß jemand, wie das in Cython http://www.cython.org/ aussehen könnte? Ich interessiere mich dafür, da ich vielleicht demnächst ein paar Codeteile (nicht zwischenspeicherbare Rabattberechnungen) meines Onlineshops hoch optimieren muss.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

gerold hat geschrieben: Was sind wir wohl in deren Augen? :mrgreen:
Bestimmt nicht so schlimm wie Du denkst. Jeder hat so seinen Spleen.

Scheme:
Die vielen Klammern haben mich immer davon abgehalten das mal zu probieren.

Und nicht zuletzt:
Gerolds nonmagic Version ist die effizienteste der Varianten.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Leonidas hat geschrieben:Wenn wir schon blödeln, dann steuere ich eine Scheme-Lösung bei. Wäre gespannt was man mit Factor zaubern könnte :)
Factor kann ich nicht, aber Prolog:

Code: Alles auswählen

group(String, Groups) :-
    string_to_list(String, [C|Cs]),
    group(Cs, [C], Groups).

group([C|Cs], [C|Group], Groups) :-
    !,
    group(Cs, [C,C|Group], Groups).
group([C|Cs], Group, [String|Groups]) :-
    group(Cs, [C], Groups),
    string_to_list(String, Group).
group([], Group, [String]) :-
    string_to_list(String, Group).

Code: Alles auswählen

?- group("mississippi",G).
G = ["m", "i", "ss", "i", "ss", "i", "pp", "i"].
Da sieht man auch, wo ich das def _group(s, *ss): herhab ;-)
In specifications, Murphy's Law supersedes Ohm's.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Hab meine Lösung nochmal überarbeitet^^

Code: Alles auswählen

from itertools import tee, izip

def group(s):
    a, b = tee(s)
    output = list()
    output.append(b.next())
    for prev_char, char in izip(a, b):
        if prev_char == char:
            output[-1] += char
        else:
            output.append(char)
    return output
Prolog weckt düstere Erinnerungen... Konnte das noch nie leiden ;)
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

ice2k3 hat geschrieben:

Code: Alles auswählen

    a, b = tee(s)
    output = list()
    output.append(b.next())
Das b.next() ist eine gute Idee:

Code: Alles auswählen

def group(cs):
    cs = iter(cs)
    s = cs.next()
    for c in cs:
        if c in s:
            s += c
        else:
            yield s
            s = c
    yield s
ice2k3 hat geschrieben:Prolog weckt düstere Erinnerungen... Konnte das noch nie leiden ;)
Juhuu! Ein Sprachenkrieg ;) Ich mochte Prolog schon immer, hatte auch nie irgendwelche Verständnis-Probleme (anders als bei Haskell :roll: ). Irgendwie scheint es der Verdrahtung meines Gehirns zu entsprechen. Und von Differenzlisten hab ich schon geträumt:

Code: Alles auswählen

?- asserta(append_dl(A - B, B - C, A - C)).
true.

?- append_dl([1,2,3|X] - X, [4,5,6|Y] - Y, Z - []).
X = [4, 5, 6],
Y = [],
Z = [1, 2, 3, 4, 5, 6] .
Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

Fehlt nicht noch was rekursives?

Code: Alles auswählen

def group(s, res=[], i=0, j=1):
    if i >= len(s)-1:
        return res + [s[i]*j]
    if s[i] == s[i+1]:
        return group(s, res, i+1, j+1)
    else:
        return group(s, res + [s[i]*j], i+1)
Das würde ich zwar nicht als elegant bezeichnen aber darum poste ich's weil mir gerade kein guter rekursiver Weg einfällt und irgendjemand hier soll ihn mir offenbaren :)
(Ist zwar fast schon peinlich, aber ich bin hier ja anonym :p)
Antworten