BPS #1: Buchstaben zählen - Auswertung

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

hamZta

Administrator

Betreff: BPS #1: Buchstaben zählen - Auswertung

BeitragMi, Jan 05, 2011 14:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Nachdem das Ende der ersten BPS etwas ungünstig auf die Feiertag gefallen ist, kommt nun verspätet aber doch der Auswertungsthread für die erste Aufgabe.

Aufgabenstellung

Postet hier eure Ergebnisse, Codes, Gedanken. Lernt von den anderen, seht euch deren Quelltext an und versucht euren eigenen zu verbessern.

Diskussion
Postet zu euren Codes stets eine kurze Erklärung mit euren Gedanken in denen ihr simpel gesagt die Frage "Wieso habe ich XY auf diese Art gelöst?" beantwortet. Beiträge, die nur den Code enthalten werden wir aus dem Thread entfernen.

Nächste Aufgabe
Ihr habt eine Woche Zeit, eure erste Aufgabe zu verbessern bzw. zu besprechen, dann kommt die nächste Aufgabe.

Viel Spaß!
Blog.

DaysShadow

BeitragMi, Jan 05, 2011 14:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Tjoa irgendwie will wohl keiner Razz

Ein Array mit 26 Plätzen für jeden Buchstaben, da zwischen Klein- und Großschreibung nicht unterschieden werden sollte, reicht.
Dann braucht man einen Stream zum lesen aus der Textdatei und einen Zwischenspeicher für jede Zeile die ich lese.
Dann hangele ich jeden Buchstaben der ausgelesenen Zeile ab und prüfe welchen Buchstaben ich da gerade habe.
Damit ich nicht 26 Mal If benutzen muss, benutze ich Mod zum angeben des richtigen Platzes im Array.
Das wird getan bis die letzte Zeile gelesen ist und dann wird ausgegeben, wie oft welcher Buchstabe vorkommt.

Finde die ganze Sache übrigens sehr nett, Lob an euch Wink

BlitzMax: [AUSKLAPPEN]
SuperStrict

Global letter_count:Int[ 26 ]
Global stream:TStream
Global line:String

stream = ReadStream( AppArgs[ 1 ] )

Repeat

line = stream.ReadLine( )

For Local i:Int = 0 Until line.length

If( line[ i ] >= 65 And line[ i ] <= 90 )

letter_count[ line[ i ] Mod 65 ]:+ 1

Else If( line[ i ] >= 97 And line[ i ] <= 122 )

letter_count[ line[ i ] Mod 97 ]:+ 1

End If

Next

Until( stream.Eof( ) )

stream.Close( )

For Local i:Int = 0 To 25

Print( Chr( 65 + i ) + ": " + letter_count[ i ] )

Next

Input( "Drücke eine Taste um zu beenden" )
Blessed is the mind too small for doubt

markus

BeitragMi, Jan 05, 2011 14:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Meinen Code habe ich so schreiben wollen, dass die Ausgabe ähnlich aussieht wie in der Aufgabenstellung gezeigt.

Also einfach per Schleife die Buchstaben A bis Z aufgelistet mit der Anzahl der im Text enthaltenen Buchstaben.

A: X
B: X
...

Die Textdatei habe ich als "test01.txt" gespeichert und im selben Ordner abgelegt wie die bmx-Datei mit meiner BPS-Lösung. Als Text habe ich den Beispieltext aus der Aufgabenstellung genommen.

Hier mein grobes Vorgehen:
1) Jede Zeile des Textes wird gelesen, wobei ich - sieht man ja in meinem Code - von maximal 1001 (For i=0 To 1000) Zeilen ausgehe.
2) Von jeder Zeile wird mit Len(Zeile) die Zeichenlänge der jeweiligen Zeile erfasst und aufgrund dessen...
3) jedes einzelne Zeichen der aktuellen Zeile (For j=0 To Len(Zeile)) mit Mid$() durchgegangen.
4) Jedes Zeichen, das aktuell im der Variable B3$ erfasst ist wird jetzt geprüft. Dabei werden Groß- und Kleinbuchstaben berücksichtigt. Der Abstand bei Ascii zwischen den Klein- und Großbuchstaben beträgt immer 32 Zeichen, deswegen habe ich die Prüfung so formuliert:

