Permalänk
Medlem

c# frekvensuppgift, hjälp

Man ska skriva ett program som läser in en textfil och sedan analyserar frekvensen av siffrorna som finns i filen. Programmet ska skriva ut hur många gånger varje siffra förekommer.
Programmet ska innehålla metoden AnalyseraFrekvens() som ska ta ett filnamn som parameter,
öppna filen och analysera innehållet. Om filen gick att öppna ska funktionen returnera värdet true,
annars värdet false.Om filen inte gick att öppna ska programmet meddela användaren. Om filen går
att öppna skall programmet anropa en ny metod VisaFrekvens() som tar frekvenserna som
parametrar och skriver ut dessa i svarsrutan.

private void Open_Click(object sender, EventArgs e) { text = txtInläsning.Text; if (!File.Exists(text)) { txtUtdata.Text = "File does not exist."; return; } StreamReader sr = new StreamReader(textBox1.Text); textBox2.Text = sr.ReadToEnd();

Längre har jag inte kommit, någon som kan hjälpa ?

Permalänk
Medlem

glömde säga att siffrorna i filen är sorterade efter rad:
ex:
1
3
5
6
1

Permalänk
Hedersmedlem

Har du funderat något på hur AnalyseraFrekvens och VisaFrekvens ska fungera? Börja med det du tycker känns lättast. Bryt ner problemet i mindre problem.

Permalänk
Medlem
Skrivet av big3ljo:

Man ska skriva ett program som läser in en textfil och sedan analyserar frekvensen av siffrorna som finns i filen. Programmet ska skriva ut hur många gånger varje siffra förekommer.
Programmet ska innehålla metoden AnalyseraFrekvens() som ska ta ett filnamn som parameter,
öppna filen och analysera innehållet. Om filen gick att öppna ska funktionen returnera värdet true,
annars värdet false.Om filen inte gick att öppna ska programmet meddela användaren. Om filen går
att öppna skall programmet anropa en ny metod VisaFrekvens() som tar frekvenserna som
parametrar och skriver ut dessa i svarsrutan.

private void Open_Click(object sender, EventArgs e) { text = txtInläsning.Text; if (!File.Exists(text)) { txtUtdata.Text = "File does not exist."; return; } StreamReader sr = new StreamReader(textBox1.Text); textBox2.Text = sr.ReadToEnd();

Längre har jag inte kommit, någon som kan hjälpa ?

Nästa steg är att gå igenom texten som du hämtade in, tecken för tecken. Sen sparar du hur många av respektive tecken det finns.

Visa signatur

ηλί, ηλί, λαμά σαβαχθανί!?

Permalänk
Medlem

static void Main() { // Verkar ju jobbigt att ta en outvariabel här, // tycker det var väldigt oklart i given uppgift hur det var tänkt att returnen var tänkt att användas var vaskaMig = AnalyseraFrekvens(@C:\Temp\a.txt); } static bool AnalyseraFrekvens(string fname) { try { int vask; // Inte optimalt med TryParsen för att sortera bort eventuellt skräp från inputfil, nån kanske har en finare idé? var ints = System.IO.File.ReadAllLines(fname).Where(s => int.TryParse(s,out vask)) .Select(int.Parse).OrderBy(c => c); var result = ints.Distinct() .Aggregate(String.Empty, (c, i) => c + String.Format("{0}: {1}\r\n", i.ToString().PadRight(ints.Max().ToString().Length), ints.Count(s => s == i))); // Här skulle vi tydligen printa i en annan funktion VisaFrekvens(result); return true; } catch (Exception ex) { Console.WriteLine("Fail: " + ex.Message); return false; } } static void VisaFrekvens(string res) { Console.WriteLine("=== Result ==="); Console.WriteLine(res); }

Stör mig dock på att jag inte kommer på nån bra lösning för att slippa köra dubbla int-parse vid inläsning...
Blev nog lite overkill med att acceptera mer än 0-9 och rensa övrigt 'skräp' från inputfilen

Permalänk
Avstängd

Jag blir ledsen i ögat av att se kod som den ovan så här kommer en bättre

var text = @1 3 5 6 1; var textLines = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); //Du kan byta utan koden ovanför till File.ReadAllLines() var sortedValues = textLines .Select(int.Parse) .GroupBy(i => i) .OrderByDescending(g => g.Count()) .Select(g => g.First());

Inget krav på att man ska tolka det som värden heller ser jag

var sortedValues = textLines .GroupBy(l => l) .OrderByDescending(g => g.Count()) .Select(g => g.First());

Visa signatur
Permalänk
Medlem

på min tid skulle man skriva programmet så att den kunde läsa in en "oändligt stor fil", annars fick man minsann poängavdrag!
(fast det kanske är jag som är för gammal... )

något i stil med följande alltså:

int[] siffror = new int[10]; while(det fortfarande finns siffror kvar att läsa) { int tal = läs in talet; siffror[tal]++; }

detta förutsätter givetvis att man läser endast en siffra åt gången. dvs 10 läses som 1 sedan 0.

Visa signatur

as far as we can tell, the massacre went well...

Permalänk
Medlem
Skrivet av CyberVillain:

Jag blir ledsen i ögat av att se kod som den ovan så här kommer en bättre

var text = @1 3 5 6 1; var textLines = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); //Du kan byta utan koden ovanför till File.ReadAllLines() var sortedValues = textLines .Select(int.Parse) .GroupBy(i => i) .OrderByDescending(g => g.Count()) .Select(g => g.First());

Inget krav på att man ska tolka det som värden heller ser jag

var sortedValues = textLines .GroupBy(l => l) .OrderByDescending(g => g.Count()) .Select(g => g.First());

Kul med feedback, trist med din spydiga stil.
Det är kod som _din_ som får mig att må illa

* Det känns helt onödig/fel i min mening att använda sig av en sträng när du vet att datat ska vara heltal. Sjukt tröttsamt med folk som lagrar allt som strängar och helst gärna som varchar(max) i databasen.
* Som en bonus så får vi en grundläggande indatavalidering / 'trimning' genom att köra intparse. Lita aldrig på indata.
* Du missade helt och hållet att följa det efterfrågade flödet (olika funktioner etc)
* Du skriver inte ut något resultat

Sist med inte minst så producerar din lösning inte ens ett korrekt resultat, tar följande sträng som exempel

7 8 r 7 7 9 4 8 e 4 2e

=== Result === 4: 2 7: 3 8: 2 9: 1 7 8 r 9 4 e 4 2e

Som vi ser så rensar jag bort skräpet och summerar det som vi kan kalla för vettig indata.
Ditt resultat är ordnat efter antal förekomster (därav 7 föst, sen 8, sen resten i en random blandning)..
Det festliga eftersom du behandlar datat som strängar är att 4:an med ett space innan räknas separat från den andra, därav, parsa skiten som int!

Därför anser jag din första verison med en intparse bättre då den iaf miserabelt failar i en exception.

Ändrar vi din fetmarkerade 'first()' till en 'count()' iställlet så kommer vi lite närmre:

3 2 1 1 1 1 1 1 1

Problemet är att vi fortfarande inte vet _vilken_ siffra/tecken som hör ihop med vilken frekvens.
Jag skrev ut ditt resultat som:

sortedValues.ToList().ForEach(x => Console.WriteLine(x));

(återkom gärna med en lösning på det, vet att min fina aggregate kanske inte är det bästa )

Slutsats? Se till att iaf göra _rätt_ om du ska läxa upp någon

Till sist så var hela skiten skriven med glimten i ögat, då en person som inte ens löser en sån här uppgift öht. knappast hade kunnat redovisa min lösning då h*n hade fått svårt att förklara hur linq/lambda fungerar...

Permalänk
Medlem
Skrivet av BasseBaba:

Kul med feedback, trist med din spydiga stil.
Det är kod som _din_ som får mig att må illa

* Det känns helt onödig/fel i min mening att använda sig av en sträng när du vet att datat ska vara heltal. Sjukt tröttsamt med folk som lagrar allt som strängar och helst gärna som varchar(max) i databasen.
* Som en bonus så får vi en grundläggande indatavalidering / 'trimning' genom att köra intparse. Lita aldrig på indata.
* Du missade helt och hållet att följa det efterfrågade flödet (olika funktioner etc)
* Du skriver inte ut något resultat

Sist med inte minst så producerar din lösning inte ens ett korrekt resultat, tar följande sträng som exempel

7 8 r 7 7 9 4 8 e 4 2e

=== Result === 4: 2 7: 3 8: 2 9: 1 7 8 r 9 4 e 4 2e

Som vi ser så rensar jag bort skräpet och summerar det som vi kan kalla för vettig indata.
Ditt resultat är ordnat efter antal förekomster (därav 7 föst, sen 8, sen resten i en random blandning)..
Det festliga eftersom du behandlar datat som strängar är att 4:an med ett space innan räknas separat från den andra, därav, parsa skiten som int!

Därför anser jag din första verison med en intparse bättre då den iaf miserabelt failar i en exception.

Ändrar vi din fetmarkerade 'first()' till en 'count()' iställlet så kommer vi lite närmre:

3 2 1 1 1 1 1 1 1

Problemet är att vi fortfarande inte vet _vilken_ siffra/tecken som hör ihop med vilken frekvens.
Jag skrev ut ditt resultat som:

sortedValues.ToList().ForEach(x => Console.WriteLine(x));

(återkom gärna med en lösning på det, vet att min fina aggregate kanske inte är det bästa )

Slutsats? Se till att iaf göra _rätt_ om du ska läxa upp någon

Till sist så var hela skiten skriven med glimten i ögat, då en person som inte ens löser en sån här uppgift öht. knappast hade kunnat redovisa min lösning då h*n hade fått svårt att förklara hur linq/lambda fungerar...

Ni är ju lika kassa båda två! Det är inte ints ni ska hitta, det är siffror. 42 = fyra tvåa. Iterera nu över hela filen tecken för tecken istället för att splittra på radslut och allt annat ni gör, och medge att det är jag som har rätt

Skickades från m.sweclockers.com

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Ni är ju lika kassa båda två! Det är inte ints ni ska hitta, det är siffror. 42 = fyra tvåa. Iterera nu över hela filen tecken för tecken istället för att splittra på radslut och allt annat ni gör, och medge att det är jag som har rätt

Skickades från m.sweclockers.com

Haha, japp, jag medger att jag har fel!
Dock så skriver han ju i sitt andra inlägg att indatat är newline-formaterat
Så vi kan nog komma övrens om att vi allihopa failar "Programmering A" eller vad detta nu är

Permalänk
Avstängd

Du får ursäkta, var lite trött där på eftermiddagen på jobbet när jag skrev det. hade precis rättat en bugg som var skapad pga kod som ser ungefär ut som det jovnas skrev före ditt svar
Hur som helst,
Står ingenstans i kravet att den ska fungera med felaktig data, men om jag nu ska stödja det hade jag istället gjort

try { ... samma kod som ovan return true; } catch(Exception ex) { log.Error(ex, "Wrong inputdata"); return false; }

Att försöka laga trasig data brukar inte vara nån bra ide, bättre kasta fel till användaren.

jag hoppade över utdata delen ja... Nu ska vi kolla in ditt exempel som min inte stödjer (Jag tar bort den trasiga datan för jag antar att vi kan lita på den, om inte se ovan för hur vi löse det)... Tycker det ser rätt ut, står inte i kravet att den ska sortera på förekomst.

Men, men, om jag nu måste skriva om koden så den fungera med trasigt data hade jag gjort såhär

var text = @7 8 r 7 7 9 4 8 e 4 2e; var textLines = text.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); //Du kan byta utan koden ovanför till File.ReadAllLines() var valueParsed = 0; var sortedValues = textLines .Select(l => new {Succes = int.TryParse(l, out valueParsed), Value = valueParsed}) .Where(i => i.Succes) .GroupBy(i => i.Value) .OrderByDescending(g => g.Count()) .Select(g => g.First()); foreach(var value in sortedValues) { System.Diagnostics.Debug.WriteLine(value.Value); }

