Betűstatisztika

Fórumok

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ások

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

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.

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;
}

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?"

Hello!

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

Petya

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

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

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"