Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Such-Algorithmus
Gehe zu Seite Zurück  1, 2, 3, 4, 5  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Input



Anmeldungsdatum: 28.07.2014
Beiträge: 59

BeitragVerfasst am: 17.08.2014, 16:06    Titel: Antworten mit Zitat

Hallo liebes Forum, hab da noch ein Problem: Ich würde gern jedes Wort im Text zählen, weiss aber nicht ob mein Algi für die einzelnen Wörter als "Input" so gut ist. Wäre froh um jeden Tipp, Komplettlösung wär natürlich auch nicht schlecht. Vielen Dank!!

Code:

dim as integer k,l,m
dim as string suche,text
Open "Finden.txt" For Binary Access Read As #1
line input #1,text

do
for k=0 to 5
if mid(text,l,k)=space(1) then
   
for m=2 to 5
suche=mid(text,l,m)
if mid(suche,m,1)=space(1) then suche=ucase(rtrim(suche)):print suche
next m

end if
next k

l=l+1
loop until l=len(text)
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 17.08.2014, 17:56    Titel: Wörter zählen und Durchschnittslänge ermitteln Antworten mit Zitat

Hallo,

was hältst du von folgendem Code? Er zählt die Wörter und ermittelt nebenbei die durchschnittliche Länge eines Wortes. lächeln
Code:
Declare Function isSplittingChar (char As UByte) As Integer

Enum EState
    undefined
    word
End Enum

Dim As UByte char
Dim As EState state = EState.undefined
Dim As UInteger numWords = 0
Dim As UInteger currentWordCharCount = 0, totalCharCount = 0

Open ExePath + "/testtext.txt" For Binary As #1
Do Until Eof(1)
    Get #1, , char
    If (isSplittingChar(char)) Then
        If (state = EState.word) Then
            numWords += 1
            totalCharCount += currentWordCharCount
            currentWordCharCount = 0
            state = EState.undefined
        End If
    Else
        If (state = EState.undefined) Then
            state = EState.word
            currentWordCharCount = 0
        End If
        currentWordCharCount += 1
    End If
Loop
'Ist noch ein Wort angefangen?
If (state = EState.word) Then
    numWords += 1
    totalCharCount += currentWordCharCount
End If
Close #1

Dim As Double averageLength = 0
If (numWords > 0) Then
    averageLength = (totalCharCount / CDbl(numWords))
End If

Print "Es wurden " & numWords & " Woerter gezaehlt."
Print "Die durchschnittliche Wortlaenge betrug ";
Print Using "##.## "; averageLength;
Print "Buchstaben."

Print
Print "Druecken Sie eine beliebige Taste zum Beenden."
GetKey
End 0


'Ermittelt, ob das uebergebene Zeichen eines ist, das das Ende
'eines Wortes kennzeichnet (zum Beispiel ein Leerzeichen, ein
'Zeilenumbruch oder ein Komma).
Function isSplittingChar (char As UByte) As Integer
    '                               ,              .              :              ;              /
    Return ((char < 33) Or (char = 44) Or (char = 46) Or (char = 58) Or (char = 59) Or (char = 47))
End Function


Als Beispiel wird diese Datei verwendet:
Code:
Schiller: Das Lied von der Glocke


Fest     gemauert      in      der     Erden
Steht die Form, aus Lehm gebrannt.


Heute muß die Glocke werden.
Frisch Gesellen, seid zur Hand.
Von der Stirne heiß
Rinnen muß der Schweiß,
Soll das Werk den Meister loben!
Doch der Segen kommt von oben.


Ende


Das führt zur Ausgabe:
Code:
Es wurden 48 Woerter gezaehlt.
Die durchschnittliche Wortlaenge betrug  4.46 Buchstaben.

Druecken Sie eine beliebige Taste zum Beenden.


Der Code liest die Datei Zeichen für Zeichen ein und kann dabei zwischen 2 Zuständen wechseln: "Wort" und "Irgendwas anderes". Auf diese Weise führen vielfache Leerzeichen, Kommas o. ä. nicht dazu, dass die Wortzahl zu hoch ermittelt wird. Nur beim Wechsel zwischen "Wort" und "Irgendwas anderes" wird der Wortzähler erhöht (oder am Ende der Datei, falls noch ein angefangenes Wort aktiv ist). Das könnte man auch schön als Automat modellieren.