Om du sedan måste stödja in en andra sortering (Allså att 9 kommer före 8 om det finns lika många av dem i sekvensen) kan du lägga på en .OrderByDescending(i => i.Value) efter .Where(i => i.Succes)

Visa signatur
Permalänk
Avstängd

Jag skyller allt på krav.. Personen bakom krav borde få sparken

Visa signatur
Permalänk
Medlem
Skrivet av BasseBaba:

Haha, japp, jag medger att jag har fel!
Dock så skriver han ju i sitt andra inlägg att indatat är newline-formaterat
Så vi kan nog komma övrens om att vi allihopa failar "Programmering A" eller vad detta nu är

Jag failar på synundersökning, men problemet löses enkelt på en rad (i ett annat språk):

scala.io.Source.fromFile("testfile.txt").filter(_.isDigit).toList.groupBy(c => c).foreach(i => printf("%s: %d\n", i._1, i._2.size))

Nu ska jag boka tid hos en optiker.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av CyberVillain:

Jag skyller allt på krav.. Personen bakom krav borde få sparken

Skrivet av Teknocide:

Jag failar på synundersökning, men problemet löses enkelt på en rad (i ett annat språk):

scala.io.Source.fromFile("testfile.txt").filter(_.isDigit).toList.groupBy(c => c).foreach(i => printf("%s: %d\n", i._1, i._2.size))

