Funktion ... eingeklammerte Teile als Sperrdruck wiedergeben

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.
Antworten
Sodenthaler
User
Beiträge: 4
Registriert: Freitag 21. Oktober 2016, 08:57

Hallo,

folgende Aufgabe bereitet mir seit Tagen Probleme.

Schreiben Sie eine Funktion hervorheben, die einen String zurückgibt, in dem alle eingeklammerten Teile eines übergebenen Springs durch Sperrdruck (ohne Klammern) hervorgehoben sind.

Ein (kleines) Beispiel, (ohne) Klammern!
Ein k_l_e_i_n_e_s Beispiel, o_h_n_e Klammern!

Lösungsansatz nicht vorhanden.
Ich weiss nicht wie ich nach der Klammern suchen soll.

Code: Alles auswählen

def hervorheben(s: str)->str:
    a='('
    if a in s:   
        print ('+' .join(a))
    print(s)
print(hervorheben('Ein (kleines) Beispiel, (ohne) Klammern!'))
Bitte um Lösungsansatz.
Vielen Dank.

Daniel :)
Zuletzt geändert von Anonymous am Freitag 21. Oktober 2016, 09:15, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
heiner88
User
Beiträge: 64
Registriert: Donnerstag 20. Oktober 2016, 07:29

Code: Alles auswählen

s1 = "Ein (kleines) Beispiel, (ohne) Klammern!"
s2 = ""
b  = False
for ch in s1:
    if ch == '(':
        ...
    elif ch == ')':
       ...
    ...

print(s1)
print(s2)
Zuletzt geändert von heiner88 am Freitag 21. Oktober 2016, 09:28, insgesamt 2-mal geändert.
BlackJack

@Sodenthaler: Der gezeigte Quelltext macht ja so gar keinen Sinn.

Wie würdest Du die Aufgabe denn von Hand lösen? Schreib das mal detailliert, in kleinen Schritten auf. Ausgangslage: Kästchenpapier mit dem Text „Ein (kleines) Beispiel, (ohne) Klammern!“ mit einem Buchstaben pro Kästchen in einer Zeile.

Was musst Du jetzt Schritt für Schritt tun um das Ergebnis in eine andere Zeile auf dem Blatt zu schreiben? Einfach Kästchen für Kästchen kopieren führt zwar in die Nähe des gewünschten Ergebnis, aber halt nicht ganz. Du musst ja bei jedem Kästchen entscheiden ob Du es kopierst oder nicht, und falls ja, ob Du nur das Kästchen kopierst, oder ob Du das Kästchen kopierst und das nächste leer lässt.

@heiner88: Dadurch das man die Hausaufgaben für andere löst, lernen die das nicht. ;-)

Edit: Trotzdem auch eine Lösung von mir:

Code: Alles auswählen

import re
from functools import partial


hervorheben = partial(re.sub, r'\((.*?)\)', lambda match: '_'.join(match.group(1)))


def main():
    print(hervorheben('Ein (kleines) Beispiel, (ohne) Klammern!'))


if __name__ == '__main__':
    main()
Sodenthaler
User
Beiträge: 4
Registriert: Freitag 21. Oktober 2016, 08:57

@ blackjack

Sowas was du benutzt haben wir nicht in der Schule druchgenommen.

...Quellcode macht keinen Sinn.
Ich habe halt die Prüfungsaufgabe. Hier soll ich die Funktion hervorheben schreiben und am Ende soll print(hervorheben('Ein (kleines) Beispiel, (ohne) Klammern!')) stehen.
Wie ich vorgehe würde:
def hervorheben(s: str)->str: #so fängt die Funktion immer an
a=0 # ich benötige ja einen Laufindex
und ab da hab ich schon die Probleme
ich muss jetzt den string durchsuchen bis ich auf eine Klammer komme
while a<len(s):
und das Wort in der Klammer will ich mit '_'.join() als Sperrdruck ausgeben.
Ich hab halt Probleme mit den Indexen.
Ich kann mir das im Kopf nicht vorstellen wie ich damit arbeiten soll.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sodenthaler: wenn Ihr gelernt habt, Typ-Annotationen zu machen, dann ... :evil:

Man kann die Aufgabe auf verschiedene Arten lösen, entweder mit Zustandsautomaten, wie heiner88, oder mit regulären Ausdrücken (was ja intern auch nur ein Zustandsautomat ist) wie BlackJack. Wenn Ihr das nicht durchgenommen habt, bleibt halt noch die umständliche Methode irgendetwas mit Indizes zu machen. Und da ist ja Dein Ansatz schon gar nicht mal so schlecht. Nur willst Du wieder nach dem ersten Schritt die restlichen auf einmal machen, wobei dann eben dieser zweite Schritt viel zu groß ist.

Daher erst einmal nur den ersten Schritt: also wie sieht ein Programm aus, das eine öffnende Klammer in einem String sucht und dessen Index ausgibt?
Sodenthaler
User
Beiträge: 4
Registriert: Freitag 21. Oktober 2016, 08:57

Hi ich komm echt nicht drauf.
Wir haben sowas noch nie durchgenommen: Suche nach einer Klammer.
Ich habe hier z.B. eine Aufgabe wo ich nach 3 gleich Buchstaben suchen soll. Das konnte ich lösen. Aber wie ich auf die Klammer komme kp.

#def highlight (s: str)->str:
# i=0

# while i<len(s):
# j=i+1
# while j<len(s) and s[j].lower()==s.lower():
# j+=1
# if j-i>=3:
# s=s[:i]+s[i:j].upper() + s[j:]
# i=j
# return s
#s = 'Aaah, eine suuuuper Werkstatttreppe!!!'
#print(s)
#print(highlight(s))

Ich komm da echt nicht weiter.

def hervorheben(s: str)->str:
i=1
while i<len(s):# durchsuche den string
for i in s:
if i=='(':



print(s)



print(hervorheben('Ein (kleines) Beispiel, (ohne) Klammern!'))
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Sodenthaler: wie sucht man nach ( ? Das ist doch deutlich einfacher, als nach gleichen Buchstaben zu suchen: Gehe die Indizes i von 0 bis Länge des Strings durch und wenn das Zeichen des Strings an der Stelle i eine öffnende Klammer ist, schreie "huhu!". Dazu mußt Du Dein Werkstattreppenbeispiel nur leicht modifizieren.
BlackJack

Drei Varianten in der Programmiersprache Io:
[codebox=io file=Unbenannt.txt]#!/usr/bin/env io

Regex

Sequence hervorhebenA := method(
"\\((.*?)\\)" asRegex matchesIn(self) \
replace(match, match at(1) asList join("_"))
)


Sequence hervorhebenB := method(
result := List clone
openBraceIndex := nil
self asList foreach(i, character,
if(openBraceIndex isNil,
if(character == "(",
openBraceIndex = i
,
result append(character)
)
,
if(character == ")",
do(
(i - openBraceIndex > 1) ifTrue(result removeLast)
openBraceIndex = nil
)
,
result append(character, "_")
)
)
)
result join
)


Sequence hervorhebenC := method(
result := Sequence clone
startIndex := 0
while(openIndex := self findSeq("(", startIndex),
result appendSeq(self exSlice(startIndex, openIndex))
closeIndex := self findSeq(")", openIndex)
if(closeIndex isNil,
startIndex = openIndex + 1
,
result appendSeq(
self exSlice(openIndex + 1, closeIndex) asList join("_")
)
startIndex = closeIndex + 1
)
)
result appendSeq(self exSlice(startIndex, self size))
)


main := method(
"Ein (kleines) Beispiel(), (ohne) Kla(mm)er(n)!" do(
List with("hervorhebenA", "hervorhebenB", "hervorhebenC") foreach(name,
getSlot(name) call println
)
)
)


isLaunchScript ifTrue(main)[/code]
heiner88
User
Beiträge: 64
Registriert: Donnerstag 20. Oktober 2016, 07:29

Die Aufgabe ist gar nicht so trivial bei den folgenden Fällen:

s = "Beispiel()" ==> "Beispiel" oder "Beispiel()"

s = ")Beispiel" ==> "Beispiel" oder ")Beispiel"

s = "(te(st)en)" ==> t_e_st_e_n oder "t_e_(st)_e_n"

usw.
heiner88
User
Beiträge: 64
Registriert: Donnerstag 20. Oktober 2016, 07:29

oder:

s = "(te(st)en)" ==> "t_e_st_e_n" oder "t_e_(st)_e_n" oder "t_e_(_s_t_)_e_n"
BlackJack

@heiner88: Stimmt, zu beschreiben wie man mit solchen Fällen umgeht, gehört zu einer Lösung dazu. Ich würde es mir einfach machen und verschachtelte Klammern als ungültige Eingabe ansehen und beschreiben, dass bei solchen Eingaben das Ergebnis undefiniert ist. :-)

