Betűstatisztika

 ( sapi | 2008. február 21., csütörtök - 20:00 )

Sziasztok!

Hogy kellene egy olyan progit írni c-ben ami megszámolja egy adott input szövegfájl(txt vagy vmilyen szövegfájl) betűit és kilistázza azokat pl:A betű előfordul 15 , B előfordul 5.És emelett statisztikát is csionál hogy hány betű volta szövegben és azt is kiiratja hogy hány százaléka a a betűk előfordulása az egész szövegben!

A nagy gondom az itt hogy nem tudom hogy a kettős betűkkel mit is csináljak !

De egy egész program részlet érdekelne!

mert nem tudom megcsinálni:-)

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Kész statisztika nem jó?
Szerk: bizonyos méret fölött az eredmény eléggé állandó.

Debian testing KDE amd64
MSI K8N-Neo-4, Athlon64 3800+, Leadtek 6600GT

sajna nekem nem jó aegy kész stat nekem egy program kellene

Az a baj a kettős betűkkel, hogy honnan tudja a program, hogy a szóban az s és a z külön áll, vagy sz/zs akar lenni? A többi annyira nem problémás, y nem nagyon szokott önmagában állni, tehát lehet olyat csinálni, hogy ha a g/t/n/l betűt y követi, akkor kettős, és együtt kell értelmezni...
Viszont a z/s -sel nem hiszem, hogy lehetne kezdeni valamit

Épeszű tanár nem adna fel olyan feladatot, hogy értelmezze a kettős betűket. Mellesleg lehetetlen is megoldani (több tízezer helyes magyar szót kellene ismernie betűk alapján a programnak). Szerintem a feladat csak úgy szólhat, hogy karaktereket kell megállapítani. Vagy a program fittyet hány a helyesírásra és a pácsót nem nem pác sóként értelmezi. :)

A „kettős betűk” két betűből állnak, egy hangot jelölnek.

de baj hogy betűről van szó mellesleg nézd vörösmarty nevét t és y és itt két betű de a tyúk nál már egy betű

valaki próbáljon már meg beírni egy progit c-be

En anno C++ -ban irtam meg ilyesmit stl-el gyakorlásként.

Ha az stl map multimap featúráit kiváltod,lesz egy alap verziód.
Ez a prg némi plusz infot is kiír az előfordulási gyakoriságon kívül,de az ne zavarjon.

Íme:

#include<iostream>
#include<map>
#include<ctype.h>
#include<math.h>

using namespace std;

int main(void)
{
char ch;
int count=0;
map<char,int> freqmap;
multimap<int,char> rmap;

while( (cin >> ch) )
  {
    if (isalnum(ch) )
      {
        ch = tolower(ch);
	++count;
        ++(freqmap[ch]);
	//cout << ch << " " << freqmap[ch];
      }
  }

map<char,int>::const_iterator it;
for (it=freqmap.begin();it != freqmap.end(); ++it )
  {
	rmap.insert ( pair< int , char >( (*it).second , (*it).first )) ;
  }

double sumpercent=0;
map<int,char>::const_reverse_iterator rit=rmap.rbegin();
  do
  {
	sumpercent += 100.0*(double)(*rit).first/((double)count);
	cout << (*rit).second << " " << (*rit).first<< " "<< 100.0*(double)(*rit).first/((double)count) << " " << -log2((double)(*rit).first/((double)count)) << " " << ceil(-log2((double)(*rit).first/((double)count))) << " " <<sumpercent <<endl;
	++rit;
  }
while ( rit != rmap.rend() ) ;

return 0;
}

"valaki próbáljon már meg beírni egy progit c-be".

Ja, követelődzeni, azt lehet!

Ezen kar porogni, ui. nem lehet megoldani.
(Meg lehet oldani, ha megvan a magyar nyelvben az osszes olyan elofordulasa a kettos betuknek latszo betukombinacioknak amik nem kettos betuk - es gondolom ez nincs meg.)
==
`Have some wine,' the March Hare said in an encouraging tone.
Alice looked all round the table, but there was nothing on it but tea.

vlmilyen dictel erdeemess probalkoni szerintem... amiben benne van az oszes szo. es ki van egeszitve evvel kapcsolatos informciokkal. Amugy maga a project az miaz?

### ()__))____________)~~~ ###
#"It's nice to be important, but it's more important to be nice"
#"Ha én veletek, ki ellenetek?"

"Amugy maga a project az miaz?"

Szerinted? prog 1 házi feladat :)

> Ezen kar porogni, ui. nem lehet megoldani.

Lehet. De az is lehet, hogy érdemes lenne a szöveg szavait elválasztani, és azután megszámolni a (kettős)betűket.

Es ha elvalasztom az miben segit a Vorosmartyn? Semmiben.
==
`Have some wine,' the March Hare said in an encouraging tone.
Alice looked all round the table, but there was nothing on it but tea.