In der Funktion isSplittingChar kann flexibel konfiguriert werden, welche Zeichen das Ende eines Wortes signalisieren sollen. So könnte man beispielsweise leicht noch Fragezeichen, Ausrufezeichen o. ä. hinzufügen, während z. B. ein Bindestrich kein neues Wort einleiten soll. Ob "Müller-Lüdenscheid" als 1 oder 2 Wörter zählen soll, kann man so anpassen.

Viele Grüße!
Sebastian
_________________

Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Input



Anmeldungsdatum: 28.07.2014
Beiträge: 59

BeitragVerfasst am: 17.08.2014, 19:14    Titel: Antworten mit Zitat

Vielen Dank!! Ich möchte aber eigentlich nur das erste Wort als Variable in ein Arrey schreiben, dann das Zweite...

Wenn dann ein Wort im Arrey schon vorhanden ist, dann wird einfach die Zahl auf 2 erhöht. Am Ende sollte es dann etwa so aussehen: Und=3 das=5 Hase=1

Mein Problem ist jetzt einfach, dass mein Prog sehr langsam ist und die Schleife wohl fast unendlich dreht.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 17.08.2014, 19:39    Titel: HashMap / Baum Antworten mit Zitat

Hallo,

dann bräuchtest du idealerweise sowas:
http://de.wikipedia.org/wiki/Hashtabelle

Wenn du ein Wort isoliert hast, musst du vom Wort (= String) zu einer Integer-Variablen kommen, die diesem Wort zugeordnet ist. Diese Integer-Variable wäre der Häufigkeitszähler des Wortes.

Eine relativ schlichte Lösung bestünde darin, einen TYPE anzulegen, der ein Wort und einen Integer enthält, und davon ein Array zu erzeugen:
Code:
TYPE TWordOccurrences
  Word As String
  Occurrences As Integer
END TYPE

Dim WordLookupArray(1 To 1) As TWordOccurrences


Dieses Array müsste für jedes gefundene Wort von Anfang bis Ende durchlaufen werden. Wenn ein gleichlautendes Wort im Array gefunden wird, wird der Zähler erhöht. Ansonsten müsste das Array mit Redim Preserve vergrößert werden. Der neu hinzugefügte Datensatz müsste mit dem Zähler 1 initialisiert werden.

Das wäre allerdings gleich an verschiedenen Stellen ineffizient. Arrays können eigentlich nicht wachsen. Müssen sie vergrößert werden, wird ein neues, größeres Array erzeugt und das alte (kleine) Array wird in das neue (große) rüberkopiert. Außerdem muss für jedes Wort in der Datei das zunehmend größere Array sequentiell durchsucht werden. Für jede Array-Zeile muss ein aufwendiger String-Vergleich durchgeführt werden. Insgesamt wäre das relativ langsam - ganz besonders, wenn die Input-Datei groß ist und nicht bloß 48 Wörter enthält. lächeln

Eine HashMap o. ä. bietet FreeBASIC leider nicht von Haus aus an. Es gibt, wenn ich mich recht erinnere, Map-Implementierungen von Stueber und von MOD (mdTypes). Wie sich die performancemäßig machen, weiß ich spontan aber leider nicht mehr.

Eine Möglichkeit für eine eigene Implementierung könnte ein Baum sein. Jeder Knoten hätte (wenn die Groß-/Kleinschreibung egal wäre) 26 Sub-Knoten (= Pointer) und einen Integer-Datenwert. Dieser entspräche der Häufigkeit des Buchstabenpfads, der in diesem Knoten endet. Die Tiefe des Baums entspräche der maximalen Wortlänge. Dieser Ansatz käme ohne eine Hash-Funktion aus.

Viele Grüße!
Sebastian
_________________

Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 18.08.2014, 09:37    Titel: Antworten mit Zitat

Hallo,

Input hat Folgendes geschrieben:
Komplettlösung wär natürlich auch nicht schlecht.
Bitte sehr, für dich tun wir doch alles! zwinkern Ich habe unter Verwendung von Sebastians Trennzeichen-Function ein Programm geschrieben, das mit sukzessiver Approximation arbeitet. Das ist schneller als eine lineare Suche und einfacher als das Hashverfahren.