Wenn aktuelles Zeichen den Ascii-Code von 65(Großes A) oder 65+32(kleines a) aufweist, dann wird der Wert im Array B(65) um 1 erhöht. Wenn Zeichen-Ascii-Code 66(Großes B) oder 66+32(kleines b), dann B(66):+1, ...

Hoffe, dass es verständlich und richtig ist ^^"

Code: [AUSKLAPPEN]
Strict
AppTitle="Buchstaben zaehlen"
Graphics 640,800

Global B[123],i,j,k

start()

Repeat
   Cls
   
   For i = 65 To 90
      DrawText Chr$(i)+": "+B[i],5,(i-65)*15   
   Next

   Flip
Until KeyHit(Key_Escape) Or AppTerminate()

Function start()
   Local Datei:TStream
   Datei = ReadFile("test01.txt")
   Local B2$,B3$
   For i=0 To 1000
      B2$ = ReadLine(Datei)
      For j=0 To Len(B2)
         B3$ = Mid$(B2,j,1)
         For k = 65 To 90
            If Asc(B3$) = k Then
               B[k]:+1
            ElseIf Asc(B3$) = (k+32) Then
               B[k]:+1
            EndIf
         Next
      Next
   Next
End Function


Edit: Jetzt habe ich bei anderen etwas gutes gesehen. Der unten stehende Code unterscheidet sich nur insofern, dass anstatt stur 1.000 Zeilen durchzugehen funktioniert er jetzt mit Return ... Until EoF(Datei) Very Happy

BlitzMax: [AUSKLAPPEN]

Strict
AppTitle="Buchstaben zaehlen"
Graphics 640,800

Global B[123],i,j,k

start()

Repeat
Cls

For i = 65 To 90
DrawText Chr$(i)+": "+B[i],5,(i-65)*15
Next

Flip
Until KeyHit(Key_Escape) Or AppTerminate()

Function start()
Local Datei:TStream
Datei = ReadFile("test01.txt")
Local B2$,B3$
'For i=0 To 1000
Return
B2$ = ReadLine(Datei)
For j=0 To Len(B2)
B3$ = Mid$(B2,j,1)
For k = 65 To 90
If Asc(B3$) = k Then
B[k]:+1
ElseIf Asc(B3$) = (k+32) Then
B[k]:+1
EndIf
Next
Next
'Next
Until Eof(Datei)
End Function
  • Zuletzt bearbeitet von markus am Mi, Jan 05, 2011 17:07, insgesamt 2-mal bearbeitet

skey-z

BeitragMi, Jan 05, 2011 15:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Dank der Erwähnung von Slices habe ich auf jedenfall wieder was neues gelernt und bin somit um große if-Abfragen drum herum gekommen.

Es werden beim zählen der Zeichen alle Ascii-Codes(0-255) berücksichtigt, wodurch auch Steuer und Satzzeichen ganz einfach ausgelesen werden können, ohne den Code groß umbauen zu müssen.

Zum testen habe ich lediglich den Beispieltext aus dem Aufgabenthread herangezogen und mal ein paar andere Zeichen mit eingabaut um auf Fehler zu testen.

Kommentare stehen direkt im Code, so wie es gefordert war.


BlitzMax: [AUSKLAPPEN]

Rem
skey-z
für BPS #1 - Buchstaben zählen
EndRem


SuperStrict

'Array deklarieren
Local ascii:Int[256]

'Datei laden
Local file:TStream=OpenFile("text.txt")

'Datei auslesen
Repeat

Local line:String = ReadLine(file)
Local lenght:Int = Len(line)

'Zeile Buchstabenweise auslesen und in das Array eintragen
For Local i:Int = 0 To lenght

Rem
Buchstaben in GROßSCHRIFT und in Ascii Code umwandeln
ASC(buchstabe$) = buchstabe in ASCII-Code
MID(text$, start%, länge%) = einzelne Zeichen aus dem text$ filtern
UPPER(text) = Alle Buchstaben in Große umwandeln
EndRem