> Es ha elvalasztom az miben segit a Vorosmartyn? Semmiben.

Vörösmarthy

Nem th, csak t.


It doesn't matter if you like my song as long as you can hear me sing

> Nem th, csak t.

Akkor ez nem jött be. Egyéb esetekben viszont jobb eredményt ad, mint a szimpla betűszámolgatás. Pld az "asszony"-ban szerintem két "sz"-t kellene számolni, a "késszár"-ban pedig egy "sz"-t ami az elválasztott alakokból jobban látszik.

Hello!

Ha segítséget, ötletet kérsz a kötelező programodhoz, segítünk szívesen, de nem fogjuk megírni helyetted.

Petya

Egy ötlet: Előveszed a Kernighan-Ritchie-t, és lapozgatod az eleje táján. Egy óra alatt meglesz a program. Ezért kaptad a feladatot.
--
CCC3

Eloszor tekintsunk el a kettos betuktol.

Nagyon egyszeru: fogsz egy tombot, ami int-eket tarol, es a betukkel indexeled (vagy azoknak vmilyen azonositojaval, pl hogy hanyadik az ABC-ben). Egyesevel olvasod a karaktereket, minden egyes olvasott karakternel megnoveled a megfelelo tombelemet. Ezt addig csinalod, amig van a file-ban olvasatlan karakter.
Ha elfogyott, akkor a tomb tartalmat felhasznalod a statisztika elkeszitesere (ha pl %-ban kell, akkor leosztod az osszes karakterrel (tomb osszege), stb..)

Kettos betuk: nyilvantartod az olvasasi ciklusban az epp olvasott karakteren kivul az _elozo_ olvasott karaktert. Felveszel par plusz valtozot, es ha a mostani betu 'z', az elozo 's', akkor megnoveled, az sz valtozojanak erteket. Ez gyakorlatilag 1-1 plusz if-et jelent kettos betunkent. (megszamolhatod az osszes karakterparost is, csak nagyobb tomb kell)

kodban kb igy nezne ki: (nem tesztelem, legalabb a szintaktikai hibakat javitsd ki, ha 0-rol nem megy :) )

#include <stdio.h>
#include <stdlib.h>

int main(int argc,char **argv)
{
  FILE *f=NULL;
  int betuk[256]; // az osszes karaktert megszamolom.. igy nem csak a betukrol lehet statisztikat mondani, hanem pl a szamokrol is
  int sz=0,zs=0,cs=0,ty=0,gy=0;
  int i,akt,elozo=-1; // akt a mostani karakter.. char nem eleg (EOF).. -1 nem ertelmes karakter
  
  f=fopen(argv[1],"rt"); // hibakezeles..
  
  for(i=0;i<256;i++)
    betuk[i]=0;
  
  while((akt=fgetc(f))!=EOF)
  {
    betuk[akt]++; // itt noveljuk..
    if((elozo=='s')&&(akt=='z')) sz++;
    if((elozo=='z')&&(akt=='s')) zs++;
    if((elozo=='c')&&(akt=='s')) cs++;
    if((elozo=='g')&&(akt=='y')) gy++;
    if((elozo=='t')&&(akt=='y')) ty++;
    elozo=akt;
  }
  fclose(f);
  
  printf("%d darab sz betu volt\n",sz);
  // stb..
  
  printf("\nkisbetuk statisztikaja:\n");
  for(i='a';i<='z';i++)
    printf("  %c: %4d\n",i,betuk[i]);
  
  printf("\nnagybetuk statisztikaja:\n");
  for(i='A';i<='Z';i++)
    printf("  %c: %4d\n",i,betuk[i]);
  
  printf("\nszamok statisztikaja:\n");
  for(i='0';i<='9';i++)
    printf("  %c: %4d\n",i,betuk[i]);
  // stb.. persze egybe is lehet venni a kis- es nagybetuket..
}

Lehet nagybetuket, kisbetuket, szamokat szamolni, stb.. innen mar konnyen megy
Ertelmezes kerdese ugyan, de esetleg kiiraskor az s betuk szamabol es a z betuk szamabol kivonhatod az sz-ek es zs-k szamat.. az if-es feltetelekbe betehetsz toupper-t (jelenleg nagy kettos betuket nem szamol).. plusz millionyi aprosag (hibakezeles), hogy maradjon meg vele munka.. ezek nagy resze ertelmezes kerdese..
----
Amikor a valtozas szele fuj, van, aki szelfogot epit, es van, aki szelmalmot. - kinai kozmondas
honlap készítés