Nu ska jag boka tid hos en optiker.

File.ReadAllLines(@C:\Temp\a.txt).Where(x => x.All(Char.IsNumber)).GroupBy(x => x).ToList().ForEach(x => Console.WriteLine(String.Format("{0}: {1}",x.First(), x.Count())));

Går säkert förbättra
Förstår fortfarande inte hur Cybervillain's svar ska producera ett resultat som visar hur många gånger varje siffra förekommer.

Permalänk
Medlem
Skrivet av CyberVillain:

Jag skyller allt på krav.. Personen bakom krav borde få sparken

*asg* Du gjorde just min dag. Låt mig adoptera dom meningarna som nytt talesätt. xD
Ledsen för OT men det inlägget var bara så.. Rätt!

Visa signatur

WS: ASUS P7P55D/i5-750, Hydro H50, XFX6950/2GB, Intel X25-V/2Tb lagring, Corsair VX-550
Server: ASUS, AMD Athlon64 X2 6000+ Scyte Ninja, NVidia GS8400Silent, 2Gb ram, ~4Tb SATA, 500W, CM Stileo500 (tyst)
"-Sometimes all that is needed is a high five. In the face. With a chair!"

Permalänk
Medlem
Skrivet av CyberVillain:

Du får ursäkta, var lite trött där på eftermiddagen på jobbet när jag skrev det. hade precis rättat en bugg som var skapad pga kod som ser ungefär ut som det jovnas skrev före ditt svar
Hur som helst,
Står ingenstans i kravet att den ska fungera med felaktig data, men om jag nu ska stödja det hade jag istället gjort
koooooooooooood

