Buchstaben eines Wortes

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Sandra
User
Beiträge: 11
Registriert: Dienstag 30. September 2008, 12:44

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
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ist sogar ganz einfach ;)

Das Zauberwort heisst Membership ;)

Code: Alles auswählen

"o" in "hello"
"x" in "hello"
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.
Zuletzt geändert von cofi am Donnerstag 2. Oktober 2008, 23:56, insgesamt 1-mal geändert.
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([])
sea-live
User
Beiträge: 440
Registriert: Montag 18. Februar 2008, 12:24
Wohnort: RP

@ 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 !
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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 ;-)
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Ü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:

Code: Alles auswählen

return all(condition(obj) for obj in seq)
Stefan
lunar

Was BlackJack ja auch getan hat ...
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
Sandra
User
Beiträge: 11
Registriert: Dienstag 30. September 2008, 12:44

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
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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]
abgdf

@BlackJack: :shock: Wow, Du kommst sogar mit Assembler klar :respekt: ...
Sandra
User
Beiträge: 11
Registriert: Dienstag 30. September 2008, 12:44

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)

Code: Alles auswählen

>>> (c in "tes" for c in "test")
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
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.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Und noch Haskell. :-)

Code: Alles auswählen

charsInString :: String -> String -> Bool
charsInString cs ss = all ((flip elem) ss) cs
sea-live
User
Beiträge: 440
Registriert: Montag 18. Februar 2008, 12:24
Wohnort: RP

Die letzten Antworten dürften einen neuling mit 10 post's etwas überfordern
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 ;)
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

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
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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 :D

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 :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Sandra
User
Beiträge: 11
Registriert: Dienstag 30. September 2008, 12:44

Vielen Dank!

Es sollte dann auch

Code: Alles auswählen

 f = all . flip elem
genügen ;)

mfg Sandra, die Haskell Expertin :lol:
Antworten