Du hast dabei eine (alphabetisch) geordnete Tabelle aller bisher gefundenen Wörter. Um ein bestimmtes Wort zu suchen, fängst du in der Mitte der Tabelle an und prüfst, ob das Wort an dieser Stelle vor oder hinter dem gesuchten Wort steht, das Wort also in der oberen oder der unteren Hälfte der Tabelle zu suchen ist. Diese Hälfte teilst du wieder in zwei Hälften usw., wobei du die Schrittweite jedesmal halbierst. Damit lässt sich eine Tabelle mit 2^n Elementen mit n Schritten durchsuchen.
Die Länge des Arrays sollte eine Zweierpotenz sein (also 16, 32, 64 usw), deshalb wird seine Größe jedesmal verdoppelt, wenn es zu klein wird.
Code:
Declare Function isSplittingChar (char As UByte) As Integer

Type wa
   wort As String
   anzahl As Integer
End Type

ReDim As wa tabelle(16)
Dim As String text
Dim As Integer anfang, ende, x, schrittweite

Open ExePath + "/testtext.txt" For Binary Access Read As #1
text = Input (Lof(1),1) 'datei einlesen
Close 1
anfang = -1

Do 'text abarbeiten
   Do 'nächsten wortanfang suchen
      anfang += 1
   Loop Until (isSplittingChar(text[anfang]) = 0) Or (anfang > Len(text))
   ende = anfang
   Do 'nächstes wortende suchen
      ende += 1
   Loop Until (isSplittingChar(text[ende]) <> 0)  Or (ende >= Len(text))
   tabelle(0).wort = LCase(Mid(text,anfang + 1, ende - anfang)) 'wort aus text holen
   If tabelle(0).wort = "" Then
      Exit Do
   EndIf
   anfang = ende 'zeiger für nächste suche setzen
   x = UBound(tabelle) / 2 'mitte der tabelle
   schrittweite = x / 2
   tabelle(0).anzahl = 1 'zählerwert für neues wort
      
   Do 'wort in tabelle suchen
      If tabelle(x).wort = tabelle(0).wort Then 'wort gefunden
         Exit Do
      ElseIf tabelle(x).wort > tabelle(0).wort Or tabelle(x).wort = "" Then
         x -= schrittweite 'nach oben
      ElseIf tabelle(x).wort < tabelle(0).wort Then
         x += schrittweite 'nach unten
      EndIf
      schrittweite /= 2 'schrittweite halbieren
   Loop While schrittweite >= 1
   
   If tabelle(x).wort = tabelle(0).wort Then 'wort schon vorhanden
      tabelle(x).anzahl += 1 'zähler erhöhen
   Else 'neues wort einfügen
      Do While (tabelle(x).wort < tabelle(0).wort) And (tabelle(x).wort <> "") 'index korrigieren
         x += 1
      Loop
      Do 'alle werte hinter dem neuen wort um eine stelle nach unten schieben
         Swap tabelle(x),tabelle(0)
         x += 1
      Loop Until tabelle(0).wort = ""
            
      If tabelle(UBound(tabelle)).wort <> "" Then
         ReDim Preserve tabelle(UBound(tabelle) * 2) 'tabellengröße verdoppeln
      EndIf
   EndIf
Loop Until ende >= Len(text)

For x = 1 To UBound(tabelle)
   If tabelle(x).wort = "" Then
      Exit For
   EndIf
   Print x;" ";tabelle(x).wort;" =";tabelle(x).anzahl
   If x Mod 20 = 0 Then
      Sleep
   EndIf
Next

Sleep
End

'Ermittelt, ob das uebergebene Zeichen eines ist, das das Ende
'eines Wortes kennzeichnet (zum Beispiel ein Leerzeichen, ein
'Zeilenumbruch oder ein Komma).
Function isSplittingChar (char As UByte) As Integer
   '                               ,              .              :              ;              /
   Return ((char < 33) Or (char = 44) Or (char = 46) Or (char = 58) Or (char = 59) Or (char = 47))
End Function


Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 18.08.2014, 16:09    Titel: Implementierung mit Baum Antworten mit Zitat

Hallo,

ich habe mal den Ansatz mit einem Baum implementiert:
http://users.freebasic-portal.de/sebastian/fb/wordcount/wordcount_tree.zip