Local char:Int = Asc(Mid(Upper(line),i,1))

'in Array eintragen wenn der Ascii-Code größer oder gleich null sind
If (char >= 0) Then
ascii[char] :+ 1
EndIf
Next

Until Eof(file) 'bis die Datei keineweiteren Zeichen enthält

CloseFile(file)

'Array auf das wesentliche verkürzen(A-Z) : siehe Slices
ascii = ascii[65..91]

'A-Z in Großbuchstaben ausgeben/verkürztes Array ausgeben
Print "----------------------------------"
Print "- Ausgabe A-Z in Grossbuchstaben -"
Print "----------------------------------"

For Local i:Int=0 To ascii.length-1
Print Chr(i+65) + ": " +ascii[i]
Next

Biesi

BeitragMi, Jan 05, 2011 21:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich wollte den Programm-Code so einfach wie möglich (mit möglichst nur BASIC-Teile, die ein Anfänger kennen könnte) und von der Struktur her gleich mit 'SuperStrict' erstellen.
Der Teil mit den Dateioperationen war für mich ganz neu (Anfänger Shocked ), aber Dank sehr guter Forum-Datenbank und der BMax-Hilfe konnte die Aufgabe gelöst werden! Very Happy

Die Aufgabe setzte nur das Auswerten der (Groß)Buchstaben und die Ausgabe in einer Bildschirmliste voraus.

Code-Beschreibung (Übersicht):
- Definition aller im Programm vorkommenden Variablen
- Generierung eines zweidimensionalen Feldes mit 2 Spalten a 26 Zeilen
Aufgabenlösung wird über ein vordefiniertes Feld gehandhabt mit einer Spalte für alle 26 Großbuchstaben und einer Spalte zum Zählen
- Datei öffnen und in einer While-Wend Schleife
Zeilenweise auslesen 'ReadLine'
alle Buchstaben in Großbuchstaben wandeln 'Upper'
Zeilenlänge ermittlen 'Len'
Mit 2 verschachtelten For-Schleifen jeden Buchstaben mit allen 26 möglichen ASCII-Codes vergleichen 'If' und 'a$[i]' und wenn eine Übereinstimmung gefunden wurde, dann das Zählfeld für den gefundenen ASCII-Code um 1 erhöhen
Die While-Schleife läuft bis zum Ende der Datei - Hier die 3te Zeile
Datei schließen
- Array-Werte auf den Bildschirm ausgeben
Mit einer For-Schleife alle 26 Zeilen des Arrays auslesen, ASCII-Code wieder in Buchstaben wandeln 'Chr' und den Wert des Zählfeldes anhängen

BlitzMax: [AUSKLAPPEN]
' BPS #1: Buchstaben zählen
' Von Biesi
' ASCII-Code A-Z = 65-90
SuperStrict

Global buchstabenarray%[26,2] 'Array für die Zeichenzählung
Global i:Int,ii:Int 'allg. Zählvariablen
Global file:TStream 'Variable für die Dateioperationen (Vorgabe von brl.stream.TStream)
Global zeilenlaenge:Int 'Variable für die jeweilige Zeilenlänge
Global a:String 'zum Speichern des Textes

' Array für die Zeichenzählung generieren
' Erste Feld für den ASCII-Code
' Zweites Feld ist Zählfeld
For i = 0 To 25
buchstabenarray[i,0] = i + 65
buchstabenarray[i,1] = 0
Next

' Datei zeilenweise auslesen und verarbeiten
file=ReadFile("test.txt")
If Not file RuntimeError "Datei test.txt ist nicht vorhanden!"
While Not Eof(file)
a$ = ReadLine(file)
a$ = Upper(a$) 'Alle Zeichen in der Zeile zu Großbuchstaben konvertieren
zeilenlaenge = (Len a$)-1 'Zeilenlänge ermitteln und auf Array (!! 0-...) anpassen
For i = 0 To zeilenlaenge
For ii = 0 To 25
If buchstabenarray[ii,0] = a$[i] 'Durch Arrayfeldabfrage wird der ASCII-Code übergeben
buchstabenarray[ii,1] = buchstabenarray[ii,1]+1 'Wenn Übereinstimmung, dann Zählfeld +1
EndIf
Next
Next
Wend
CloseStream file