Pedagógiailag nem jó, amit csinálsz.

És mi van a cirill betűkkel, UTF-8 kódolással, stb., hogy legalább kicsit is érdekesebb legyen a dolog?

--
CCC3

UTF-re gondoltam kozben, de tul bonyolult lenne igy elsore (es nem lenne atlathato a sok bitvadaszattol egy cseppet sem). Mindenesetre atalakithato.

Hogy pedagogiailag jo-e, az mas kerdes. Tapasztalatom szerint igen. A feladatot nem oldottam meg teljes mertekben, es az elejen eleg pontosan elmagyaraztam a mukodeset. Ha valaki nem szokott meg hozza a programozashoz, nem biztos, hogy ki tudja talalni az algoritmust magatol. Ha viszont ugyanazt az elvet 5-6 helyen mar latta, akkor legkozelebb mar gondolni fog erre is. Nem olyan szorakoztato persze, mint egyedul rajonni, de ezt mar feladta azzal, hogy kodot kert egy forumon. 1:1-ben meg nem tudja leadni, a hozzaszolas vegen emlitett problemak miatt, es az mar sokat segit a megertesben, ha atgyurja a kodot. (En is szoktam php.net-rol, JS kodgyujtemenyekrol kodot masolni, mint ahogy elore elkeszitett lib-eket is hasznlok. Sokszor at kell ugyan alakitani, de legalabb nem elolrol kell kezdeni.)
----
Amikor a valtozas szele fuj, van, aki szelfogot epit, es van, aki szelmalmot. - kinai kozmondas
honlap készítés

A pedagógiai cél, hogy a tanuló önállóan írjon egy egyszerű programot. Lehet, hogy ehhez elő kell vennie egy C tankönyvet. Ez is pedagógiai cél.
--
CCC3

No jó, hogy ne csak kötekedjek:

Mások is, és a programodban te is betűkről (kis- és nagybetűkről) és karakterekről írtok. Valójában, amit számoltok, azok nem betűk, hanem byteok. Egy png kép bytejait ugyanígy lehetne számolgatni (csak nincs értelme). 10 évvel ezelőtt még mindegy volt, hogy betű vagy byte.

Mostanra azonban a számítógépeken különvált a betű és a byte fogalma. Byte csak 256 féle van, betű viszont sokkal több. Gondolj csak a latin, cirill, görög, örmény, héber betűkre (ezek mind különböznek), vagy az ázsiai nyelvek írásjeleire. A mostani számítógépek a szövegeket (ezt is, amit itt írok) UTF-8 kódolásban tárolják. Ez azt jelenti, hogy a byteszámolgatós programod nem fogja megtalálni már az egyszerű 'á' betűket sem. Hoppá.

Ha már informatika tantárgy, akkor jó volna megemlíteni, hogy wchar_t, meg UTF-8.

Egy kis szemléltetés:
ТЕРМИНЫ И УСЛОВИЯ КОПИРОВАНИЯ, РАСПРОСТРАНЕНИЯ И МОДИФИКАЦИИ
(ez a GPL alcíme oroszul)

--
CCC3

A leheto legegyszerubb megoldas (semmi kettosbetu):

#include <stdio.h>

int main( int argc, char* argv[] )
{
   int   i;
   FILE* f;
   int count[256];

   if( argc < 2 ) {
	   printf("hiba: adja meg a fajl nevet\n");
	   return 1;
   }

   for(i=0; i<256; i++)
   {
      count[i] = 0;
   }

   f = fopen(argv[1], "rt");
   if( f==NULL ) {
	   printf("hiba: a fajlt em lehet megnyitni");
	   return 2;
   }

   while(1)
   {
      int c = fgetc(f);
      if( c==EOF )
         break;

      if( c<0 || c>255 ) {
		  printf("hiba: nem vart betu");
		  return 3;
	  }

	  count[c] += 1;
   }

   fclose(f);

   printf("gyakorisagok:\n");
   for(i=0; i<256; i++)
   {
      if( count[i] < 1 )
         continue;

      printf("'%c': %d-szer\n", i, count[i]);
   }

   return 0;
}

hehe most latom megeloztek...

Én elsőre Pythonban úgy csinálnám, hogy egy szótárba venném fel a betű-előfordulás párosokat. Minden karakterre megnézném, hogy szerepel-e már a szótárban, ha igen növelem az hozzátartózó számot, ha nem akkor bővítem a szótárt az új betűvel. Unicode kompatibilis a megoldás elvileg :)
Valami hasonlót biztos meg lehet valósítani C/C++-ban is.
--
"my mind had skipped town and left me behind to pay the rent"