Göm meny
Gäller för: VT21

Laboration 7: Rättstavning

I laboration 7 kommer ni att skriva ett objektorienterat program från grunden samt beskriva dess struktur med hjälp av klassdiagram. Instruktionerna kommer endast beskriva de krav som ställs på programmet. Hur ni löser dessa krav är upp till er.

Redovisning och kompletteringar

  • Information om den muntliga redovisningen, samt eventuella kompletteringar kan ni läsa om sidan Redovisning.

Checklista att gå igenom vid redovisning

Vid redovisning ska ni gå igenom nedanstående checklista för den assistent ni redovisar för.

Ni ska även visa och skicka in UML-diagram för er implementation.

  1. Visa att ni kan köra ert program:
    • Demonstrera att det går att använda med olika ordfrekvensdata-filer och att ni kan kontrollera olika texter.
    • Peka ut och visa att alla krav på utskrifter och innehåll i rapporterna finns med.
  2. Visa att pycodestyle och pydocstyle inte ger några anmärkningar.
  3. Visa UML-diagrammet för ert program och redogör kortfattat för vilka roller era olika klasser har, samt hur/när instanser av de olika klasserna skapas.
  4. Den assistent som ni redovisar för kommer att be er redogöra för en eller fler av följande moment i ert program:
    • Översiktlig genomgång inläsning av ordfrekvensdata
    • Översiktlig genomgång av flöde vid utskrift av rapport - vilka instanser är inblandade
    • Hur upptäcks ett okänt ord, vilka instanser är inblandade i den processen?
    • Hur plockas förslag på “rättstavade” ord fram?
  5. Vad tar/tog lång tid i er kod? Varför? Har ni lyckats få det att gå snabbare? Eller om inget tar lång tid, vad skulle kunna tänkas ta lång tid ett program som detta?

Krav för godkänd kod

  • Koden ska följa PEP 8.
  • Moduler (själva filen), funktioner, klasser och metoder ska kommenteras enligt PEP 257.
  • Koden ska följa koddispositionen nedan.
  • Koden ska utföra uppgifterna enligt respektive uppgiftsbeskrivning.
  • Koden ska vara uppdelad i olika filer enligt instruktionerna för respektive uppgift.

För hjälp med kontroll av PEP, se PEP 8 och PEP 257.

Krav på koddisposition

För att göra det lättare att hitta i koden är det bör den följa en genomtänkt koddisposition. Nedan är en vanlig disposition som används i många språk.

  1. Alla import-satser placeras högst upp i filen
  2. Eventuella globala konstanter
  3. Funktionsdefinitioner
  4. Kod utanför funktioner, t.ex. anrop till en main()-funktion.

Krav på kommentarer och namngivning av funktioner och variabler

  • Alla satser som består av fler än en rad ska ha en tillhörande kommentar. Dvs if-satser, loopar, funktioner och metoder. Kommentaren ska inte vara en “innantilläsning” av koden den hör till. Använd rätt kommentarsmarkering (t.ex. """ för dokumentationssträngar, # för kommentarer i löpande kod, se PEP 8 och PEP 257).
  • Funktioner och variabler ska vara döpta på ett bra sätt, dvs att de är beskrivande och reflekterar innehåll/funktion. Låt funktionsnamn vara verb och variabelnamn vara substantiv. Undvik namn på enbart en bokstav (var beredda att kunna motivera varför ni valt just det namnet).

Här är icke-godkänd kod:

v = 0
q = 0
u = [19, 21, 24, 20]

# för alla element t i u, lägg till t till v
for t in u:
    v += t
q = v/len(u)

Här är en godkänd variant

sum_age = 0
avg_age = 0
ages = [19, 21, 24, 20]

# räkna ut summan av alla åldrar
for age in ages:
    sum_age += age
avg_age = sum_age/len(ages)

Försök att tänka på

  • Minimera användningen av hårdkodade siffror, (s.k. magic numbers). Använd istället variabler med förklarande namn.
  • Dela upp er kod i delfunktioner/delmetoder vid behov:
    • när ni stöter på kod som ni upprepar, bryt ut koden (lägg koden i en funktion/metod)
    • dela även upp er kod i fler funktioner/metoder när den blir för lång

Uppgift

I denna uppgift ska ni skriva ett program som kontrollerar stavning på alla ord i en fil. Stavningskontrollen ska använda ordfrekvens-data för att kontrollera orden. I de fall där ett ord inte finns med bland ordfrekvens-data (dvs att ordet är okänt för programmet), ska förslag på rättstavning visas.

Denna laboration blir lite av en fortsättning på det laboration 2 i kursen. I laboration 2 använde ni ordfrekvensdata för att föreslå möjliga fortsättningar på ett ord användaren skrev in, t.ex. "hopps" -> "hoppsan".

I denna uppgift ska ni beräkna det kortaste redigeringsavståndet (minimum edit distance) mellan okända ord ni stöter på i en text och ord som finns bland ordfrekvens-datat. För varje okänt ord ska programmet ge förslag på kända ord som skulle kunna ersätta det okända ordet med.

Programmet ska också informera om hur lång tid det tar att köra, skriva ut information under körning, samt spara en rapport med förslag på ordersättningar.

Förrutom att ert program ska uppfylla kraven nedan, ska ni även se till att ni ritar ett UML-diagram över era klasser (börja med en skiss på det och förfina under labben) och att koden följer kodkraven.

Se vidare avsnitten nedan om

Förberedelser innan ni börjar programmera

Innan ni börjar programmera, gör nedanstående förberedelser och visa dem för en labassistent.

  • Läs igenom informationen om implementationskrav m.m. (listan ovan).
  • Diskutera och beskriv med egna ord vad ert program ska göra. Vad behöver ert program göra? I vilken ordning? Skriv ner detta som modulkommentar i er skriptfil.
  • Gör ett utkast på ert UML-diagram. När ni börjar implementera, se till att uppdatera UML-diagrammet när ni ändrar er.
  • Beskriv kortfattat i text vad era klasser ska göra. Detta är dels för att ni i pargruppen ska vara överrens om hur ni vill strukturera programmet, samt för att underlätta för labassistenterna när de hjälper er och vid redovisning. Skriv beskrivningarna av klasserna i er skriptfil som docstrings till era klasser som ni har i ert UML-diagram.

UML-diagram

UML-diagram för er kod ska presenteras vid redovisningstillfället. Ni väljer själva om ni ritar UML-diagrammet på papper eller använder något program eller webbtjänst.

  • På datorerna i SU-salarna och på ThinLinc finns programmet Dia installerat (under kategorin “Graphics”)
  • Gratis webbtjänster ni kan använda: draw.io, umletino

Krav på implementationen

Ni får definiera fler klasser än de som beskrivs nedan. Ni får också skriva ut mer information utöver det som anges nedan.

Körtid: Ert program får inte ta mer än 1 minut per körning.

Se tipsen nedan för saker ni kan tänka på för att minska körtiden.

Klasser

  • Koden ska definiera klassen SpellingWarning vars instanser representerar upptäckta eventuella stavfel (bara för att ett ord inte finns i ordfrekvensdatat betyder inte att det är fel).
  • Koden ska definiera klassen Report som innehåller alla SpellingWarning-instanser som skapas under rättstavningskontrollen.

Spara rapport i textfil

Efter att ha kontrollerat en textfil ska en rapport sparas som en textfil (en rapportfil för varje fil som kontrolleras). Rapporten ska innehålla följande:

  • namnet på filen som kontrollerats
  • hur lång tid det tagit att kontrollera filen
  • alla potentiella fel som upptäckts

För varje potentiellt fel som upptäckts ska följande information finnas:

  • radnummer som felet upptäckts på
  • det potentiellt felstavade ordet
  • minst tre förslag på korrekta ord

Utskrifter vid körning

När skriptet körs ska minst följande information skrivas ut:

  • Efter att ordfrekvensdata har laddats, skriv ut information hur många ord som det laddats in frekvenser för, samt från vilken fil som informationen laddats in ifrån.
  • När programmet börjar kontrollera en text, skriv namnet på filen som kontrolleras.
  • När rapporten sparas, samt namnet på den fil som rapporten sparats i.

Köra skriptet

Skriptet ska gå kunna anropas direkt från prompten i ett terminalfönster och ska kunna ta emot en eller fler filer att kontrollera (se exempel längre ner)

Distansläge: Om ni kör i Windows går det bra att ni kör skriptet genom att först skriva python3:

$ python3 erfil.py ordfrekvensdata.tsv filattkontrollera.txt

Frivilligt - använd modulen argparse

Använd modulen argparse för att hantera flaggor och argument till skriptet (se nedan).

Exempel på anrop från terminal

Ni bestämmer själva vad som skrivs ut när ni kör ert program. Under utvecklingen kan ni också skriva ut mer information som hjälper er felsöka.

Exempel på kontroll av texten kort2.txt och 6cyyy-2019.txt med hjälp av ordfrekvensdata från webbnyheter:

$ ./spellcheck.py data/webbnyheter2013_stats.tsv texter/kort2.txt texter/6cyyy-2019.txt
* Loading word frequency data from 'data/webbnyheter2013_stats.tsv'...
* Frequency data for 472,748 words loaded.
* 2 file(s) to check.
* Reading 'texter/kort2.txt'' and looking for unknown words...
* Found 7 unknown words.
* Saving report to kort2_report.txt
* Reading 'texter/6cyyy-2019.txt' and looking for unknown words...
* Found 9 unknown words.
* Saving report to 6cyyy-2019_report.txt

Utskrift av rapporten för kontrollen av texten kort2.txt:

$ cat kort2_report.txt
Spell check for 'texter/dev/kort2.txt' took 2.08 seconds.

[line 2] högga: höga, högre, hög
[line 2] tråts: trots, från, två
[line 4] totalförstörelse: totalförstördes, totalförsvarets, spelförståelse
[line 6] säjer: säger, det, som
[line 7] gallet: fallet, allt, gäller
[line 9] huvudtornen: huvudrollen, huvudstaden, huvudpersonen
[line 10] redda: rädda, redan, enda
[line 11] klocktornen: koncernen, flickorna, konkursen
[line 14] uppeges: uppges, uppger, precis
[line 16] visadee: visade, visar, vidare
[line 17] himle: himlen, ville, timme

Utskrift av rapporten för kontrollen av texten 6cyyy-2019.txt:

$ cat 6cyyy-2019_report.txt
Spell check for for 'texter/6cyyy-2019.txt' took 1.75 seconds

[line 1] civilingenjörsprogram: civilingenjörsstudent, viktminskningsprogram, privatiseringsprogram
[line 14] matematikgrund: matchavgörande, stigmatisering, hatbrottsgrupp
[line 17] masterprofiler: batteriproblem, ministerposter, rasprofilering
[line 20] ämnesmässig: spelmässigt, skilsmässan, skilsmässor
[line 26] masterprofiler: batteriproblem, ministerposter, rasprofilering
[line 45] teoritung: teoretisk, searching, retoriken
[line 66] biofysiker: analytiker, historiker, biografier
[line 82] kvalitetsingenjör: kvalitetsansvarig, kvalitetsmärkning, kvalitetskontroll
[line 84] sensorfusion: konstruktion, konstitution, pansarfordon

Implementationstips

  • Leta efter okända ord: Ta bort skiljetecken från slutet på ord för att inte de ska uppfattas som en del av ordet. Gör även om det ord ni letar efter så att det bara består av små bokstäver.
  • Inläsning av ordfrekvensdata: Strunta i ord i ordfrekvensdatat som inte bara består av bokstäver.
  • Leta efter förslag: Ni kan behöva begränsa antalet förslag ert program letar efter för att hålla körtiden rimlig. Säg att ni letar efter förslag till ordet “exempfl” (7 bokstäver), så finns det i webbnyheter2013_stats.tsv fler än 35000 möjliga ord att välja mellan. Det är därför rimligt att begränsa antalet ord som programmet tittar på. Prova t.ex. att endast räkna ut redigeringsavståndet för de 1000 mest frekventa orden (antalet är godtyckligt och syftet är endast att få ner tiden det tar för ert program att köra)
  • Kontrollera om alla tecken är bokstäver: Strängmetoden str.isalpha() returnerar True om alla tecken i en sträng är bokstäver.
  • Använd dictionary: För att snabba upp uppslag av ordfrekvensen för ett ord, kan ni lagra dem i ett dictionary där ordet är nyckel och frekvensen är värdet.
  • Dela upp datat: Ni kan samtidigt lagra ord-data i separata listor för olika ordlängder så slipper ni leta efter dessa vid varje sökning. Eftersom ni inte vet hur många listor ni behöver kan ni skapa dessa vid behov och spara dem i ett dictionary där nyckeln är längden på ordet och värdet är en lista med orden.
  • Utskrift med print() som inte syns på en gång: Om ni i en loop gör en utskrift, t.ex. print(value) som inte syns förrän efter loopen är färdig kan ni lägga till nyckelordsargumentet flush=True, dvs print(value, flush=True) vilket ser till att utskriften inte buffras, utan skrivs ut på en gång.

Uppgiftsinformation

Kortaste redigeringsavståndet

Det kortaste redigeringsavståndet mellan två ord är det minsta antalet operationer (t.ex. byt ut, lägg till, ta bort) som måste utföras för att förändra ett ord till ett annat.

En algoritm som beräknar detta (Levenshtein avståndet) finns implementerat som funkionen minimum_edit_distance() i filen /courses/TDDE44/kursmaterial/laboration7/med.py som ni kan kopiera och importera in i er kod.

Distansläge: med.py

Ordfrekvensdata

Till denna laboration har ni möjlighet att välja mellan ordfrekvensdata som skapats från olika källor. Datat i dessa filer är tab-separerat (dvs tab-tecknet, \t, används för att separera ord och dess frekvens) och sorterat så att de mest frekventa orden kommer först. Ordfrekvenserna bygger på ordformer och inte orden i grundform, dvs att “stor” och “stora” räknas som två olika ord. Däremot har det inte gjorts någon skillnad på användning av stora eller små bokstäver. Filerna finns i /courses/TDDE44/kursmaterial/laboration7/data.

Distansläge: data

  • attasidor_stats.tsv bygger på nyhetsartiklar från den lättlästa webbplatsen 8 sidor och täcker knappt 56 000 ord
  • gp2013_stats.tsv bygger på texter från Göteborgs-Posten från 2013 och täcker ca 386000 ord
  • gp2d_stats.tsv bygger på texter från Göteborgs-Postens helgbilaga och täcker drygt 85000 ord
  • suc3_stats.tsv bygger på SUC 3.0 (Stockholm-Umeå Corpus) och täcker ca 95000 ord
  • webbnyheter2013_stats.tsv bygger på nyhetstexter från olika webbsidor från 2013 och täcker ca 473000 ord

Det spelar ingen större roll vilken datakälla ni använder i denna laboration, men det kommer att påverka hur många ord som är kända/okända och hur många förslag som kan hittas (t.ex. finns det fler än 42000 ord av längden 10 i webbnyheter2013_stats.tsv).

Att det finns så här mycket data betyder att ni kan behöva begränsa t.ex. hur många ord ni slår upp redigeringsavståndet för för att programmet inte ska ta för lång tid på sig.

Texter att kontrollera

Ni kan använda vilka texter ni vill för att testa ert skript, men det finns några förberedda i /courses/TDDE44/kursmaterial/laboration7/texter. Filerna kort2.txt, mellan2.txt och lang2.txt innehåller diverse stavfel. Filerna kort1.txt, mellan1.txt och lang1.txt är de ursprungliga texterna.

Distansläge: texter

OBS! Högerklicka på filerna och välj “Spara som…” istället för att besöka filerna. Förklaring: Webbservern tror att alla textfiler är kodade med ISO-8859-1 (latin-1) vilket gör att åäö i filer som är kodade med UTF-8 ser konstiga ut när de visas i webbläsaren.

Räkna hur lång tid något tar

För denna laboration kan ni använda modulen funktionen time() i modulen time för att ta reda på hur lång tid som gått. Importera time och så kan ni använda time.time() som returnerar tiden just nu uttryckt som antalet sekunder sedan kl. 0.00, 1 januari, 1970. Spara värdet på time.time() när ni börjar er bearbetning och spara värdet på time.time() när ni är klara så är differensen antalet sekunder som gått.

Kuriosa: Unix Tick Tocks to a Billion

Rättstavning / förslag på kända ord

Det finns många strategier som kan tillämpas när det kommer till att ta fram förslag på vilket känt ord (ett ord som finns i ordfrekvensdatat) som ett okänt ord (ord i texten som inte finns med i ordfrekvensdatat) kan ersättas med.

Börja med att endast titta på kända ord som är av samma längd som det okända ordet. Dvs att programmet kan föreslå korrigering av ordet "hejsam" till "hejsan".

I mån av tid kan ni uttöka funktionaliteten på programmet så att programmet även kan föreslå korrigeringar som innebär att lägga till/ta bort bokstäver från det okända ordet. T.ex. kan föreslå korrigering av "hejsa" till "hejsan" och "hejsann" till "hejsan".

Frivilligt: använda modulen argparse

Python har en inbyggd modul som kan användas för att hantera flaggor och argument som skickas till ett skript. För att lära dig om modulen, leta efter en tutorial på webben, eller se någon av de nedanstående:

I laboration 7 kan argparse användas för att definiera flaggor för att från kommandoraden bestämma t.ex.

  • hur många förslag som ska tas med i rapporten
  • maximala antalet förslag att räkna ut minimum edit distance på
  • om rapporten ska skrivas ut i terminalen förrutom att sparas till fil
  • vilken datafil som ska användas
  • osv.

Exempel: ./spellcheck.py --data data/datafil.tsv --num_sug 5 --print-report texter/kort1.txt


Sidansvarig: Johan Falkenjack
Senast uppdaterad: 2024-04-16