' Ergebnisausgabe
For i = 0 To 25
Print Chr(buchstabenarray[i,0])+": "+buchstabenarray[i,1]
Next
 

Macintosh

BeitragDo, Jan 06, 2011 15:50
Antworten mit Zitat
Benutzer-Profile anzeigen
So... Hier Mein Code
:)

Es werden alle Zeichen gezählt, aber nur buchstaben aA-zZ ausgegeben.

1. Datei Öffnen
2. Datei bis zum Ende auslesen und jeden Character im array +1
3. Alle Character von aA-zZ ausgeben und ein "Balkendiagram" ausgeben.
- Die zahlen werden Rechtbündig dargestellt, dies wird durch die Funktion "FormatedNumber( string, n )" ermöglicht.

BlitzMax: [AUSKLAPPEN]
'
'
'
SuperStrict

'pfad "erfragen"
Local path:String = RequestFile( "Open", "txt" )
If Not path RuntimeError( "file not found!" )

'datei laden
Local file:TStream = ReadFile( path )
If Not file RuntimeError( "file not found!" )

'character-count array
Local characters:Int[ 256 ]

'Zeichen zaehlen
While Not Eof( file )
Local line:String = ReadLine( file )

For Local pos:Int = 0 Until line.length
characters[ line[pos] ] :+ 1
Next
Wend

'Ausgeben
Print "---------"

For Local i:Int = 65 To 90
Local count:Int = characters[i] + characters[i+97-65]
Print Chr(i) + ": " + formatedNumber(count, 5) + " |" + AsciBar( count )
Next

Print "---------"

'Datei schliessen
CloseFile( file )

'AsciBar Funktion
Function AsciBar:String( c:Int )
Local str:String = ""
For Local i:Int = 0 Until c
str :+ "-"
Next
Return str
EndFunction

'formated number Funktion
Function formatedNumber:String( number:Int, size:Int = 4 )
Local str:String = String( number )
For Local i:Int = 0 Until size - str.length
str = " " + str
Next
Return str
EndFunction


Und die Ausgabe des Textes "Hello World!" (mit "Diagramm" :D )
Code: [AUSKLAPPEN]
---------
A:     0 |
B:     0 |
C:     0 |
D:     1 |-
E:     1 |-
F:     0 |
G:     0 |
H:     1 |-
I:     0 |
J:     0 |
K:     0 |
L:     3 |---
M:     0 |
N:     0 |
O:     2 |--
P:     0 |
Q:     0 |
R:     1 |-
S:     0 |
T:     0 |
U:     0 |
V:     0 |
W:     1 |-
X:     0 |
Y:     0 |
Z:     0 |
---------

mpmxyz