Man könnte natürlich auch explizit darauf prüfen und das entsprechend als Fehler melden.
Sodenthaler
User
Beiträge: 4
Registriert: Freitag 21. Oktober 2016, 08:57

Ok danke für eure Hilfe.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ich hab mich mal an Erlang versucht, bin mir aber fast sicher, dass man das besser lösen kann:

[codebox=erlang file=Unbenannt.txt]-module(khigh).

-export([khigh/1]).


khigh(L) ->
khigh(L, 0).


khigh([H | Rest], Level) ->
if
H == $( -> khigh(Rest, Level+1);
H == $) -> khigh(Rest, max(Level-1, 0));
Level > 0 -> khigh_format(H, Rest) ++ khigh(Rest, Level);
true -> [H | khigh(Rest, Level)]
end;

khigh([], _Level) ->
[].


khigh_format(C, [H | _]) ->
if
H == $) -> [C];
H == $ -> [C];
C == $ -> [C];
true -> [C, $_]
end;

khigh_format(C, []) ->
C.
[/code]

Code: Alles auswählen

81> khigh:khigh(")123 (test) (foo (bar)) abc)").
"123 t_e_s_t f_o_o b_a_r abc"
the more they change the more they stay the same
BlackJack

Von Erlang's ”Pfeilsyntax” für Funktionen inspiriert habe ich meine drei Io-Varianten mal nach CoffeeScript portiert:
[codebox=coffeescript file=Unbenannt.coffee]#!/usr/bin/env coffee
'use strict'

String::sperrdruck = -> @split('').join('_')


String::hervorhebenA = ->
@replace /\((.*?)\)/g, (_, group) -> group.sperrdruck()


String::hervorhebenB = ->
result = []
openBraceIndex = null
for character, i in @
if openBraceIndex is null
if character == '(' then openBraceIndex = i else result.push character
else
if character == ')'
result.pop() if i - openBraceIndex > 1
openBraceIndex = null
else
result.push character, '_'
result.join ''


String::hervorhebenC = ->
result = []
startIndex = 0
until (openIndex = @indexOf('(', startIndex)) == -1
result.push @[startIndex...openIndex]
closeIndex = @indexOf ')', openIndex
if closeIndex == -1
startIndex = openIndex + 1
else
result.push @[openIndex + 1...closeIndex].sperrdruck()
startIndex = closeIndex + 1
result.push @[startIndex..]
result.join ''


main = ->
string = 'Ein (kleines) Beispiel(), (ohne) Kla(mm)er(n)!'
console.log string['hervorheben' + character]() for character in 'ABC'
null


main() if require.main == module[/code]
BlackJack

Wenn man das ganze nach FreeBASIC portiert sehen die Varianten B und C nicht so viel anders aus, aber es gibt so ein nostalgisches Gefühl, dass man das damals unter DOS in QBasic so hätte lösen können. Bei Variante A sieht man wie lang eine Lösung mit regulären Ausdrücken werden kann, wenn man keine moderne Sprache/Bibliothek verwendet, die das besser unterstützt.
[codebox=freebasic file=Unbenannt.txt]#include once "pcre.bi"


FUNCTION sperrdruck$(text AS STRING)
DIM result AS STRING, i AS INTEGER

result = ""
FOR i = 1 TO Len(text)
result = result + Mid$(text, i, 1)
IF i < Len(text) THEN result = result + "_"
NEXT
sperrdruck$ = result
END FUNCTION


FUNCTION hervorhebenA$(text AS STRING)
CONST cOvectorCount = 6, pattern = "\((.*?)\)"
DIM result AS STRING, re AS PCRE PTR, errorMessage AS ZSTRING PTR, _
errorOffset AS INTEGER, startIndex AS INTEGER, rc AS INTEGER, _
ovector(cOvectorCount - 1) AS INTEGER