Hier der Quelltext (ist aber auch im ZIP-Archiv enthalten):
http://users.freebasic-portal.de/sebastian/fb/wordcount/wordcount_tree.bas

Das ZIP-Archiv enthält die rund 1 MB große deutsche Übersetzung der Debian-Referenz.

Das Programm ist nur oberflächlich getestet. Verwendung auf eigene Gefahr und ohne Garantie für Richtigkeit der Ergebnisse. Sicherlich sind an manchen Stellen Optimierungen möglich. Zum Beispiel wird oft LEN(...) ermittelt. Das könnte man besser als Integer-Parameter mitschleifen, damit das nicht so oft ermittelt werden muss. Allerdings wird dadurch das Programm auch etwas unübersichtlicher.

Der Häufigkeitsbaum wird so tief wie die Länge des längsten Wortes. Der Aufwand zum Nachschlagen einer Worthäufigkeit ist linear von der Wortlänge abhängig und dauert für alle Worte der Länge n gleich lang (Best Case = Worst Case = Average Case). Es ist also etwas anderes als eine sequentielle "Liste", wo es eine Rolle spielt, ob das Wort am Anfang der Liste sofort gefunden wird (Best Case) oder erst die ganze Liste bis zum Ende durchsucht werden muss, ehe das Wort gefunden wird (Worst Case).



Bei den Zeitmessungen ist zu beachten, dass beide durch PRINT-Ausgaben zwischendurch verfälscht (= verlängert) werden (Zeilen 64-66 und Zeile 107).

Viele Grüße!
Sebastian
_________________

Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Input



Anmeldungsdatum: 28.07.2014
Beiträge: 59

BeitragVerfasst am: 18.08.2014, 21:40    Titel: Antworten mit Zitat

Vielen Dank euch beiden; ihr seit ja echte Freaks!! happy Ich werd es aber trotzdem mal selber noch versuchen; vom Prinzip her sollte es ja nicht all zu schwer sein. Werde mich melden, wenn ich's geschafft hab. LG: Input zwinkern
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 19.08.2014, 13:16    Titel: Antworten mit Zitat

@ Sebastian:
Ich habe unsere beiden Programme mal miteinander verglichen: Beim Suchen von einzelnen Wörtern ist dein Programm ca. 15 mal so schnell wie meins, da helfen auch alle Programmiertricks nichts. grinsen Dafür habe ich beim Einlesen der Datei die Nase vorn. lächeln Ich habe mir daher erlaubt, beides zu kombinieren und deine Einleseroutine umzuschreiben. Das Resultat habe ich nach http://www.freebasic-portal.de/porticula/wortzaehler-1773.html hochgeladen. Die Vermischung unserer Programmierstile sieht nicht wirklich schön aus, aber es funktioniert: Das Einlesen geht jetzt gut 10mal so schnell. happy

Eine Macke hat das Programm allerdings (noch): Wenn man nach einem Wort sucht, das im Text nicht vorkommt, stürzt es ab.

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 19.08.2014, 19:27    Titel: Antworten mit Zitat

grindstone hat Folgendes geschrieben:
ca. 15 mal so schnell

Ja, es ist halt ein ganz anderer Ansatz. Bei einem Array, in dem sequentiell nachgeschlagen wird, nimmt der durchschnittliche Nachschlageaufwand mit der Größe des Arrays (also mit der Anzahl unterschiedlicher Wörter) zu. Je mehr Wörter im Array sind, desto länger dauert es durchschnittlich, bis das gesuchte gefunden wird. Wenn das gesuchte Wort gar nicht in der Liste ist, muss sogar das ganze Array durchsucht werden, wenn man es nicht nach dem Einlesen sortiert.

Bei der Baum-Methode ist der Nachschlage-Aufwand nur von der Länge des nachzuschlagenden Wortes abhängig. Das Nachschlagen eines bspw. 8-buchstabigen Worts verursacht immer den gleichen Aufwand - egal, ob 3 Wörter oder 3 Millionen Wörter verwaltet werden.

Der Performance-Unterschied zwischen Array und Baum wird also mit zunehmender Wortanzahl / Datenmenge noch erheblicher.

grindstone hat Folgendes geschrieben:
Das Einlesen geht jetzt gut 10mal so schnell.

