Seite 1 von 2
Buchstaben eines Wortes
Verfasst: Donnerstag 2. Oktober 2008, 23:31
von Sandra
Hi,
Es gilt eine Funktion zu schreiben, welche überprüft, ob ein Wort aus gewissen Buchstaben besteht...
Dies funktioniert auch schon ganz gut:
Code: Alles auswählen
def f(xs):
b = True
for x in xs:
b = b and x=="t" or x=="e" or x=="s"
print xs, b
f("Hallo")
f("Test")
Doch wie kann ich auf an die Funktion übergebene Buchstaben überprüfen, also ohne diese bereits Fix im Code fest zu legen?
Ich hoffe ihr habt ein paar Tipps
mfg Sandra
Verfasst: Donnerstag 2. Oktober 2008, 23:56
von cofi
Ist sogar ganz einfach
Das Zauberwort heisst Membership
Gib das mal in den Interpreter ein, dann kommt dir schon eine Lösung
Ein Tipp am Rande: Benutze doch sprechende Variablennamen. Die tun nicht weh und machen den Code verständlicher, für andere aber auch für dich.
Verfasst: Donnerstag 2. Oktober 2008, 23:56
von BlackJack
Hm, ist ziemlich schwer Tipps zu geben ohne direkt eine Lösung zu verraten, weil's eigentlich ziemlich einfach ist. Wenn Du's "konventionell" lösen willst, dann musst Du Dir einfach mal überlegen wie Du in der Schleife `x` nacheinander auf mehrere als Sequenz übergebene Buchstaben prüfst. Also "*Für* jeden Buchstaben auf den getestet werden soll, mache folgenden Test" auf English und dann in Quelltext übersetzen, sollte eigentlich recht einfach sein.
Ansonsten hier zwei Einzeiler als Ideen:
Code: Alles auswählen
In [145]: all(c in 'tes' for c in 'hallo')
Out[145]: False
In [146]: all(c in 'tes' for c in 'test')
Out[146]: True
In [147]: set('hallo') - set('tes')
Out[147]: set(['a', 'h', 'l', 'o'])
In [148]: set('test') - set('tes')
Out[148]: set([])
Verfasst: Freitag 3. Oktober 2008, 07:58
von sea-live
@ BlackJack
ich frag mich immer warum die Lehrer auf konventionelle lösungen beharren und dann zu Sprachen wie Python wechseln die dafür simple Lösungungen haben !
mein Prof früher Java ganz früher C++ ist auch auf der schiene !
Verfasst: Freitag 3. Oktober 2008, 10:39
von Hyperion
sea-live hat geschrieben:@ BlackJack
ich frag mich immer warum die Lehrer auf konventionelle lösungen beharren und dann zu Sprachen wie Python wechseln die dafür simple Lösungungen haben !
mein Prof früher Java ganz früher C++ ist auch auf der schiene !
Naja, vermutlich soll das Konzept von Schleifen verdeutlicht werden. Man kann halt nicht bei jedem Beispiel überlegen, ob man es in Sprache xyz irgend wie eleganter und besser hinbekommen kann - oder aber der Aufgabensteller weiß es gar nicht
Verfasst: Freitag 3. Oktober 2008, 10:54
von sma
Übrigens, das Sprachmuster
Code: Alles auswählen
b = True
for obj in seq:
b = b and condition(obj)
return b
kann man in Python mit der eingebauten Funktion all() und einem Generatorausdruck kürzer darstellen:
Stefan
Verfasst: Freitag 3. Oktober 2008, 11:39
von lunar
Was BlackJack ja auch getan hat ...
Verfasst: Freitag 3. Oktober 2008, 11:45
von BlackJack
@sea-live: Wahrscheinlich weil man bei ``my_list.sort()`` nicht lernt wie man einen Sortieralgorithmus selber entwerfen und implementieren kann.
In diesem Fall würde man bei Verzicht auf `all()` und ``in`` zum Beispiel die Komplexität der Lösung deutlicher sehen, weil man sich Gedanken macht, wie diese beiden Konstrukte intern implementiert sind.
In diesem Sinne hier eine Lösung die zeigt, was der Prozessor "wirklich" macht:
Code: Alles auswählen
SYS_EXIT equ 1
SYS_WRITE equ 4
STDOUT equ 1
section .data
wrong_number_of_args:
db "wrong number of arguments", 10
wrong_number_of_args_len equ $ - wrong_number_of_args
true:
db "True", 10
true_len equ $ - true
false:
db "False", 10
false_len equ $ - false
section .text
global _start
_start:
cmp [esp], dword 3
je .correct_number_of_arguments
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, wrong_number_of_args
mov edx, wrong_number_of_args_len
int 0x80
mov ebx, 1
jmp short exit
.correct_number_of_arguments:
mov esi, [esp+8]
mov ebx, [esp+12]
.outer
lodsb
or al, al
jz .print_true
xor ecx, ecx
.inner
mov dl, [ebx+ecx]
or dl, dl
jz .print_false
cmp al, dl
je .outer
inc ecx
jmp short .inner
.print_true
mov ecx, true
mov edx, true_len
jmp short .print
.print_false
mov ecx, false
mov edx, false_len
.print
mov eax, SYS_WRITE
mov ebx, STDOUT
int 0x80
xor ebx, ebx
exit:
mov eax, SYS_EXIT
int 0x80
Testlauf:
Code: Alles auswählen
bj@s8n:~$ nasm -f elf test2.asm && ld test2.o
bj@s8n:~$ ./a.out
wrong number of arguments
bj@s8n:~$ ./a.out test tes
True
bj@s8n:~$ ./a.out hallo tes
False
Verfasst: Freitag 3. Oktober 2008, 14:45
von Sandra
Ok, vielen Dank...
Sieht nun wie Folgt aus:
Code: Alles auswählen
def f(string, chars):
print string, all(c in chars for c in string)
chs = "tes"
f("Hallo", chs)
f("Test", chs)
Doch wieso erhalte ich nun:
Hallo False
Test False
Kann dies an
T und
t liegen, falls ja, wie kann man ersteres in zweiteres umwandeln?
mfg Sandra
Verfasst: Freitag 3. Oktober 2008, 14:48
von Hyperion
Versuche doch mal zunächst die List-Comprehension zu kapieren. Danach siehst Du bestimmt klarer.
Code: Alles auswählen
>>> [c in "tes" for c in "test"]
[True, True, True, True]
>>> [c in "tes" for c in "tost"]
[True, False, True, True]
Verfasst: Freitag 3. Oktober 2008, 19:05
von abgdf
@BlackJack:
Wow, Du kommst sogar mit Assembler klar :respekt: ...
Verfasst: Samstag 4. Oktober 2008, 16:36
von Sandra
So funktioniert es nun Problemlos:
Code: Alles auswählen
def f(string, chars):
print string, all(c in chars.lower() for c in string.lower())
Die Vermutung scheint also nicht ganz falsch gewesen zu sein...
Doch was bewirken die runden Klammern (ich dachte, diese währen für Funktionsaufrufe dar)
bei der Eingabe?
Damit erhält man die Ausgabe
generator object, ohne Klammern (wie oben) funktioniert es nicht (oder sind diese dort quasi doppelt belegt, für
all und für
for) - es lässt sich allerdings auch
all([c in "tes" for c in "test"]) mit eckigen klammern angeben.
mfg Sandra
Verfasst: Samstag 4. Oktober 2008, 16:49
von BlackJack
Runde Klammern hinter einem Namen sind für den Aufruf des Objekts. Runde Klammern um etwas der Form `expr for item in iterable` erzeugen einen Generatorausdruck. Also im Grunde das gleiche wie eine "list comprehension", nur dass keine Liste erzeugt wird, sondern man einen `generator` bekommt, der erst auf verlangen die einzelnen Elemente berechnet.
Wenn um einen Generatorausdruck sowieso schon runde Klammern stehen, zum Beispiel bei einem Aufruf, dann darf man ein Paar runde Klammern weg lassen.
Generatorausdruck am Beispiel:
Code: Alles auswählen
In [216]: a = [c in 'ao' for c in 'hallo']
In [217]: a
Out[217]: [False, True, False, False, True]
In [218]: a = (c in 'ao' for c in 'hallo')
In [219]: a
Out[219]: <generator object at 0x856294c>
In [220]: a.next()
Out[220]: False
In [221]: a.next()
Out[221]: True
In [222]: a.next()
Out[222]: False
In [223]: a.next()
Out[223]: False
In [224]: a.next()
Out[224]: True
In [225]: a.next()
---------------------------------------------------------------------------
<type 'exceptions.StopIteration'> Traceback (most recent call last)
/home/bj/<ipython console> in <module>()
<type 'exceptions.StopIteration'>:
Vorteil ist neben dem sparen der eckigen Klammern, dass `all()` sofort mit dem iterieren abbricht, wenn das erste `False` auftritt, also weniger berechnet werden muss als beim Aufruf mit einer "list comprehension" die ja vorher schon den Test für alle Buchstaben gemacht hat.
Verfasst: Sonntag 5. Oktober 2008, 11:24
von Leonidas
Verfasst: Sonntag 5. Oktober 2008, 12:00
von BlackJack
Und noch Haskell.
Code: Alles auswählen
charsInString :: String -> String -> Bool
charsInString cs ss = all ((flip elem) ss) cs
Verfasst: Sonntag 5. Oktober 2008, 18:26
von sea-live
Die letzten Antworten dürften einen neuling mit 10 post's etwas überfordern
Verfasst: Sonntag 5. Oktober 2008, 18:31
von lunar
Ja und? Er muss sie ja nicht lesen.
Auch hat das nichts mit "Neuling" oder der Anzahl der Posts zu tun, sondern einfach nur damit, ob man Haskell oder Scheme kann. Ich habe ein bisschen mehr als 10 Posts, die Haskell-Lösung erschließt sich mir trotzdem nicht, weil ich nun mal keine Ahnung von Haskell habe
Verfasst: Sonntag 5. Oktober 2008, 19:06
von audax
You is not object? Haha!
Code: Alles auswählen
def all_in_string(a, b)
b.split('').each{|c|
if not a.include? c
return false
end }
true
end
puts all_in_string("Foobar", "arb")
Irgendwas sagt mit, dass das zu umständlich ist Oo
Verfasst: Sonntag 5. Oktober 2008, 20:42
von Leonidas
lunar hat geschrieben:Ich habe ein bisschen mehr als 10 Posts, die Haskell-Lösung erschließt sich mir trotzdem nicht, weil ich nun mal keine Ahnung von Haskell habe
Ja, das geht den meisten so, mich eingeschlossen. Die Haskell-Kundigen sind auch in dem aktiven Kern in der Minderzahl. Aber der Fairness halber muss ich sagen, dass ich die Assembler-Lösung auch nicht verstehe, da ich schlichtweg kein Assembler kann
sea-life, einige Leute haben einfach Spaß am programmieren und führen gerne auch alternative Lösungen vor. Ich finde solche Threads immer toll, weil man dann sieht, wie man auf andere Weise an das Problem herangehen kann. Lustig ist es auch, wenn auf eine Python-Hausaufgabe dann Lösungen in Self, Io etc. gepostet werden. Liegt aber vielleicht auch an meiner Art von Humor
Verfasst: Sonntag 5. Oktober 2008, 23:27
von Sandra
Vielen Dank!
Es sollte dann auch
genügen
mfg Sandra, die Haskell Expertin