re = PCRE_Compile(pattern, 0, @errorMessage, @errorOffset, NULL)
IF re = NULL THEN
PRINT "error compiling pattern: "; *errorMessage; " at "; errorOffset
PRINT pattern
PRINT Space(errorOffset); "^"
END
END IF

result = ""
startIndex = 0
GOTO exec_pcre
DO
result = result + _
Mid$(text, startIndex + 1, ovector(2) - startIndex - 1) + _
sperrdruck$(Mid$(text, ovector(2) + 1, ovector(3) - ovector(2)))
startIndex = ovector(1)
exec_pcre:
rc = PCRE_Exec(re, NULL, text, Len(text), startIndex, 0, @ovector(0), _
cOvectorCount)
LOOP WHILE rc > 0

PCRE_Free(re)

IF rc <> PCRE_ERROR_NOMATCH THEN
PRINT "matching error: "; rc
END
END IF
hervorhebenA$ = result + Mid$(text, startIndex + 1, Len(text))
END FUNCTION


FUNCTION hervorhebenB$(text AS STRING)
DIM result AS STRING, openIndex AS INTEGER, i AS INTEGER, ch AS STRING

result = ""
openIndex = -1
FOR i = 1 TO Len(text)
ch = Mid$(text, i, 1)
IF openIndex = -1 THEN
IF ch = "(" THEN openIndex = i ELSE result = result + ch
ELSE
IF ch = ")" THEN
IF i - openIndex > 1 THEN result = Left$(result, Len(result) - 1)
openIndex = -1
ELSE
result = result + ch + "_"
END IF
END IF
NEXT
hervorhebenB$ = result
END FUNCTION


FUNCTION hervorhebenC$(text AS STRING)
DIM startIndex AS INTEGER, openIndex AS INTEGER, closeIndex AS INTEGER, _
result AS STRING

result = ""
startIndex = 1
GOTO get_open_index
DO
result = result + Mid$(text, startIndex, openIndex - startIndex)
closeIndex = InStr(openIndex + 1, text, ")")
IF closeIndex = 0 THEN
startIndex = openIndex + 1
ELSE
result = result + sperrdruck$(Mid$(text, openIndex + 1, _
closeIndex - openIndex - 1))
startIndex = closeIndex + 1
END IF
get_open_index:
openIndex = InStr(startIndex, text, "(")
LOOP UNTIL openIndex = 0
hervorhebenC$ = result + Mid$(text, startIndex)
END FUNCTION


CONST text = "Ein (kleines) Beispiel(), (ohne) Kla(mm)er(n)!"
PRINT hervorhebenA$(text)
PRINT hervorhebenB$(text)
PRINT hervorhebenC$(text)[/code]
heiner88
User
Beiträge: 64
Registriert: Donnerstag 20. Oktober 2016, 07:29

Nur Aussenklammer löst Verhalten aus.
Alle inneren Klammern werden wie die anderen Zeichen behandelt.

Code: Alles auswählen

def klammer(str):
    k = 0
    s = ""
    for i, ch in enumerate(str):
        if ch == '(':
            k += 1
            if k > 1:
               s += "(_"
        elif ch == ')':
            if k > 1:
               s += ")_"
            if k == 1:
                s = s[:-1] if i > 0 and s[-1] == "_" else s
            k -= 1
            if k < 0:
                k = 0
        else:
            s += ch
            if k > 0:
               s += "_"
    return s

s1 = ")Ein (kleines) Beispiel(), (ohne) Kla(mm)er(n). ((aa)). ((aa(bb)cc)). (aa(bb(cc)dd)ee)."
print(s1)
s2 = klammer(s1)
print(s2)

Code: Alles auswählen

)Ein (kleines) Beispiel(), (ohne) Kla(mm)er(n). ((aa)). ((aa(bb)cc)). (aa(bb(cc)dd)ee).
Ein k_l_e_i_n_e_s Beispiel, o_h_n_e Klam_mern. (_a_a_). (_a_a_(_b_b_)_c_c_). a_a_(_b_b_(_c_c_)_d_d_)_e_e.
Antworten