Skrivet av BasseBaba:

File.ReadAllLines(@C:\Temp\a.txt).Where(x => x.All(Char.IsNumber)).GroupBy(x => x).ToList().ForEach(x => Console.WriteLine(String.Format("{0}: {1}",x.First(), x.Count())));

Går säkert förbättra
Förstår fortfarande inte hur Cybervillain's svar ska producera ett resultat som visar hur många gånger varje siffra förekommer.

Filtrera bort de tecken som inte är siffror dåe! Flatmap that shit.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Avstängd
Skrivet av BasseBaba:


Förstår fortfarande inte hur Cybervillain's svar ska producera ett resultat som visar hur många gånger varje siffra förekommer.

var sortedValues = textLines .Select(l => new {Succes = int.TryParse(l, out valueParsed), Value = valueParsed}) //Projicerar alla rader till en anonym typ .Where(i => i.Succes) //Hämtar ut de som är siffror .GroupBy(i => i.Value) //Grupperar på siffran .OrderByDescending(g => g.Count()) //Räknar hur många items det är i varje grupp och sorterar fallande .Select(g => g.First()); //Eftersom det är samma värde i alla inom en grupp väljer jag första..

Det var väll inte så svårt?

edit: ops, jag missade det lilla kravet att de ville se hur många ggr varje siffra repeterats. trodde det var siffran man skulle skriva ut

Visa signatur
Permalänk
Avstängd

.Where(x => x.All(Char.IsNumber)) den var snygg

Visa signatur
Permalänk
Avstängd

Ett tips till nästa gång är att använda http://specflow.org/
Kraven blir mycket mer tydliga då, samt att det är lätt att red / green testa.. BDD for the win

Visa signatur