Der Geschwindigkeitsunterschied beim Einlesen begründet sich damit, dass dein Code die komplette Datei zuerst in einem Stück in den RAM einliest und dann aus dem String im RAM die Wörter extrahiert. Operationen auf Daten im RAM sind viel schneller als auf Festplattendaten. Allerdings ist der Nachteil der Methode, dass die ganze Datei zuerst in einem Stück eingelesen werden muss (ggf. auch eine 1 GB große Datei). Mein Code liest Zeichen für Zeichen ein und der Wortpuffer wird nur so lang wie das längste Wort. Man spart also womöglich gigabyteweise Speicher.

Ist mal wieder ein "Trade-Off", wo man abwägen muss, in welche Richtung man optimieren möchte. lächeln

grindstone hat Folgendes geschrieben:
Eine Macke hat das Programm allerdings (noch): Wenn man nach einem Wort sucht, das im Text nicht vorkommt, stürzt es ab.

Ups, Bug ist behoben. lächeln (Link ist gleich geblieben.)


_________________

Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 562
Wohnort: Jüterbog

BeitragVerfasst am: 19.08.2014, 20:13    Titel: Antworten mit Zitat

Find das mit dem Baum recht spannen aber mir geht hier ein wenig die Vorstellung verloren.

Angenommen hab "nur" meine 26 Buchstaben:
eine Hand mit 26 Fingern und auf jedem Finger wieder eine (mit 26 Finger) usw?

Mutton
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 19.08.2014, 20:24    Titel: Antworten mit Zitat

Muttonhead hat Folgendes geschrieben:
Angenommen hab "nur" meine 26 Buchstaben:
eine Hand mit 26 Fingern und auf jedem Finger wieder eine (mit 26 Finger) usw?

Genau. lächeln

Nicht an jedem Finger geht es weiter zu einer tieferliegenden Hand, sondern auf einem Finger kann auch NULL stehen. Und auf jeder Handfläche steht drauf, wie häufig das Wort vorkommt, das bei dieser Hand endet.

Beim Wort "HAND" würde der Pfad H->A->N->D verfolgt (4 Ebenen tief) und dann der Zähler vom D am Ende um 1 erhöht.
_________________

Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Toa-Nuva



Anmeldungsdatum: 14.04.2006
Beiträge: 204
Wohnort: München

BeitragVerfasst am: 20.08.2014, 02:33    Titel: Antworten mit Zitat

Diese Datenstruktur nennt sich übrigens Trie. lächeln

Was den Tradeoff zwischen Einlesen einzelner Zeichen vs kompletter Dateien angeht, da würde ich eigentlich immer einen Puffer fester Größe (z.B. 16 oder 32 KB) verwenden. Dann hängt es nicht von der Dateigröße ab, wie viel Arbeitsspeicher man verbraucht, und trotzdem sollte das Lesen nicht (wahrnehmbar) länger dauern, als würde man die komplette Datei auf einmal einlesen.
Wenn die Programmiersprache bzw deren Bibliotheken von sich aus nicht schon so was anbieten, würde es sich empfehlen, selbst einen Wrapper für die zur Verfügung stehenden Dateizugriffsoperationen zu schreiben.
Zeichenweises Einlesen direkt von der Festplatte würde ich auf jeden Fall auf den Tod vermeiden. happy
_________________
704 Signature not found
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 20.08.2014, 03:13    Titel: Antworten mit Zitat

Sebastian hat Folgendes geschrieben:
Operationen auf Daten im RAM sind viel schneller als auf Festplattendaten
Natürlich ist das schneller, deshalb mache ich es ja. grinsen Das alleine bringt allerdings "nur" eine verfünffachung der Geschwindigkeit. Das Isolieren der einzelnen Wörter mithilfe von 2 Pointern, die sich am String "entlanghangeln", verdoppelt dann noch einmal das Tempo.
Sebastian hat Folgendes geschrieben:
Man spart also womöglich gigabyteweise Speicher
Mit dem Problem der begrenzten Stringlänge habe ich mich zu QBasic-Zeiten herumgeschlagen (max. 64kB für alle Daten), es ist -bei Bedarf- ganz einfach zu lösen: Es wird immer nur eine speicherverträgliche Menge an Daten geladen. Sobald ein Pointer das Ende des Strings erreicht, wird der vordere Teil des Strings, der schon abgearbeitet ist, gelöscht und eine geeignete Menge nachgeladen und hinten drangehängt. Das ist immer noch deutlich schneller, als jedes Zeichen einzeln aus der Datei zu holen.