BeitragDo, Jan 06, 2011 17:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich bewerbe mich hiermit für den Sonderpreis des längsten Codes! Laughing
BlitzMax: [AUSKLAPPEN]
SuperStrict
Framework brl.Blitz
Import brl.System
Import brl.StandardIO
Import brl.Map
'Die vier Schritte einer objektorientierten Lösung:
Local text:String=LoadText(RequestFile("Textdatei zum Auslesen auswählen","txt")) '1. die Eingabe heranschaffen (eine Datei laden)
Local stats:TCharStats=New TCharStats '2. ein Objekt zum Lösen des Problems erstellen
'stats.ProcessString(text,MODE_CASE_SENSITIVE|MODE_ALL_CHARS) '
stats.ProcessString(text) '3. das Problem lösen lassen
Print stats.toString() '4. das Ergebnis zurückgeben
'Hier kommen ein paar Konstanten zur Anpassung der Statistik:
Const MODE_CASE_INSENSITIVE:Int=%1 '
Const MODE_CASE_SENSITIVE:Int=%0 '
'
Const MODE_LETTERS_ONLY:Int=%10 '
Const MODE_ALL_CHARS:Int=%00 '
'
Type TCharStats 'die Lösungsklasse zum BPS #1
Field chars:TMap=New TMap 'Hier sind die einzelnen Datensätze gespeichert.
'
Method ProcessString(text:String,mode:Int=MODE_CASE_INSENSITIVE|MODE_LETTERS_ONLY)
For Local i:Int=0 Until text.length 'Man gehe jedes Zeichen durch...
ProcessChar(text[i..i+1],mode) '...und gebe die Arbeit an jemand anderes weiter.
Next '
EndMethod '
Method ProcessChar(char:String,mode:Int=MODE_CASE_INSENSITIVE|MODE_LETTERS_ONLY)'
Local upperChar:String=char.toUpper() '
If (mode & MODE_CASE_INSENSITIVE) 'Hier kommt ein bisschen Aufblähcode durch zusätzliche Features.
char=upperChar '
EndIf '
If (mode & MODE_LETTERS_ONLY) '
If upperChar<"A" Or upperChar>"Z" '
Return '
EndIf '
EndIf '
Local testChar:TChar=TChar.Create(char) 'Das besondere an dieser Klasse: Sie kann unter bestimmten Umständen
Local charObj:TChar=TChar(chars.ValueForKey(testChar)) '(z.B. bei dem Text "sssssssssssssssssssssssssssssssssssssssssssssss")
If charObj=Null 'speichereffizient sein.
charObj=testChar '(Nur dumm, dass durch den verwendeten Ansatz schnell )
chars.Insert(charObj,charObj) '(ein vielfaches an Speicher benötigt wird... Wink )
EndIf '
charObj.IncrementCounter() 'Dieser Methode ist das Zählen zu umständlich.
'Diese Arbeit wird daher weitergegeben.
EndMethod '
Method toString:String() 'Für eine schön formatierte Ausgabe sorgt diese Methode.
Local text:String '
For Local charObj:TChar=EachIn(chars.Values()) 'Jedes Zeichen wird beachtet!
text:+charObj.toString()+"~r~n" 'Es muss aber auch etwas dafür machen. (->Arbeit wurde weitergegeben.)
Next '
Return text '
EndMethod '
EndType '
'
Type TChar '
Field char:String 'Damit das Zeichen weiß, was es ist, merkt es sich das.
Field count:Long=0 'Hier wird es auch mit großen Texten keine Probleme geben.
'ganz vorbildlich:
Function Create:TChar(char:String) 'Es gibt hier sowohl eine Create-Funktion...
Return New TChar.Init(char) '
EndFunction '
Method Init:TChar(char:String) '...als auch eine Init-Methode zum Erstellen des Objektes.
Self.char=char '
Return Self '
EndMethod '
Method IncrementCounter() 'Pfui! Was hat hier Mathematik in diesem Code zu suchen?
Self.count:+1 '
EndMethod '
Method Compare:Int(other:Object) 'Damit kann man die Objekte auch als Schlüssel in den Bäumen nutzen.
Return -other.Compare(Self.char) '
EndMethod '
Method toString:String() 'Hier wird die artgerechte Ausgabe des Zeichens ermöglicht.
If char=" " '
Return "~q ~q: "+count '
ElseIf char>" " '
Return char+": "+count '
Else '
Return "["+char[0]+"]: "+count '
EndIf '
EndMethod '
EndType '

Hier ist außerdem der Kandidat für den kleinsten und unübersichtlichsten Code, welcher genau das gleiche macht:
BlitzMax: [AUSKLAPPEN]
t$=Lower(LoadText(RequestFile("")))
For i="a"[0] To "z"[0]
Print Chr(i)+": "+(Len(t)-Len(t.Replace(Chr(i),"")))
Next

Hier wurde einfach ein bisschen mit der Ersetzfunktion herumgetrickst.
Zu Empfehlen ist dieser Code aber aus mehreren Gründen, darunter auch die Notwendigkeit eines guten Programmierstiles, nicht.
mfG
mpmxyz
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group