Und überhaupt der Speicherbedarf: Der komplette Baum belegt ca. 77,6 MB. also etwa das 78fache der Ausgangsdatei, da fällt der eine String in Dateigröße eigentlich kaum noch ins Gewicht. Oder anders ausgedrückt: Wenn für einen String in Dateilänge nicht genug Speicher da ist, reicht es für den Baum erst recht nicht. zwinkern

Nur zum Vergleich: Die fertig eingelesene und alphabetisch geordnete Tabelle mit den dazugehörigen Häufigkeiten ist gerade einmal 209 kB groß.

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Toa-Nuva



Anmeldungsdatum: 14.04.2006
Beiträge: 204
Wohnort: München

BeitragVerfasst am: 20.08.2014, 14:23    Titel: Antworten mit Zitat

grindstone hat Folgendes geschrieben:
Und überhaupt der Speicherbedarf: Der komplette Baum belegt ca. 77,6 MB. also etwa das 78fache der Ausgangsdatei, da fällt der eine String in Dateigröße eigentlich kaum noch ins Gewicht. Oder anders ausgedrückt: Wenn für einen String in Dateilänge nicht genug Speicher da ist, reicht es für den Baum erst recht nicht. zwinkern

Je größer die Datei ist, desto eher kommen darin aber auch Wörter (bzw Präfixe) mehrfach vor. Und die erzeugen dann ja keine zusätzlichen Speicherkosten (Knoten im Baum). D.h. die Größe des Baumes sollte deutlich sublinear mit der Größe der Datei wachsen. Wenn die Datei nur ein einziges Wort enthält, sollte der Baum grob überschlagen sogar ~900 Mal so viel Speicher belegen wie die Datei. grinsen Kann ja mal jemand ausprobieren, wie groß eine Datei (mit sinnvollem Inhalt) sein muss, bis der Speicherbedarf des Baumes von der Dateigröße überholt wird. happy

Und natürlich gäbe es noch viele Möglichkeiten, Speicher zu sparen. Wenn man z.B. jedes Wort in eine Kombination von ASCII-Kleinbuchstaben normalisiert, sind nur noch 26 (statt 224) Pointer in jedem Knoten nötig. Oder man könnte eine dynamisch wachsende Hash-Tabelle o.ä. anstelle eines Arrays fester Größe verwenden verwenden, sodass ein Knoten mit wenigen Kind-Knoten (Pointern, die nicht null sind) auch weniger Speicher belegt als einer mit vielen Kind-Knoten. happy
_________________
704 Signature not found
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
Sebastian
Administrator


Anmeldungsdatum: 10.09.2004
Beiträge: 5969
Wohnort: Deutschland

BeitragVerfasst am: 20.08.2014, 15:47    Titel: Antworten mit Zitat

Toa-Nuva hat Folgendes geschrieben:
Je größer die Datei ist, desto eher kommen darin aber auch Wörter (bzw Präfixe) mehrfach vor. Und die erzeugen dann ja keine zusätzlichen Speicherkosten (Knoten im Baum). D.h. die Größe des Baumes sollte deutlich sublinear mit der Größe der Datei wachsen.

ja, hätte es nicht besser formulieren können zwinkern

Für jede Wiederholung eines Wortes wird ja lediglich der UInteger-Zähler im Knoten inkrementiert. Die Größe des Baumes bzw. der Speicherbedarf ist, wie Toa-Nuva schon schreibt, nur von der Anzahl verschiedener Wörter abhängig. Je mehr Text man eingelesen hat, desto seltener wird der Fall, dass man auf ein Wort stößt, das bisher keinen Pfad hat.

Wenn du eine 10 GB große Datei verarbeiten lässt, die nur aus "Hallo Welt"-Wiederholungen besteht, hast du nur "eine Hand voll" Knoten mit wenigen kB Speicherbedarf.

Bei Texten mit natürlicher Sprache lässt sich der RAM-Bedarf des Baums als Sättigungskurve beschreiben mit ganz geringen RAM-Grenzkosten pro zusätzlicher Textmenge, wenn erst mal ein Vorrat an Text eingelesen ist.

Hab mal versucht, das grob zu skizzieren:



Hat jemand Lust, mit FB+Screen eine grafische Darstellung des Baumwachstums zu basteln, wenn z. B. der Volltext der Bibel oder der deutschen Wikipedia eingelesen wird? happy

Viele Grüße!
Sebastian
_________________

Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden Website dieses Benutzers besuchen
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 21.08.2014, 02:17    Titel: Antworten mit Zitat

Sebastian hat Folgendes geschrieben:
Hat jemand Lust, mit FB+Screen eine grafische Darstellung des Baumwachstums zu basteln, wenn z. B. der Volltext der Bibel oder der deutschen Wikipedia eingelesen wird? happy
Bring mich nicht auf dumme Gedanken! Ich habe mit dem Thema sowieso schon viel mehr Zeit verbracht, als ich eigentlich wollte...
.....

bin dagegen ==> Hmmm.... ==> bin dafür ==> Pfff.... ==> bin dagegen ==> mit dem Kopf durch die Mauer wollen ==> bin dafür

... OK, die Bibel ist kein Problem, aber wie komme ich an den Volltext von Wikipedia? Und -Frage an den Administrator- wie kann ich hier im Forum einen Screenshot posten?

Gruß
grindstone
_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4597
Wohnort: ~/

BeitragVerfasst am: 21.08.2014, 08:34    Titel: Antworten mit Zitat

Der Volltext der Wikipedia wird wohl schwierig - außer du schreibst dir einen Crawler - einzelne Artikel könntest du aber als Ebook sichern, wobei auch die Ausgabe als PDF oder ODF unterstützt wird.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
RockTheSchock



Anmeldungsdatum: 04.04.2007
Beiträge: 138

BeitragVerfasst am: 21.08.2014, 09:06    Titel: Antworten mit Zitat

Naja einen Crawler braucht man dafür nicht. Da gibt es dumps, für die es wiederum Tools zum Import in eine SQL Datenbank gibt.

http://de.wikipedia.org/wiki/Hilfe:Download
http://dumps.wikimedia.org/enwiki/latest/
http://dumps.wikimedia.org/dewiki/latest/

Ich habe mir mal eine Datei angeschaut. Die scheint zumindest aus reinem Text zu bestehen - einen Titel pro Zeile.
dewiki-latest-all-titles-in-ns0.gz

dewiki-latest-pages-articles.xml.bz2
Aus der XML Datei dewiki-latest-pages-articles.xml.bz2 kann man sicher auch den Text leicht herausholen. Z.b. gibt es folgendes Tool:

https://github.com/bwbaugh/wikipedia-extractor
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
grindstone



Anmeldungsdatum: 03.10.2010
Beiträge: 1211
Wohnort: Ruhrpott

BeitragVerfasst am: 21.08.2014, 10:20    Titel: Antworten mit Zitat

Unter ftp://ftp5.gwdg.de/pub/wikipedia/DVD/Wikipedia.zeno kann man den kompletten Text herunterladen (Dateigröße ca. 3 GB), allerdings nicht als lesbaren Text, sondern (angeblich) im XML-Format. Es gibt dazu Anzeigetools, aber ob man das Ganze damit in ASCII-Text konvertieren kann, weiß ich nicht, und Open Office dürfte vor dieser Dateigröße wohl kapitulieren. Ich werde mal downloaden, aber das dauert...

Die Bibel als reiner Text ist übrigens gerade mal 4 MB groß. verwundert

Gruß
grindstone

EDIT: Hier ein Screenshot einer ersten "quick & dirty" - Version der grafischen Darstellung des Speicherbedarfs (mit der Bibel als Quelltext, AT + NT)


_________________
For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen!


Zuletzt bearbeitet von grindstone am 14.10.2014, 07:03, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Muttonhead



Anmeldungsdatum: 26.08.2008
Beiträge: 562
Wohnort: Jüterbog

BeitragVerfasst am: 21.08.2014, 15:17    Titel: Antworten mit Zitat

Ist das der komplette Graph? Würde ja bedeuten das die Bibel bis zum Schluß fleißig mit neuen Wörtern bestückt ist, der Graph ist ja nun alles andere als grade

Mutton
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite Zurück  1, 2, 3, 4, 5  Weiter
Seite 2 von 5

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz