View Full Version : [Vari] Contest 19: Full Text Search(e non solo).
È penalizzante per chi usa linguaggi di basso livello...
Vincenzo1968
02-02-2013, 17:04
Proposta che mi è venuta in mente così, tanto per:
1) Perché non diamo un punteggio alle implementazioni, che tenga conto della lunghezza del codice e del tempo impiegato?
Ad esempio una formula banale potrebbe essere:
[ 1/(tempo * bytes sorgente) ] * 100
Questa chiaramente è molto semplice, ma si potrebbero dare dei pesi e quindi decidere se è più importante il tempo impiegato o il numero di bytes del codice sorgente.
2) si potrebbe mettere una classifica in prima pagina con i punteggi calcolati come sopra
A me, visto che ho deciso di utilizzare Ruby, "viene allo scendere", come si suol dire dalle mie parti(in italiano: "viene in discesa") :D
Per me come volete voi ma, come dice kwb, penalizza gli utilizzatori di C, C++, Java, Assembly...
Ah penalizza Vicius... Allora si!!! :D
Vincenzo1968
02-02-2013, 17:23
Ho aggiustato la mia versione per il punto B.2
Adesso la ricerca delle parole è più accurata:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <stdint.h>
//#include <time.h>
//#include <ctype.h>
//#define BLOCK_SIZE 4096
#define BLOCK_SIZE 8192
typedef struct tagFindRec
{
unsigned long long countChars;
int countRows;
int maxRowLenght;
int countWords;
int maxWordLenght;
char szLongerWord[1000];
} FindRec;
void InitFindRec(FindRec *myFindRec);
void doCount(const char *szFileName, FindRec *myFindRec);
int isValidSeparatorChar(unsigned char c);
void PrintHelp(const char *szProg);
void ExtractFileName(const char *szPathName, char *szFileName);
/*---------------------------------------------------------------------------------------------------------------------*/
void InitFindRec(FindRec *myFindRec)
{
myFindRec->countChars = 0;
myFindRec->countRows = 0;
myFindRec->maxRowLenght = 0;
myFindRec->countWords = 0;
myFindRec->maxWordLenght = 0;
myFindRec->szLongerWord[0] = '\0';
}
void doCount(const char *szFileName, FindRec *myFindRec)
{
int x, k;
int index1;
int column;
int maxWordLenght;
uint64_t sizeData;
uint64_t howPages;
int blockLen;
int lastBlockLen;
FILE *fp;
char szWord[512];
unsigned char *myBlock = NULL;
szWord[0] = '0';
myBlock = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlock )
{
printf("Memoria insufficiente.\n");
return;
}
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s. Addio!\n", szFileName);
return;
}
#if __linux__ || __APPLE__
fseeko(fp, 0, SEEK_END);
sizeData = ftello(fp);
fseeko(fp, 0, SEEK_SET);
#else
_fseeki64(fp, 0, SEEK_END);
sizeData = _ftelli64(fp);
_fseeki64(fp, 0, SEEK_SET);
#endif
howPages = (sizeData / BLOCK_SIZE);
lastBlockLen = (int)(sizeData - howPages * BLOCK_SIZE);
x = 0;
blockLen = 0;
column = 0;
maxWordLenght = 0;
index1 = 0;
myFindRec->countChars = 0;
myFindRec->countWords = 0;
myFindRec->countRows = 0;
myFindRec->maxWordLenght = 0;
myFindRec->maxRowLenght = 0;
while ( blockLen = fread(myBlock, 1, BLOCK_SIZE, fp) )
{
myFindRec->countChars += blockLen;
while ( index1 < blockLen )
{
if ( myBlock[index1] == '\n' )
{
//row++;
myFindRec->countRows++;
if ( column > myFindRec->maxRowLenght )
myFindRec->maxRowLenght = column;
column = 1;
}
else
{
column++;
}
if ( !isValidSeparatorChar(myBlock[index1]) )
{
maxWordLenght++;
szWord[x++] = myBlock[index1];
}
else
{
if ( (x > 0) &&
(
(
(szWord[0] >= 'A' && szWord[0] <= 'Z') || (szWord[0] >= 'a' && szWord[0] <= 'z')
|| (szWord[0] >= 128 && szWord[0] <= 154) || (szWord[0] >= 224 && szWord[0] <= 237)
)
)
)
{
myFindRec->countWords++;
szWord[x] = '\0';
for ( k = 0; k < x; k++ )
{
if ( szWord[k] >= '0' && szWord[k] <= '9' )
{
szWord[k] = '\0';
index1 -= x - k;
x = k;
}
}
if ( maxWordLenght > myFindRec->maxWordLenght )
{
myFindRec->maxWordLenght = maxWordLenght;
//szWord[x] = '\0';
strcpy(myFindRec->szLongerWord, szWord);
}
}
x = 0;
maxWordLenght = 0;
}
index1++;
}
index1 = 0;
}
fclose(fp);
free(myBlock);
}
int isValidSeparatorChar(unsigned char c)
{
switch (c)
{
case '\t':
case '\n':
case '_':
case 32:
case 33:
case 34:
//case 35:
//case 36:
//case 156:
case 39:
case 40:
case 41:
case 44:
case 45:
case 46:
case 47:
case 58:
case 59:
case 60:
case 62:
case 63:
case 64:
case 91:
case 93:
case 123:
case 124:
case 125:
case 169:
case 170:
case 174:
case 175:
case 184:
case 237:
case 239:
case 240:
case 241:
case 243:
case 244:
case 245:
case 246:
case 247:
case 248:
case 249:
case 250:
case 251:
case 252:
case 253:
return 1;
default:
return 0;
}
return 0;
}
void PrintHelp(const char *szProg)
{
printf("\nUso: %s NomeFileInput\n", szProg);
}
void ExtractFileName(const char *szPathName, char *szFileName)
{
int k, i, x;
char c;
k = strlen(szPathName);
#ifdef __linux__ /* __gnu_linux__ */
c = '/';
#else
c = '\\';
#endif
i = k - 1;
while ( i >= 0 )
{
if ( szPathName[i] == c )
break;
i--;
}
i++;
x = 0;
for (;;)
{
szFileName[x] = szPathName[i];
if (szFileName[x] == '\0' || szFileName[x] == '.' )
break;
x++;
i++;
}
szFileName[x] = '\0';
}
int main(int argc, char* argv[])
{
FindRec myFindRec;
char szExeName[256];
//clock_t c_start, c_end;
//double TempoImpiegato;
if ( argc < 2 )
{
#ifdef __linux__
PrintHelp(argv[0]);
#else
ExtractFileName(argv[0], szExeName);
PrintHelp(szExeName);
#endif
printf("\nPremere INVIO per terminare.");
getc(stdin);
return -1;
}
InitFindRec(&myFindRec);
//c_start = clock();
doCount(argv[1], &myFindRec);
//c_end = clock();
//TempoImpiegato = (double)(c_end - c_start) / CLOCKS_PER_SEC;
//printf("Tempo impiegato per preelaborazione indice-> %5.5f secondi\n\n", TempoImpiegato);
printf("Il file \"%s\" contiene %d righe.\n", argv[1], myFindRec.countRows);
printf("La riga più lunga è lunga %d byte.\n", myFindRec.maxRowLenght - 1);
printf("Il file contiene %llu caratteri.\n", myFindRec.countChars);
printf("Nel file ci sono %d parole.\n", myFindRec.countWords);
printf("La parola più lunga è lunga %d byte.\n", myFindRec.maxWordLenght);
printf("Ecco una delle parole più lunghe: \"%s\".\n", myFindRec.szLongerWord);
printf("\n");
return 0;
}
Comunque ho notato che in alcuni dei file di input ci sono dei caratteri Unicode.
Potete verificarlo con questa versione del mio programma che è uguale alla precedente solo che oltre a riportare il conteggio delle parole crea il file "VerificaOutputB02.txt" inserendovi ogni parola trovata con lunghezza > 8 byte:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <stdint.h>
//#include <time.h>
//#include <ctype.h>
//#define BLOCK_SIZE 4096
#define BLOCK_SIZE 8192
typedef struct tagFindRec
{
unsigned long long countChars;
int countRows;
int maxRowLenght;
int countWords;
int maxWordLenght;
char szLongerWord[1000];
} FindRec;
void InitFindRec(FindRec *myFindRec);
void doCount(const char *szFileName, FindRec *myFindRec);
int isValidSeparatorChar(unsigned char c);
void PrintHelp(const char *szProg);
void ExtractFileName(const char *szPathName, char *szFileName);
/*---------------------------------------------------------------------------------------------------------------------*/
void InitFindRec(FindRec *myFindRec)
{
myFindRec->countChars = 0;
myFindRec->countRows = 0;
myFindRec->maxRowLenght = 0;
myFindRec->countWords = 0;
myFindRec->maxWordLenght = 0;
myFindRec->szLongerWord[0] = '\0';
}
void doCount(const char *szFileName, FindRec *myFindRec)
{
int x, k;
int index1;
int column;
int maxWordLenght;
uint64_t sizeData;
uint64_t howPages;
int blockLen;
int lastBlockLen;
FILE *fp;
FILE *fpOutput;
char szWord[512];
unsigned char *myBlock = NULL;
szWord[0] = '0';
myBlock = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlock )
{
printf("Memoria insufficiente.\n");
return;
}
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s. Addio!\n", szFileName);
return;
}
fpOutput = fopen("VerificaOutputB02.txt", "w");
if ( fpOutput == NULL )
{
printf("Errore nell'apertura del file \"OutputB02.txt\". Addio!\n");
return;
}
#if __linux__ || __APPLE__
fseeko(fp, 0, SEEK_END);
sizeData = ftello(fp);
fseeko(fp, 0, SEEK_SET);
#else
_fseeki64(fp, 0, SEEK_END);
sizeData = _ftelli64(fp);
_fseeki64(fp, 0, SEEK_SET);
#endif
howPages = (sizeData / BLOCK_SIZE);
lastBlockLen = (int)(sizeData - howPages * BLOCK_SIZE);
//myFindRec->countChars = (long long)sizeData;
//myFindRec->countChars = howPages * BLOCK_SIZE + lastBlockLen;
x = 0;
blockLen = 0;
column = 0;
//bFirst = 1;
maxWordLenght = 0;
index1 = 0;
myFindRec->countChars = 0;
myFindRec->countWords = 0;
myFindRec->countRows = 0;
myFindRec->maxWordLenght = 0;
myFindRec->maxRowLenght = 0;
while ( blockLen = fread(myBlock, 1, BLOCK_SIZE, fp) )
{
myFindRec->countChars += blockLen;
while ( index1 < blockLen )
{
if ( myBlock[index1] == '\n' )
{
//row++;
myFindRec->countRows++;
if ( column > myFindRec->maxRowLenght )
myFindRec->maxRowLenght = column;
column = 1;
}
else
{
column++;
}
if ( !isValidSeparatorChar(myBlock[index1]) )
{
maxWordLenght++;
szWord[x++] = myBlock[index1];
}
else
{
if ( (x > 0) &&
(
(
(szWord[0] >= 'A' && szWord[0] <= 'Z') || (szWord[0] >= 'a' && szWord[0] <= 'z')
|| (szWord[0] >= 128 && szWord[0] <= 154) || (szWord[0] >= 224 && szWord[0] <= 237)
)
)
)
{
myFindRec->countWords++;
szWord[x] = '\0';
for ( k = 0; k < x; k++ )
{
if ( szWord[k] >= '0' && szWord[k] <= '9' )
{
szWord[k] = '\0';
index1 -= x - k;
x = k;
}
}
for ( k = 0; k < x; k++ )
{
if ( (x > 8) && ((szWord[k] < 'A' || szWord[k] > 'Z') && (szWord[k] < 'a' || szWord[k] > 'z')) )
{
fputs(szWord, fpOutput);
fputc('\n', fpOutput);
}
}
if ( maxWordLenght > myFindRec->maxWordLenght )
{
myFindRec->maxWordLenght = maxWordLenght;
//szWord[x] = '\0';
strcpy(myFindRec->szLongerWord, szWord);
}
}
x = 0;
maxWordLenght = 0;
}
index1++;
}
index1 = 0;
}
fclose(fp);
fclose(fpOutput);
free(myBlock);
}
int isValidSeparatorChar(unsigned char c)
{
switch (c)
{
case '\t':
case '\n':
case '_':
case 32:
case 33:
case 34:
//case 35:
//case 36:
//case 156:
case 39:
case 40:
case 41:
case 44:
case 45:
case 46:
case 47:
case 58:
case 59:
case 60:
case 62:
case 63:
case 64:
case 91:
case 93:
case 123:
case 124:
case 125:
case 169:
case 170:
case 174:
case 175:
case 184:
case 237:
case 239:
case 240:
case 241:
case 243:
case 244:
case 245:
case 246:
case 247:
case 248:
case 249:
case 250:
case 251:
case 252:
case 253:
return 1;
default:
return 0;
}
return 0;
}
void PrintHelp(const char *szProg)
{
printf("\nUso: %s NomeFileInput\n", szProg);
}
void ExtractFileName(const char *szPathName, char *szFileName)
{
int k, i, x;
char c;
k = strlen(szPathName);
#ifdef __linux__ /* __gnu_linux__ */
c = '/';
#else
c = '\\';
#endif
i = k - 1;
while ( i >= 0 )
{
if ( szPathName[i] == c )
break;
i--;
}
i++;
x = 0;
for (;;)
{
szFileName[x] = szPathName[i];
if (szFileName[x] == '\0' || szFileName[x] == '.' )
break;
x++;
i++;
}
szFileName[x] = '\0';
}
int main(int argc, char* argv[])
{
FindRec myFindRec;
char szExeName[256];
//clock_t c_start, c_end;
//double TempoImpiegato;
if ( argc < 2 )
{
#ifdef __linux__
PrintHelp(argv[0]);
#else
ExtractFileName(argv[0], szExeName);
PrintHelp(szExeName);
#endif
printf("\nPremere INVIO per terminare.");
getc(stdin);
return -1;
}
InitFindRec(&myFindRec);
//c_start = clock();
doCount(argv[1], &myFindRec);
//c_end = clock();
//TempoImpiegato = (double)(c_end - c_start) / CLOCKS_PER_SEC;
//printf("Tempo impiegato per preelaborazione indice-> %5.5f secondi\n\n", TempoImpiegato);
printf("Il file \"%s\" contiene %d righe.\n", argv[1], myFindRec.countRows);
printf("La riga più lunga è lunga %d byte.\n", myFindRec.maxRowLenght - 1);
printf("Il file contiene %llu caratteri.\n", myFindRec.countChars);
printf("Nel file ci sono %d parole.\n", myFindRec.countWords);
printf("La parola più lunga è lunga %d byte.\n", myFindRec.maxWordLenght);
printf("Ecco una delle parole più lunghe: \"%s\".\n", myFindRec.szLongerWord);
printf("\n");
return 0;
}
In qualche parola, nel file prodotto in output, si può notare la presenza di strani caratteri dovuta, appunto, ai caratteri unicode presenti nei file originali.
Provatelo con file di piccole dimensioni, massimo 1 GiB.
Quindi delle due l'una:
-1: o modifichiamo il punto A facendo escludere, nel file di output, i caratteri unicode,
-2: o per il punto B(B.1 e B.2) gestiamo i caratteri unicode per la ricerca.
Io propendo per la seconda ipotesi. Voi che dite?
Vincenzo1968
02-02-2013, 21:35
Ce l'ho fatta!
http://img405.imageshack.us/img405/464/c19b01vittoriaassoluta.jpg
Adesso gestisco i caratteri unicode e ho financo ridotto i tempi di tre secondi!
:yeah: :winner: :yeah:
Vincenzo1968
02-02-2013, 21:40
Questo è il mio codice per il punto B.2:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <stdint.h>
//#include <time.h>
//#include <ctype.h>
//#define BLOCK_SIZE 4096
#define BLOCK_SIZE 8192
typedef struct tagFindRec
{
unsigned long long countChars;
int countRows;
int maxRowLenght;
int countWords;
int maxWordLenght;
char szLongerWord[1000];
} FindRec;
void InitFindRec(FindRec *myFindRec);
void doCount(const char *szFileName, FindRec *myFindRec);
int isValidSeparatorChar(unsigned char c);
int isValidWordChar(unsigned char c);
void PrintHelp(const char *szProg);
void ExtractFileName(const char *szPathName, char *szFileName);
/*---------------------------------------------------------------------------------------------------------------------*/
void InitFindRec(FindRec *myFindRec)
{
myFindRec->countChars = 0;
myFindRec->countRows = 0;
myFindRec->maxRowLenght = 0;
myFindRec->countWords = 0;
myFindRec->maxWordLenght = 0;
myFindRec->szLongerWord[0] = '\0';
}
void doCount(const char *szFileName, FindRec *myFindRec)
{
int x, k;
int index1;
int column;
int maxWordLenght;
uint64_t sizeData;
uint64_t howPages;
int blockLen;
int lastBlockLen;
FILE *fp;
char szWord[512];
unsigned char *myBlock = NULL;
szWord[0] = '0';
myBlock = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlock )
{
printf("Memoria insufficiente.\n");
return;
}
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s. Addio!\n", szFileName);
return;
}
#if __linux__ || __APPLE__
fseeko(fp, 0, SEEK_END);
sizeData = ftello(fp);
fseeko(fp, 0, SEEK_SET);
#else
_fseeki64(fp, 0, SEEK_END);
sizeData = _ftelli64(fp);
_fseeki64(fp, 0, SEEK_SET);
#endif
howPages = (sizeData / BLOCK_SIZE);
lastBlockLen = (int)(sizeData - howPages * BLOCK_SIZE);
x = 0;
blockLen = 0;
column = 0;
maxWordLenght = 0;
index1 = 0;
myFindRec->countChars = 0;
myFindRec->countWords = 0;
myFindRec->countRows = 0;
myFindRec->maxWordLenght = 0;
myFindRec->maxRowLenght = 0;
while ( blockLen = fread(myBlock, 1, BLOCK_SIZE, fp) )
{
myFindRec->countChars += blockLen;
while ( index1 < blockLen )
{
if ( myBlock[index1] == '\n' )
{
myFindRec->countRows++;
if ( column > myFindRec->maxRowLenght )
myFindRec->maxRowLenght = column;
column = 1;
}
else
{
column++;
}
//if ( !isValidSeparatorChar(myBlock[index1]) )
if ( isValidWordChar(myBlock[index1]) )
{
maxWordLenght++;
szWord[x++] = myBlock[index1];
}
else
{
if ( (x > 0)
&& (
(
(szWord[0] >= 'A' && szWord[0] <= 'Z') || (szWord[0] >= 'a' && szWord[0] <= 'z')
|| (szWord[0] >= 128 && szWord[0] <= 154) || (szWord[0] >= 224 && szWord[0] <= 237)
)
)
)
{
myFindRec->countWords++;
szWord[x] = '\0';
if ( maxWordLenght > myFindRec->maxWordLenght )
{
myFindRec->maxWordLenght = maxWordLenght;
strcpy(myFindRec->szLongerWord, szWord);
}
}
x = 0;
maxWordLenght = 0;
}
index1++;
}
index1 = 0;
}
fclose(fp);
free(myBlock);
}
int isValidSeparatorChar(unsigned char c)
{
if (
(c >= 65 && c <= 90) ||
(c >= 97 && c <= 122) ||
(c >= 192 && c <= 214) ||
(c >= 217 && c <= 246) ||
(c >= 249 && c <= 255)
)
return 0;
return 1;
}
int isValidWordChar(unsigned char c)
{
if (
(c >= 65 && c <= 90) ||
(c >= 97 && c <= 122) ||
(c >= 192 && c <= 214) ||
(c >= 217 && c <= 246) ||
(c >= 249 && c <= 255)
)
return 1;
return 0;
}
void PrintHelp(const char *szProg)
{
printf("\nUso: %s NomeFileInput\n", szProg);
}
void ExtractFileName(const char *szPathName, char *szFileName)
{
int k, i, x;
char c;
k = strlen(szPathName);
#ifdef __linux__ /* __gnu_linux__ */
c = '/';
#else
c = '\\';
#endif
i = k - 1;
while ( i >= 0 )
{
if ( szPathName[i] == c )
break;
i--;
}
i++;
x = 0;
for (;;)
{
szFileName[x] = szPathName[i];
if (szFileName[x] == '\0' || szFileName[x] == '.' )
break;
x++;
i++;
}
szFileName[x] = '\0';
}
int main(int argc, char* argv[])
{
FindRec myFindRec;
char szExeName[256];
//clock_t c_start, c_end;
//double TempoImpiegato;
if ( argc < 2 )
{
#ifdef __linux__
PrintHelp(argv[0]);
#else
ExtractFileName(argv[0], szExeName);
PrintHelp(szExeName);
#endif
printf("\nPremere INVIO per terminare.");
getc(stdin);
return -1;
}
InitFindRec(&myFindRec);
//c_start = clock();
doCount(argv[1], &myFindRec);
//c_end = clock();
//TempoImpiegato = (double)(c_end - c_start) / CLOCKS_PER_SEC;
//printf("Tempo impiegato per preelaborazione indice-> %5.5f secondi\n\n", TempoImpiegato);
printf("Il file \"%s\" contiene %d righe.\n", argv[1], myFindRec.countRows);
printf("La riga più lunga è lunga %d byte.\n", myFindRec.maxRowLenght - 1);
printf("Il file contiene %llu caratteri.\n", myFindRec.countChars);
printf("Nel file ci sono %d parole.\n", myFindRec.countWords);
printf("La parola più lunga è lunga %d byte.\n", myFindRec.maxWordLenght);
printf("Ecco una delle parole più lunghe: \"%s\".\n", myFindRec.szLongerWord);
printf("\n");
return 0;
}
E questo è il codice per verificare la bontà delle parole trovate:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <stdint.h>
//#include <time.h>
//#include <ctype.h>
//#define BLOCK_SIZE 4096
#define BLOCK_SIZE 8192
typedef struct tagFindRec
{
unsigned long long countChars;
int countRows;
int maxRowLenght;
int countWords;
int maxWordLenght;
char szLongerWord[1000];
} FindRec;
void InitFindRec(FindRec *myFindRec);
void doCount(const char *szFileName, FindRec *myFindRec);
int isValidSeparatorChar(unsigned char c);
int isValidWordChar(unsigned char c);
void PrintHelp(const char *szProg);
void ExtractFileName(const char *szPathName, char *szFileName);
/*---------------------------------------------------------------------------------------------------------------------*/
void InitFindRec(FindRec *myFindRec)
{
myFindRec->countChars = 0;
myFindRec->countRows = 0;
myFindRec->maxRowLenght = 0;
myFindRec->countWords = 0;
myFindRec->maxWordLenght = 0;
myFindRec->szLongerWord[0] = '\0';
}
void doCount(const char *szFileName, FindRec *myFindRec)
{
int x, k;
int index1;
int column;
int maxWordLenght;
uint64_t sizeData;
uint64_t howPages;
int blockLen;
int lastBlockLen;
FILE *fp;
FILE *fpOutput;
char szWord[512];
unsigned char *myBlock = NULL;
szWord[0] = '0';
myBlock = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlock )
{
printf("Memoria insufficiente.\n");
return;
}
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s. Addio!\n", szFileName);
return;
}
fpOutput = fopen("VerificaOutputB02.txt", "w");
if ( fpOutput == NULL )
{
printf("Errore nell'apertura del file \"OutputB02.txt\". Addio!\n");
return;
}
#if __linux__ || __APPLE__
fseeko(fp, 0, SEEK_END);
sizeData = ftello(fp);
fseeko(fp, 0, SEEK_SET);
#else
_fseeki64(fp, 0, SEEK_END);
sizeData = _ftelli64(fp);
_fseeki64(fp, 0, SEEK_SET);
#endif
howPages = (sizeData / BLOCK_SIZE);
lastBlockLen = (int)(sizeData - howPages * BLOCK_SIZE);
x = 0;
blockLen = 0;
column = 0;
maxWordLenght = 0;
index1 = 0;
myFindRec->countChars = 0;
myFindRec->countWords = 0;
myFindRec->countRows = 0;
myFindRec->maxWordLenght = 0;
myFindRec->maxRowLenght = 0;
while ( blockLen = fread(myBlock, 1, BLOCK_SIZE, fp) )
{
myFindRec->countChars += blockLen;
while ( index1 < blockLen )
{
if ( myBlock[index1] == '\n' )
{
myFindRec->countRows++;
if ( column > myFindRec->maxRowLenght )
myFindRec->maxRowLenght = column;
column = 1;
}
else
{
column++;
}
//if ( !isValidSeparatorChar(myBlock[index1]) )
if ( isValidWordChar(myBlock[index1]) )
{
maxWordLenght++;
szWord[x++] = myBlock[index1];
}
else
{
if ( (x > 0)
&& (
(
(szWord[0] >= 'A' && szWord[0] <= 'Z') || (szWord[0] >= 'a' && szWord[0] <= 'z')
|| (szWord[0] >= 128 && szWord[0] <= 154) || (szWord[0] >= 224 && szWord[0] <= 237)
)
)
)
{
myFindRec->countWords++;
szWord[x] = '\0';
if ( x >= 21)
{
fputs(szWord, fpOutput);
fputc('\n', fpOutput);
}
if ( maxWordLenght > myFindRec->maxWordLenght )
{
myFindRec->maxWordLenght = maxWordLenght;
strcpy(myFindRec->szLongerWord, szWord);
}
}
x = 0;
maxWordLenght = 0;
}
index1++;
}
index1 = 0;
}
fclose(fp);
fclose(fpOutput);
free(myBlock);
}
int isValidSeparatorChar(unsigned char c)
{
if (
(c >= 65 && c <= 90) ||
(c >= 97 && c <= 122) ||
(c >= 192 && c <= 214) ||
(c >= 217 && c <= 246) ||
(c >= 249 && c <= 255)
)
return 0;
return 1;
}
int isValidWordChar(unsigned char c)
{
if (
(c >= 65 && c <= 90) ||
(c >= 97 && c <= 122) ||
(c >= 192 && c <= 214) ||
(c >= 217 && c <= 246) ||
(c >= 249 && c <= 255)
)
return 1;
return 0;
}
void PrintHelp(const char *szProg)
{
printf("\nUso: %s NomeFileInput\n", szProg);
}
void ExtractFileName(const char *szPathName, char *szFileName)
{
int k, i, x;
char c;
k = strlen(szPathName);
#ifdef __linux__ /* __gnu_linux__ */
c = '/';
#else
c = '\\';
#endif
i = k - 1;
while ( i >= 0 )
{
if ( szPathName[i] == c )
break;
i--;
}
i++;
x = 0;
for (;;)
{
szFileName[x] = szPathName[i];
if (szFileName[x] == '\0' || szFileName[x] == '.' )
break;
x++;
i++;
}
szFileName[x] = '\0';
}
int main(int argc, char* argv[])
{
FindRec myFindRec;
char szExeName[256];
//clock_t c_start, c_end;
//double TempoImpiegato;
if ( argc < 2 )
{
#ifdef __linux__
PrintHelp(argv[0]);
#else
ExtractFileName(argv[0], szExeName);
PrintHelp(szExeName);
#endif
printf("\nPremere INVIO per terminare.");
getc(stdin);
return -1;
}
InitFindRec(&myFindRec);
//c_start = clock();
doCount(argv[1], &myFindRec);
//c_end = clock();
//TempoImpiegato = (double)(c_end - c_start) / CLOCKS_PER_SEC;
//printf("Tempo impiegato per preelaborazione indice-> %5.5f secondi\n\n", TempoImpiegato);
printf("Il file \"%s\" contiene %d righe.\n", argv[1], myFindRec.countRows);
printf("La riga più lunga è lunga %d byte.\n", myFindRec.maxRowLenght - 1);
printf("Il file contiene %llu caratteri.\n", myFindRec.countChars);
printf("Nel file ci sono %d parole.\n", myFindRec.countWords);
printf("La parola più lunga è lunga %d byte.\n", myFindRec.maxWordLenght);
printf("Ecco una delle parole più lunghe: \"%s\".\n", myFindRec.szLongerWord);
printf("\n");
return 0;
}
È uguale al precedente tranne il fatto che produce il file "VerificaOutputB02.txt" contenente le parole con lunghezza >= 21 byte.
Se volete verificare parole di lunghezza minore basta che modifichiate la seguente riga di codice(ma, se per esempio mettete 8, il file risultante sarà molto più grosso; quindi provatelo su file di piccole dimentiosi 100/200 MB):
Riga 144 circa:
if ( x >= 21)
:D
http://img829.imageshack.us/img829/4062/c19b02verify.jpg
Bho niente non partecipo perchè ho python su mac che è impazzito...
In pratica alcuni caratteri, come £ non vengono stampati.
Se apro la console interattiva da terminale dando python, se dopo provo a fare una cosa semplice tipo:
res="£"
Nel momento in cui premo £ ( shift+3 ) l'interprete mi torna ad inizio riga... :eek:
Contanto i caratteri invece, raddoppia il numero di caratteri presenti in un file.
Se scrivo in un file:
££
Il risultato di:
print fp.read()
è 4 :doh:
Lo script era parzialmente completato, ma non potendo provarlo accuratamente... :rolleyes:
MHA!
EDIT: Non è un problema del terminale, perchè fuori dall'interprete posso scrivere tranquillamente £
Vincenzo1968
02-02-2013, 21:53
Bho niente non partecipo perchè ho python su mac che è impazzito...
In pratica alcuni caratteri, come £ non vengono stampati.
Se apro la console interattiva da terminale dando python, se dopo provo a fare una cosa semplice tipo:
res="£"
Nel momento in cui premo £ ( shift+3 ) l'interprete mi torna ad inizio riga... :eek:
Contanto i caratteri invece, raddoppia il numero di caratteri presenti in un file.
Se scrivo in un file:
££
Il risultato di:
print fp.read()
è 4 :doh:
Lo script era parzialmente completato, ma non potendo provarlo accuratamente... :rolleyes:
MHA!
EDIT: Non è un problema del terminale, perchè fuori dall'interprete posso scrivere tranquillamente £
E vabbé, tu fai ritornare il risultato di python/2 ;)
Comunque, come ti dicevo prima, fottitene del numero di caratteri. Concentrati sul numero di parole.
;)
E vabbé, tu fai ritornare il risultato di python/2 ;)
Comunque, come ti dicevo prima, fottitene del numero di caratteri. Concentrati sul numero di parole.
;)
Si ma viene tutto sballato, perchè se anche una parola è fatta da
£($) non me la prenderà o comunque, nel conteggio per la parola più lunga viene fuori un casino...
Python 3.3 sembra non avere questo problema... Vedo se riesco a integrarlo con Eclipse
cdimauro
03-02-2013, 06:58
Probabilmente il problema è dovuto alla codifica dei caratteri, di cui non è stato tenuto conto nel contest.
Ormai quando parliamo di testo, non pensiamo più byte grezzi, com'è stato fatto aprendo i file finora (con 'rb' e 'wb'), ma specificando una codifica per la lettura e la scrittura, e internamente una stringa viene manipolata come Unicode oppure, per ottimizzare, con una codifica che ne rappresenta un suo sottoinsieme, come l'UTF16; nei server generalmente i testi vengono codificati col massimo del range dei caratteri, quindi come UTF32.
Con Python fino alla 2.7 se apri il file senza b si suppone che sia un file di testo, codificato come ASCII; se specifichi b, vengono letti byte grezzi. Su Python >= 3, il default è che i file letti senza b sono di testo, e si suppone che la codifica sia UTF-8, per cui le stringhe saranno codificate come UTF16 o UTF32, a seconda di com'è stato compilato CPython; mentre come 'b vengono letti al solito come byte grezzi, ma non vengono restituite stringhe, quanto oggetti byte (immutabili).
Sì, è un casino. Ed è per questo che con Python 3 hanno deciso di fare pulizia col linguaggio, in modo che quando si parla di stringhe, si fa sempre uso di oggetti che manipolano "Unicode". Mentre per i byte grezzi, ci sono i byte (immutabili; molto simili alle vecchie stringhe) o bytearray (come i precedenti, ma modificabili).
Dopo questa disquisizione, rimane il problema di cui sopra. A mio avviso per il contest si dovrebbe procedere usando UTF-8 per i testi di input. Poi internamente si può decidere quale codifica usare (continuare con UTF-8, come hanno fatto quelli di Perl, oppure usare UTF16 o UTF32), ma bisogna tenere presente che con UTF-8 non è che per eliminare tutti gli spazi, tab, newline, ecc. si può semplicemente togliere di mezzo i byte grezzi 0x20, 0x8, 0x0a, 0x0c, ecc., perché questi possono far parte del gruppo di byte che codifica un certo carattere "lungo" (che occupa più di un byte) e si deve tenere conto di ciò.
In Python credo sia molto semplice da gestire: basta leggere i file come testo per la versione >= 3, che automaticamente suppone che il file sia UTF-8 e le stringhe restituite sono "Unicode" (UTF16 o UTF32).
Nel caso della 2.7 o inferiore si apre sempre come testo usando il modulo codecs:
import codecs
f = codecs.open('Saro Falsaperla.txt', 'r', 'utf-8')
che restituisce stringhe "Unicode", appunto.
Ho visto che il codec di default è line buffered, ma accetta come parametro "buffering" col quale si può specificare quanto dev'essere grande il buffer. Magari si può fare qualche prova mettendolo a 64 * 1024 o a valori più elevati per vedere se migliorare la velocità di lettura (o scrittura).
A me, visto che ho deciso di utilizzare Ruby, "viene allo scendere", come si suol dire dalle mie parti(in italiano: "viene in discesa") :D
Per me come volete voi ma, come dice kwb, penalizza gli utilizzatori di C, C++, Java, Assembly...
Ah penalizza Vicius... Allora si!!! :D
Ed io uso uglify.
fs=require("fs"),lazy=require("lazy"),lazy(fs.createReadStream("file")).lines.map(function(a){return words=(""+a).split(/\W+/),s="",words.forEach(function(a){s.length<a.length&&(s=a)}),{b:a.length,w:words.length,s:s}}).foldr(function(a,b){return{b:a.b+b.b+1,l:b.l+1,w:a.w+b.w,s:b.s.length<a.s.length?a.s:b.s}},{b:0,l:0,w:0,s:""},function(a){console.log(a.b+" byte\n"+a.l+" righe\n"+a.w+" parole\n"+"la parola piu lunga e' "+a.s)})
Stesso programma di prima. Da 1206 a 430 byte. Riduzione del 280% circa. :asd:
È penalizzante per chi usa linguaggi di basso livello...
Beh per quello basterebbe usare i giusti pesi (o nel caso di linguaggio di basso livello, le giuste librerie :p )...
Vincenzo1968
03-02-2013, 10:37
L'unico file, tra quelli presenti nei file di input, codificato come UTF8 è "descartes_discorso_sul_metodo.txt".
Me ne sono accorto aprendolo con Geany che, nella barra di stato, in basso, visualizza la codifica del file aperto.
Gli altri sono tutti codificati secondo il normale(normale, dico, per noi europei) ISO-8859-1.
Per cui, se preferite, togliete il file suddetto dai file di input. Ma, se utilizzate una delle soluzioni presentate dagli altri per il punto A, dovete modificare i sorgenti in modo che non tengano conto del file in questione.
In alternativa sostituitelo con un normale file dallo stesso titolo ma codificato con ISO-8859-1.
;)
Vincenzo1968
03-02-2013, 10:40
Ed io uso uglify.
fs=require("fs"),lazy=require("lazy"),lazy(fs.createReadStream("file")).lines.map(function(a){return words=(""+a).split(/\W+/),s="",words.forEach(function(a){s.length<a.length&&(s=a)}),{b:a.length,w:words.length,s:s}}).foldr(function(a,b){return{b:a.b+b.b+1,l:b.l+1,w:a.w+b.w,s:b.s.length<a.s.length?a.s:b.s}},{b:0,l:0,w:0,s:""},function(a){console.log(a.b+" byte\n"+a.l+" righe\n"+a.w+" parole\n"+"la parola piu lunga e' "+a.s)})
Stesso programma di prima. Da 1206 a 430 byte. Riduzione del 280% circa. :asd:
Ci mancava uglify. Mo siamo completi. :mbe:
:D
Senti maaaaaaaaaaa per provare il tuo in JavaScript che debbo fare? Ancora mica me l'hai spiegato. Come cacchio lo uso 'sto node? E posso schiaffare il codice JavaScript dentro un file HTML e farlo partire da li? E come?
Ci mancava uglify. Mo siamo completi. :mbe:
:D
Senti maaaaaaaaaaa per provare il tuo in JavaScript che debbo fare? Ancora mica me l'hai spiegato. Come cacchio lo uso 'sto node? E posso schiaffare il codice JavaScript dentro un file HTML e farlo partire da li? E come?
Crea un file .js e poi lo lanci con node. Così: node puntob.js
Vincenzo1968
03-02-2013, 10:57
Qualche tempo fa avevo scritto un programmino per verificare i vari formati dei file:
#include <stdio.h>
#define TF_ANSI 1
#define TF_UTF16LE 2
#define TF_UTF16BE 3
#define TF_UTF8 4
int LeggiTipoFile(const char *szFileName)
{
FILE * fp;
unsigned char byte1, byte2, byte3;
int numread;
fp = fopen(szFileName, "rb");
if ( fp == NULL )
return -1;
numread = fread(&byte1, 1, 1, fp);
if ( !numread ) // file vuoto;
{
fclose(fp);
return 0;
}
if ( byte1 == 0xFF ) // UTF16LE?
{
numread = fread(&byte2, 1, 1, fp);
if ( !numread )
{
fclose(fp);
return 0;
}
if ( byte2 == 0xFE )
{
fclose(fp);
return TF_UTF16LE;
}
else
{
fclose(fp);
return TF_ANSI;
}
}
if (byte1 == 0xFE) // UTF16BE?
{
numread = fread(&byte2, 1, 1, fp);
if ( !numread )
{
fclose(fp);
return 0;
}
if ( byte2 == 0xFF )
{
fclose(fp);
return TF_UTF16BE;
}
}
if (byte1 == 0xEF) // UTF8?
{
numread = fread(&byte2, 1, 1, fp);
if ( !numread )
{
fclose(fp);
return 0;
}
if ( byte2 == 0xBB )
{
numread = fread(&byte3, 1, 1, fp);
if ( !numread )
{
fclose(fp);
return 0;
}
if ( byte3 == 0xBF)
{
fclose(fp);
return TF_UTF8;
}
}
}
fclose(fp);
return TF_ANSI;
}
int main()
{
int k;
int typeFile;
char* arrayFiles[] =
{
"All/amor_fa_.txt",
"All/bertoldo.txt",
"All/candid_t.txt",
"All/convivio.txt",
"All/dell_art.txt",
"All/del_roma.txt",
"All/del_tr_t.txt",
"All/descartes_discorso_sul_metodo.txt",
"All/de_vulga.txt",
"All/dialogo_.txt",
"All/diario_d.txt",
"All/discorsi.txt",
"All/don_chis.txt",
"All/il_bugia.txt",
"All/il_corsa.txt",
"All/il_saggi.txt",
"All/i_pirati.txt",
"All/i_promes.txt",
"All/la_banca.txt",
"All/la_divin.txt",
"All/la_ric_t.txt",
"All/la_rivin.txt",
"All/la_tigre.txt",
"All/le_mecan.txt",
"All/le_opere.txt",
"All/le_tigri.txt",
"All/l_adulat.txt",
"All/l_amante.txt",
"All/l_avaro.txt",
"All/principe.txt",
"All/sidereus.txt",
"All/storia_d.txt",
"All/sulla_or.txt"
};
printf("\n");
for ( k = 0; k < 33; k++ )
{
typeFile = LeggiTipoFile(arrayFiles[k]);
switch( typeFile )
{
case TF_ANSI:
printf("Il file %s e' nel formato ANSI\n", arrayFiles[k]);
break;
case TF_UTF16LE: // UTF16 Little Endian
printf("Il file %s e' nel formato TF_UTF16LE(UTF16 Little Endian)\n", arrayFiles[k]);
break;
case TF_UTF16BE: // UTF16 Big Endian
printf("Il file %s e' nel formato TF_UTF16BE(UTF16 Big Endian)\n", arrayFiles[k]);
break;
case TF_UTF8:
printf("Il file %s e' nel formato TF_UTF8(UTF8)\n", arrayFiles[k]);
break;
default:
printf("%s Errore!!!\n", arrayFiles[k]);
break;
}
}
printf("\n");
return 0;
}
Legge soltanto i primi tre byte del file quindi restituisce sempre ANSI per tutti i nostri file, anche per "descartes_discorso_sul_metodo.txt":
http://img687.imageshack.us/img687/87/verifyencoding.jpg
Bisognerebbe modificarlo in modo da fargli leggere l'intero file e, se trova byte con la codifica UTF8, fermare lo scanning e fargli restituire, appunto, UTF8 anziché ANSI.
Vincenzo1968
03-02-2013, 11:18
Crea un file .js e poi lo lanci con node. Così: node puntob.js
Ah minchia, hai vinto! Batti tutti: me, wc:
http://img10.imageshack.us/img10/6417/nodevicius.jpg
Velocissimo. Non stampa un accidente di niente ma è velocissimo. :D
Il file chiamato "file" c'è nella cartella dov'è presense viciusb01.js come da screenshot di qualche post fa.
http://www.hwupgrade.org/public/style_emoticons/default/patpat.gif
Qui va senza problemi. Avrai un computer difettoso. :O
http://f.cl.ly/items/1i0E121l321o0N1W2e2V/works.png
Vincenzo1968
03-02-2013, 11:49
Qui va senza problemi. Avrai un computer difettoso. :O
http://f.cl.ly/items/1i0E121l321o0N1W2e2V/works.png
http://www.hwupgrade.org/public/style_emoticons/default/rage.png
Vincenzo1968
03-02-2013, 12:06
Visto che a te funziona vuoi farlo tu uno screenshot coi tempi di tutt'e tre le applicazioni? La tua, la mia e wc.
Occhio, la mia la devi compilare così:
gcc -O3 puntob02.c -o puntob02
Poi esegui così:
./puntob02 file
wc invece lo esegui così:
wc -w -l -L file
o così:
wc -w file
I tempi, ovviamente, devi prenderli su un file grosso, almeno 1 GiB.
Vincenzo1968
03-02-2013, 13:46
Qualcuno che ha Linux potrebbe cortesemente postare un benchmark dei tre programmi?
Se nessuno si offre, a Vicius verrà assegnata, per il punto B.2, la stessa versione di default di Gugo:
print "ci ho messo 7 ore."
;)
Vincenzo1968
03-02-2013, 14:11
Com'è che nelle mie due versioni(32/64 bit) differisce il conteggio delle parole?
Eppure, se eseguo il file di verifica, entrambe le versioni producono lo stesso risultato:
particolareggiatamente
quattrocentocinquanta
quattromilanovantasettesimi
sproporzionatissimamente
dugentosettantacinque
dugentosettantacinque
quattrocentocinquanta
quattromilanovantasettesimi
disaventuratissimamente
sovramagnificentissimamente
honorificabilitudinitate
sproporzionatissimamente
particolareggiatamente
quattrocentocinquanta
dugentosettantacinque
dugentosettantacinque
sproporzionatissimamente
disaventuratissimamente
sovramagnificentissimamente
honorificabilitudinitate
quattromilanovantasettesimi
:confused:
EDIT: Ah no, avevo preso l'eseguibile sbagiato per la versione a 64 bit. Sto uploadando i file giusti. ;)
Vincenzo1968
03-02-2013, 14:41
Ho seguito questa guida passo passo per installare nodejs nel mio sistema:
http://www.hacksparrow.com/how-to-install-node-js-on-ubuntu-linux.html
Tutto è andato a buon fine ma non c'è verso di fargli stampare la versione:
node -v
Non stampa un tubo.
:confused:
EDIT: ah no! Bisognava riavviare il sistema. Provvedo a fare i benchmarks ;)
Vincenzo1968
03-02-2013, 14:59
Vicius asfaltato:
http://img708.imageshack.us/img708/628/viciusfottuto.jpg
:D
EDIT: E poi che parola trova? "--------------------------------------------------------------------" parola è? :D
Nel file piccolo:
Esempio file di piccolissime dimensioni.
Questa riga contiene parole dentro (parentesi).
Anche questa contiene [parentesi], ma quadre.
Quest'altra riga contiene parole all'interno di {parentesi graffe}.
Riga con caratteri strani: #$££$%$%%£££$$ *****$$$|||||&&&&&.
Ciao.
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Tommo$ node Viciusb02.js
nel file ci sono 282 byte
su 9 righe
che contengono 41 parole
e la parola più lunga è "piccolissime"
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Tommo$ ./puntob264 file
Il file "file" contiene 9 righe.
La riga più lunga è lunga 67 byte.
Il file contiene 279 caratteri.
Nel file ci sono 32 parole.
La parola più lunga è lunga 12 byte.
Ecco una delle parole più lunghe: "piccolissime".
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Tommo$ wc -w file
32 file
Vincenzo1968
03-02-2013, 17:46
Ragazzi ho asfaltato pure wc. Non solo il mio programma è più veloce, ma riporta anche l'esatto numero di parole.
Potete verificarlo con la seconda versione che ho postato, quella che mette le parole trovate in un file di output:
Avviando il programma sul più piccolo dei file in input, "amor_fa_.txt",
http://img338.imageshack.us/img338/5817/vittoriaassoluta.jpg
Il mio programma riporta l'esatto numero di parole, 2665.
Dovete modificare la riga if ( x >= 21 ) con if ( x >= 0 ) in modo da fargli mettere nel file in output tutte le parole.
A meno che wc non consideri parole gli articoli, il lo la i gli le e cavoli vari. Ma non ci vuole niente a modificare il mio automa a stati finiti in tal senso. ;)
:yeah: :winner: :yeah:
Vincenzo1968
03-02-2013, 18:34
Aggiunto, nel primo post, il punto B.3:
Punto B.3
Si modifichi il programmino di cui al punto B.2 in modo da fargli accettare due argomenti dalla riga di comando(oltre al nome del file):
1) Il parametro "-L=d" dove d sta per la dimensione minima delle parole che l'utente desidera per il conteggio. Per esempio, -L=5 significa che l'utente desidera che vengano conteggiate le parole con lunghezza >= 5.
2) Il parametro "-F=file" dove file sta per il nome di un file specificato dall'utente dove sono listati, una parola per riga, le parole che l'utente desidera escludere dalla ricerca. Per esempio:
il
lo
la
i
gli
le
Col suddetto file passato come argomento, il programmino dovrà escludere dal conteggio le parole "il", "lo", "la", "i", "gli", "le".
Vincenzo1968
04-02-2013, 12:50
È quasi pronta la mia versione Ruby per il punto B.1...
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Pare che i file abbiano caratteri non ASCII.
Nel mio specifico caso, avevo visto che il problema era con £ .
Aggiungendo all'inizio dello script python:
#coding: utf-8
Il problema pare risolto..
Ora controllerò
Vincenzo1968
04-02-2013, 13:02
Pare che i file abbiano caratteri non ASCII.
Nel mio specifico caso, avevo visto che il problema era con £ .
Aggiungendo all'inizio dello script python:
#coding: utf-8
Il problema pare risolto..
Ora controllerò
Ottimo!
:yeah: :winner: :yeah:
Vincenzo1968
04-02-2013, 13:12
http://www.hwupgrade.it/forum/showpost.php?p=38973462&postcount=42
È carinissimo il codice Haskell:
http://img35.imageshack.us/img35/5421/haskellnice.jpg
:D
Gliel'ho sempre detto a Vicius ma non vuol darmi retta :O
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
:D
Ottimo!
:yeah: :winner: :yeah:
OK, ho ( credo ) risolto...
Finito di studiare guardo se riesco a finire sto scirpt..
Vicius asfaltato:…
Solo 12 volte più lento. Mi aspettavo di peggio da js. :O
EDIT: E poi che parola trova? "--------------------------------------------------------------------" parola è? :D
Da un appassionato di dfa come te non mi aspettavo una domanda simile. Pensavo conoscessi le regexp come pochi. Ho usato \W+ per fare lo split quindi le parole sono \w+. Gli underscore, non sono trattini, vengono considerati come parte di una parola.
Non ho tempo di controllare ma immagino che il numero di parole diverso sia dovuto a questo. Oppure a qualche valore vuoto generato dalla split.
Vincenzo1968
04-02-2013, 13:56
Solo 12 volte più lento. Mi aspettavo di peggio da js. :O
Da un appassionato di dfa come te non mi aspettavo una domanda simile. Pensavo conoscessi le regexp come pochi. Ho usato \W+ per fare lo split quindi le parole sono \w+. Gli underscore, non sono trattini, vengono considerati come parte di una parola.
Non ho tempo di controllare ma immagino che il numero di parole diverso sia dovuto a questo. Oppure a qualche valore vuoto generato dalla split.
Ah ti sei arricampato finalmente! :D
No le regexp le conosco quel minimo che basta per utilizzarle con Flex. ;)
Preferisco implementare a mano automi a stati finiti di tipo deterministico per le ricerche.
Le implementazioni delle regexp, nei vari linguaggi, utilizzano automi a stati finiti di tipo non deterministico; è per questo che risultano lente. ;)
Non determinismo = backtracking: http://swtch.com/~rsc/regexp/regexp1.html
Backtracking a volte catastrofico: http://www.regular-expressions.info/catastrophic.html
http://www.hwupgrade.org/public/style_emoticons/default/motherofgod.png
Ah ti sei arricampato finalmente! :D
Fammi capire. Secondo te sto cercando scuse perché non è veloce come la versione C? :rotfl:
Vincenzo1968
04-02-2013, 15:36
Fammi capire. Secondo te sto cercando scuse perché non è veloce come la versione C? :rotfl:
No assolutamente. È che mi fa piacere leggerti. Non sto scherzando ;)
No assolutamente. È che mi fa piacere leggerti. Non sto scherzando ;)
Ah. Ma scrivi in italiano. Che altrimenti non ti capisco. :O
Vincenzo1968
04-02-2013, 16:23
Ah. Ma scrivi in italiano. Che altrimenti non ti capisco. :O
:D
M'hai fatto venire un'idea con quell'accenno alle regexp. Quante volte ci capita di leggere codice altrui in cui ci sono delle regexp di difficile comprensione?
Il tizio s'è scordato di commentare il codice e noi dobbiamo cercare di capire che cacchio fa la regexp.
Dunque si potrebbe aggiungere il seguente punto B.4:
Si scriva un programmino che prenda in input una regexp e la traduca in italiano.
Che dite?
Forse è meglio aprirci un contest a parte. Si si. Uh! il lavoro non manca! :D
Punto b.2
Forse il codice funziona, o forse no. Provate voi, io non ci sto capendo niente...
import sys
import codecs as cd
def countChars(fp):
print 'Numero di caratteri: ',len(fp.read())
fp.seek(0)
def countLines(fp):
print 'Numero di righe: ',len(fp.readlines())
fp.seek(0)
def countWords(fp):
p=fp.read().split()
print 'Ci sono {} parole nel file di testo' .format(len(p))
fp.seek(0)
def longLine(fp):
longest=''
for i in fp.readlines():
if len(i) > len(longest):
longest=i
print 'La riga piu\' lunga e\':\n\t', longest,'Ed e\' lunga {} caratteri'.format(len(longest))
fp.seek(0)
def longWord(fp):
longest=''
for i in fp.read().split():
if len(longest) < len(i):
longest=i
print 'Parola piu\' lunga: {0}\ndi {1} caratteri'.format(longest,len(longest))
#fp=cd.open(sys.argv[1],encoding='utf-8')
fp=open(sys.argv[1],'r')
countChars(fp)
countLines(fp)
countWords(fp)
longLine(fp)
longWord(fp)
fp.close()
Codice python. Si avvia dando:
python nomesorgente.py percorsofile
Vincenzo1968
04-02-2013, 17:03
Grande Kwb.
Lo provo subito. Comunque, anche se non dovesse funzionare stracatafottitene.
Hai tutta la mia ammirazione(per quello che può valere).
;)
Grande Kwb.
Lo provo subito. Comunque, anche se non dovesse funzionare stracatafottitene.
Hai tutta la mia ammirazione(per quello che può valere).
;)
Eh beh ma se non va perde di significato nel contest :asd:
EDIT: Cmq mi sto leggendo un po' la questione sulla codifica caratteri in python.
Mi pare bizzarro che nessuno di voi abbia riscontrato questi problemi con nessuno dei file.
Forse è perchè sono su Mac?
EDIT2: Nella riga commentata:
fp=cd.open(sys.argv[1],encoding='utf-8')
Se invece di utf-8 uso mac-roman non ho problemi...
Vincenzo1968
04-02-2013, 17:10
Kwb, ci sei quasi:
=== python c19b02KWB.py fileA_21MB.txt
Numero di caratteri: 1048576
Numero di righe: 6298
Ci sono 174920 parole nel file di testo
La riga piu' lunga e':
SALV. Io sommamente laudo ammiro
caduto in mente concetto tanto stupendo
L'unica cosa è che non devi fare stampare la riga più lunga ma la parola più lunga. ;)
Vincenzo1968
04-02-2013, 17:12
Eh beh ma se non va perde di significato nel contest :asd:
EDIT: Cmq mi sto leggendo un po' la questione sulla codifica caratteri in python.
Mi pare bizzarro che nessuno di voi abbia riscontrato questi problemi con nessuno dei file.
Forse è perchè sono su Mac?
EDIT2: Nella riga commentata:
fp=cd.open(sys.argv[1],encoding='utf-8')
Se invece di utf-8 uso mac-roman non ho problemi...
No no, io li ho riscontrati eccome, i problemi con unicode. Apposta ho fatto una versione per verificare i caratteri trovati e farglieli stampare su file. Alla fine ho aggiustato il mio codice per fargli gestire i caratteri unicode.
;)
Si ma la cosa bella è che anche se metto codifica unicode8, mi trova ancora caratteri non convertibili...:doh:
Vincenzo1968
04-02-2013, 17:37
C'è un problema coi file grossi:
http://img850.imageshack.us/img850/4363/kwbb.jpg
Prova a leggere/scrivere piccoli blocchi da 4096 byte come abbiamo visto in precedenza per la versione non pythonica.
Vediamo anche cosa suggerisce cdimauro.
Comunque complimentissimi. ;)
Vincenzo1968
04-02-2013, 17:53
Raga', per il futuro contest sulle regexp, dovremo trattare robe del tipo:
questa, per esempio, che cosa fa?
(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:
\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(
?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[
\t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\0
31]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\
](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+
(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:
(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)
?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\
r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[
\t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)
?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t]
)*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[
\t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*
)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t]
)+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)
*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+
|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r
\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:
\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t
]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031
]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](
?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?
:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?
:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?
:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?
[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\]
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|
\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>
@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"
(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?
:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[
\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-
\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(
?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;
:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([
^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\"
.\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\
]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\
[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\
r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\]
\000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]
|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \0
00-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\
.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,
;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?
:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[
^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]
]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(
?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(
?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[
\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t
])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t
])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?
:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|
\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:
[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\
]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)
?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["
()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)
?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>
@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[
\t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,
;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t]
)*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\
".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?
(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".
\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:
\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\[
"()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])
*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])
+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\
.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z
|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(
?:\r\n)?[ \t])*))*)?;\s*)
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
http://www.ex-parrot.com/pdw/Mail-RFC822-Address.html ;)
:D
C'è un problema coi file grossi:
http://img850.imageshack.us/img850/4363/kwbb.jpg
Prova a leggere/scrivere piccoli blocchi da 4096 byte come abbiamo visto in precedenza per la versione non pythonica.
Vediamo anche cosa suggerisce cdimauro.
Comunque complimentissimi. ;)
Hmm, sto rileggendo le pagine indietro, sperando ci fosse un aiutino in python di cdimauro, ma purtroppo non c'è. :D
Quello che intendi dire tu è:
1. Leggo i primi x byte dal file
2. Li processo ( conto parole, righe, caratteri, parola più lunga, riga più lunga )
3. Ritorno al punto 1 se il file non è finito
4. Stampo tutto
Oppure come?
Vincenzo1968
04-02-2013, 18:13
Questa è l'ultima versione che ha postato cdimauro(è un miglioramento della mia versione non pythonica):
from functools import partial
def Main():
dimfileout = 1024 * 1024 * 1024
dimcurr = 0
print "\nInizio a copiare il file..."
fo = open('I_Promessi_Sposi.txt', 'wb')
fi = file("All/i_promes.txt", 'rb')
Read = partial(fi.read, 4096)
Write = fo.write
Seek = partial(fi.seek, 0)
while dimcurr < dimfileout:
r = Read()
while r:
Write(r)
dimcurr += 4096
r = Read()
Seek()
fo.close()
fi.close()
print "Ho finito!"
Main()
Il programmino legge il file di input in blocchi da 4096 byte e li scrive, sempre in blocchi da 4096 byte, nel file di output. Il ciclo si ripete finché il file di output non abbia raggiunto la dimensione di 1 GiB (1024 * 1024 * 1024).
Prova a prendere spunto dal programmino di cui sopra. ;)
Vincenzo1968
04-02-2013, 18:14
Hmm, sto rileggendo le pagine indietro, sperando ci fosse un aiutino in python di cdimauro, ma purtroppo non c'è. :D
Quello che intendi dire tu è:
1. Leggo i primi x byte dal file
2. Li processo ( conto parole, righe, caratteri, parola più lunga, riga più lunga )
3. Ritorno al punto 1 se il file non è finito
4. Stampo tutto
Oppure come?
Praticamente, si, è questo il metodo. ;)
Ovviamente devi gestire il caso in cui una riga sia spammata tra due blocchi consecutivi. Puoi dare un'occhiata al mio codice ma è in C. :cry:
Vincenzo1968
04-02-2013, 18:53
Giovedì pomeriggio non cercatemi ché sono alla presentazione del libro di Consolo(a Vicius dico):
http://img803.imageshack.us/img803/1069/consolo.jpg
Allo Steri, sede della Santa Inquisizione in Sicilia.
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Raga', per il futuro contest sulle regexp, dovremo trattare robe del tipo:
:D
Come ama dire un collega, esistono due tipi di informatici: chi non sa usare le regex e chi crede di saperle usare. http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Non capisco se ci ho preso o meno:
totChar=0
totLines=0
totWords=0
longestLine=''
longestWord=''
currentPosition=0
#fp=cd.open(sys.argv[1],encoding='mac-roman')
fp=open(sys.argv[1],'rb')
while fp.read(1024):
currentPosition=fp.tell()
totChar+=countChars(fp)
print 'Caratteri parziali:', totChar
totLines+=countLines(fp)
print 'Linee parziali:', totLines
fp.seek(currentPosition);
Per come la vedo io, dovrebbe funzionare...
L'idea è che siccome uso differenti funzioni per trovare le cose richieste, alla fine di ognuna, porto il fp a 0.
Di conseguenza all'inizio, con fp.tell() salvo la posizione corrente.
Tuttavia va avanti a tipo l'infinito... :mbe:
Ho provato con 1024 byte alla volta, per vedere se fa qualcosa...
Non capisco se sbaglio a far tornare indietro il cursore ( si chiama così? ) sul file pointer o se while fp.read(1024) è sempre verificata...
Quasi mi scoccia chiedere una mano nel contest, ma ste cose col buffer mai le ho fatte...
EDIT:
Ovviamente devi gestire il caso in cui una riga sia spammata tra due blocchi consecutivi. Puoi dare un'occhiata al mio codice ma è in C.
Cosa vuol dire?
Cmq probabilmente in C lo avrei già fatto sto programma :D , solo che se non uso mai python non imparo niente...
Vincenzo1968
04-02-2013, 21:40
Come ama dire un collega, esistono due tipi di informatici: chi non sa usare le regex e chi crede di saperle usare. http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
:asd:
Vincenzo1968
04-02-2013, 21:47
Non capisco se ci ho preso o meno:
totChar=0
totLines=0
totWords=0
longestLine=''
longestWord=''
currentPosition=0
#fp=cd.open(sys.argv[1],encoding='mac-roman')
fp=open(sys.argv[1],'rb')
while fp.read(1024):
currentPosition=fp.tell()
totChar+=countChars(fp)
print 'Caratteri parziali:', totChar
totLines+=countLines(fp)
print 'Linee parziali:', totLines
fp.seek(currentPosition);
Per come la vedo io, dovrebbe funzionare...
L'idea è che siccome uso differenti funzioni per trovare le cose richieste, alla fine di ognuna, porto il fp a 0.
Di conseguenza all'inizio, con fp.tell() salvo la posizione corrente.
Tuttavia va avanti a tipo l'infinito... :mbe:
Ho provato con 1024 byte alla volta, per vedere se fa qualcosa...
Non capisco se sbaglio a far tornare indietro il cursore ( si chiama così? ) sul file pointer o se while fp.read(1024) è sempre verificata...
Quasi mi scoccia chiedere una mano nel contest, ma ste cose col buffer mai le ho fatte...
EDIT:
Cosa vuol dire?
Cmq probabilmente in C lo avrei già fatto sto programma :D , solo che se non uso mai python non imparo niente...
Domani mattina ti spiego per benino l'algoritmo che ho utilizzato io. Ora sono stanco morto.
Comunque si, l'idea è quella. Si tratta di leggere, in blocchi, i byte grezzi(anziché leggere con readlines() e simili). Poi si esaminano i byte uno a uno.
In questo modo è facile gestire le righe e/o le parole che cominciano in un blocco e terminano nell'altro(o negli altri se la riga è particolarmente lunga).
Si tratta di scrivere un pochino di codice in più. Roba non pythonica. Ma almeno siamo sicuri di non esaurire la memoria(e il codice risulta molto più veloce). ;)
Domattina lo vediamo meglio. ;)
cdimauro
04-02-2013, 22:17
Qualche tempo fa avevo scritto un programmino per verificare i vari formati dei file:
[...]
Legge soltanto i primi tre byte del file quindi restituisce sempre ANSI per tutti i nostri file, anche per "descartes_discorso_sul_metodo.txt":
Bisognerebbe modificarlo in modo da fargli leggere l'intero file e, se trova byte con la codifica UTF8, fermare lo scanning e fargli restituire, appunto, UTF8 anziché ANSI.
Infatti non basta controllare i primi byte per ricavare il charset usato in un file.
Pare che i file abbiano caratteri non ASCII.
Nel mio specifico caso, avevo visto che il problema era con £ .
Aggiungendo all'inizio dello script python:
#coding: utf-8
Il problema pare risolto..
Ora controllerò
Quella "direttiva" serve esclusivamente per i sorgenti di Python <= 2.7, i quali, in sua assenza, si suppone e devono essere codificati come ASCII.
Con Python 3, invece, non c'è più quella direttiva: i file vanno codificati come UTF-8.
Eh beh ma se non va perde di significato nel contest :asd:
EDIT: Cmq mi sto leggendo un po' la questione sulla codifica caratteri in python.
Mi pare bizzarro che nessuno di voi abbia riscontrato questi problemi con nessuno dei file.
Forse è perchè sono su Mac?
EDIT2: Nella riga commentata:
fp=cd.open(sys.argv[1],encoding='utf-8')
Se invece di utf-8 uso mac-roman non ho problemi...
Perché il Mac-Roman è un charset i cui simboli sono codificati come singoli byte, in maniera simile al Latin-1 e a tanti altri charset. In sostanza, vengono letti i byte così come sono, e problemi generalmente non ce ne sono (tranne per charset che usano meno di 256 simboli: se il codec usato da Python incontra byte non usati, solleva un'eccezione).
L'UTF-8, invece, ha una codifica ben diversa, ed è facile che leggendo un file che non sia UTF-8, ma Latin-1, Mac-Roman, o altro, il codec sollevi un'eccezione.
I charset sono stati e sono una spina nel fianco dell'informatica. E' per questo che negli ultimi anni s'è imposto l'UTF-8, che ormai è diventato lo standard di riferimento per le informazioni testuali, per cui ribadisco il mio consiglio di usarlo anche nel contest, perché nel mondo reale ormai difficilmente se ne può fare a meno se l'interoperabilità è un valore importante.
Si ma la cosa bella è che anche se metto codifica unicode8, mi trova ancora caratteri non convertibili...:doh:
UTF-8: Unicode è un'altra cosa.
Per il resto, vedi sopra.
C'è un problema coi file grossi:
http://img850.imageshack.us/img850/4363/kwbb.jpg
Prova a leggere/scrivere piccoli blocchi da 4096 byte come abbiamo visto in precedenza per la versione non pythonica.
Vediamo anche cosa suggerisce cdimauro.
Comunque complimentissimi. ;)
Viene letto tutto il file in memoria con la .read(), per cui è facile che il processo muoia per mancanza di memoria.
Come ama dire un collega, esistono due tipi di informatici: chi non sa usare le regex e chi crede di saperle usare. http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Esistono anche quelli che non le digeriscono. :O
Non capisco se ci ho preso o meno:
totChar=0
totLines=0
totWords=0
longestLine=''
longestWord=''
currentPosition=0
#fp=cd.open(sys.argv[1],encoding='mac-roman')
fp=open(sys.argv[1],'rb')
while fp.read(1024):
currentPosition=fp.tell()
totChar+=countChars(fp)
print 'Caratteri parziali:', totChar
totLines+=countLines(fp)
print 'Linee parziali:', totLines
fp.seek(currentPosition);
Per come la vedo io, dovrebbe funzionare...
L'idea è che siccome uso differenti funzioni per trovare le cose richieste, alla fine di ognuna, porto il fp a 0.
Di conseguenza all'inizio, con fp.tell() salvo la posizione corrente.
Tuttavia va avanti a tipo l'infinito... :mbe:
Non capisco se sbaglio a far tornare indietro il cursore ( si chiama così? ) sul file pointer o se while fp.read(1024) è sempre verificata...
Esatto: è quello il motivo.
Quasi mi scoccia chiedere una mano nel contest, ma ste cose col buffer mai le ho fatte...
EDIT:
Cosa vuol dire?
Cmq probabilmente in C lo avrei già fatto sto programma :D , solo che se non uso mai python non imparo niente...
Cerca di affrontare un solo problema alla volta. Affronta un (sotto) punto del problema B.2, e quando sei sicuro passa all'implementazione dell'altro.
Soltanto alla fine, quando avrai il codice funzionante per tutto, puoi cercare di vedere se e come ottimizzarlo.
Visto che si parla di effettuare dei conteggi, ti consiglio di usare la classe Counter del modulo collections, che fa proprio al caso tuo. ;)
Domani mattina ti spiego per benino l'algoritmo che ho utilizzato io. Ora sono stanco morto.
Comunque si, l'idea è quella. Si tratta di leggere, in blocchi, i byte grezzi(anziché leggere con readlines() e simili). Poi si esaminano i byte uno a uno.
In questo modo è facile gestire le righe e/o le parole che cominciano in un blocco e terminano nell'altro(o negli altri se la riga è particolarmente lunga).
Si tratta di scrivere un pochino di codice in più. Roba non pythonica. Ma almeno siamo sicuri di non esaurire la memoria(e il codice risulta molto più veloce). ;)
Domattina lo vediamo meglio. ;)
Bon, a me sembrava tutto a posto, ma non riesco a fermarlo.. Vedremo se hai suggerimenti utili domani :)
Quella "direttiva" serve esclusivamente per i sorgenti di Python <= 2.7, i quali, in sua assenza, si suppone e devono essere codificati come ASCII.
Con Python 3, invece, non c'è più quella direttiva: i file vanno codificati come UTF-8.
Ah ok.. Questa cosa della codifica mi ha preso un po' alla sprovvista perchè non l'ho mai trattata nel corso dei miei studi con nessun linguaggio e ora come ora mi sono documentato sommariamente sulla questione per ciò che concerne python.
Perché il Mac-Roman è un charset i cui simboli sono codificati come singoli byte, in maniera simile al Latin-1 e a tanti altri charset. In sostanza, vengono letti i byte così come sono, e problemi generalmente non ce ne sono (tranne per charset che usano meno di 256 simboli: se il codec usato da Python incontra byte non usati, solleva un'eccezione).
L'UTF-8, invece, ha una codifica ben diversa, ed è facile che leggendo un file che non sia UTF-8, ma Latin-1, Mac-Roman, o altro, il codec sollevi un'eccezione. Da ciò che ho capito leggendo un po' sulla documentazione di python, l'UTF è stato fatto per mappare in maniera intelligente tanti caratteri diversi in maniera univoca.
Ebbene, continuo a non capire perchè con UTF-8 leggendo il file mi deve dare problemi, non è stato fatto per risolverli? E se leggo flussi di byte, non dovrebbe semplicemente tradurmeli e mapparli con il giusto codice?
Il problema si presentava anche con UTF-32 :fagiano:
Esatto: è quello il motivo.
Quale? Che la while è sempre verificata? Com'è possibile? Una volta che la read() arriva a fine file, non dovrebbe essere False il risultato ( e uscire dal while )?
Inoltre ho provato anche:
while True:
c=fp.read(1024)
if c == '':
break
Non va..
Cerca di affrontare un solo problema alla volta. Affronta un (sotto) punto del problema B.2, e quando sei sicuro passa all'implementazione dell'altro.
Soltanto alla fine, quando avrai il codice funzionante per tutto, puoi cercare di vedere se e come ottimizzarlo.
Beh, in se funzionava il codice, ma non con file così grossi :asd:
Visto che si parla di effettuare dei conteggi, ti consiglio di usare la classe Counter del modulo collections, che fa proprio al caso tuo. ;)
Terrò a mente la cosa, perchè, forse per inesperienza, sto avendo serie difficoltà a prendere, per esempio, i singoli caratteri, o debuggare il codice carattere per carattere ( come avrei fatto in C ).
Trovo che tutto il sistema di read(), readline(), readlines() si faccia parecchio sentire che è di alto livello: faccio fatica ad analizzare la singola riga o i singoli pezzi di byte... :(
Da ciò che ho capito leggendo un po' sulla documentazione di python, l'UTF è stato fatto per mappare in maniera intelligente tanti caratteri diversi in maniera univoca.
Ebbene, continuo a non capire perchè con UTF-8 leggendo il file mi deve dare problemi, non è stato fatto per risolverli? E se leggo flussi di byte, non dovrebbe semplicemente tradurmeli e mapparli con il giusto codice?
Il problema si presentava anche con UTF-32 :fagiano:
L'unica cosa che fa UTF è specificare quale sia la rappresentazione binaria delle varie lettere quando le vai a scrivere su disco. Non si preoccupa della conversione da un tipo di codifica ad un'altro. Quando apri il file e dici a python che questo è utf8 ma dentro ci sono byte che, se interpretati con quella codifica, non hanno senso è chiaro che ti da errore.
cdimauro
05-02-2013, 08:26
Da ciò che ho capito leggendo un po' sulla documentazione di python, l'UTF è stato fatto per mappare in maniera intelligente tanti caratteri diversi in maniera univoca.
Ebbene, continuo a non capire perchè con UTF-8 leggendo il file mi deve dare problemi, non è stato fatto per risolverli? E se leggo flussi di byte, non dovrebbe semplicemente tradurmeli e mapparli con il giusto codice?
Il problema si presentava anche con UTF-32 :fagiano:
Vedi il messaggio di Vicius.
Quale? Che la while è sempre verificata? Com'è possibile? Una volta che la read() arriva a fine file, non dovrebbe essere False il risultato ( e uscire dal while )?
Inoltre ho provato anche:
while True:
c=fp.read(1024)
if c == '':
break
Non va..
ll problema è che quando richiami le tue funzioni, queste alla fine riavvolgono il file, tu poi leggi i primi 1024 byte, e quindi la stringa che ottieni è sempre non vuota.
Terrò a mente la cosa, perchè, forse per inesperienza, sto avendo serie difficoltà a prendere, per esempio, i singoli caratteri, o debuggare il codice carattere per carattere ( come avrei fatto in C ).
Trovo che tutto il sistema di read(), readline(), readlines() si faccia parecchio sentire che è di alto livello: faccio fatica ad analizzare la singola riga o i singoli pezzi di byte... :(
Ecco, il problema è forse quello: NON devi lavorare come stessi usando il C. Python è diverso, ha i suoi strumenti, e dovresti modellare il codice in funzione di ciò.
Nello specifico, per il punto B.2 la soluzione più semplice e immediata è, invece, proprio quella di usare readline (non readlines, perché satura la memoria, come abbiamo visto).
Vero è che tu devi avere a che fare con caratteri, parole, e linee, ma perché devi per forza partire coi primi e arrivare alle ultime? Meglio partire da una linea, visto che Python ha già una funzione per leggerle, e almeno per questo compito te lo risolve immediatamente.
All'interno di una riga ci sono poi le parole, e i caratteri. Per questi ultimi ti basterebbe (condizionale!) scorrere la stringa, perché ogni elemento di una stringa è un carattere; ma puoi evitarlo perché la classe Counter ti consente di ottenere lo scopo del sottopunto previsto per i caratteri, senza che tu faccia altro.
Infine anche per estrarre le parole puoi far ricorso ad appositi strumenti che Python mette a disposizione per le stringhe, da dare poi in pasto sempre a un oggetto Counter.
Ovviamente devi conoscere meglio Python, altrimenti finisci che vai a scrivere codice C, appunto, quando c'è di meglio e di più semplice a disposizione. Devi sviluppare, insomma, una mentalità da pythonista. ;)
Vincenzo1968
05-02-2013, 08:53
Cesare dixit: "Viene letto tutto il file in memoria con la .read(), per cui è facile che il processo muoia per mancanza di memoria."
Ma il file che ho aperto è di 1 GiB e io ho 4 GiB di ram. :confused:
Vincenzo1968
05-02-2013, 09:15
Spiego l'algoritmo che ho utilizzato:
Supponiamo di leggere il file in blocchi da 21 byte.
Questo è il file:
Questa è la prima riga.
Questa è la seconda riga.
Questa è la terza riga.
Questa è la quarta riga.
Questa è la quinta riga.
Leggendo il primo blocco da 21 byte abbiamo un buffer contenente la stringa:
Questa è la prima rig
Imposto la variabile sentinella a zero.
Per il conteggio delle parole leggo i byte dal buffer uno alla volta. Per ogni byte letto incremento di 1 il valore dela variabile sentinella.
Il primo carattere, 'Q', non è uno spazio quindi lo considero l'inizio di una parola. Continuo a leggere un byte alla volta fino a quando incontro uno spazio. Incontrando lo spazio, incremento di uno il conteggio delle parole. Continuo così fino a quando il valore della variabile sentinella è minore della dimensione del blocco.
Se la variabile sentinella mi dice che sono alla fine del blocco, leggo tramite read il successivo blocco di 21 byte e imposto il valore della variabile sentinella a 0.
Il secondo blocco letto è:
a.\nQuesta è la second
Leggendo il primo byte, 'a', capisco che è la continuazione della parola che avevo iniziato a leggere alla fine del primo blocco. Il carattere succesivo, '.' mi dice che la parola l'ho letta tutta e, dunque, incremento di uno il conteggio delle parole. Il carattere successivo, '\n', newline, mi dice che ho letto la prima riga e dunque incremento di uno il conteggio delle righe.
Si procede in questo modo fino alla lettura dell'ultimo blocco.
cdimauro
05-02-2013, 09:20
Cesare dixit: "Viene letto tutto il file in memoria con la .read(), per cui è facile che il processo muoia per mancanza di memoria."
Ma il file che ho aperto è di 1 GiB e io ho 4 GiB di ram. :confused:
Credo che dipenda dalla terza funzione invocata (countWords), che oltre a leggere l'intero file (e quindi consuma un bel po' di memoria già solo per questo) lo suddivide poi in parole, generando una mega lista finale.
Per processori a 64 bit, i puntatori e gli interi utilizzati internamente da Python nelle sue strutture occupano 8 byte ciascuno. Inoltre Python "internizza" (utilizza sempre lo stesso oggetto) soltanto le stringhe vuote o quelle che hanno soltanto un carattere, per cui in TUTTI gli altri casi vengono generati nuovi oggetti stringa (ognuno mi sembra che occupi almeno 32 byte).
Quindi non faccio fatica a immaginare che la memoria della tua macchina sia stata saturata.
EDIT: l'algoritmo che hai appena spiegato non serve in Python. Basta utilizzare un approccio "line-based", come ho spiegato prima, sfruttando poi altri strumenti di Python per elaborare i casi previsti.
Cesare dixit: "Viene letto tutto il file in memoria con la .read(), per cui è facile che il processo muoia per mancanza di memoria."
Ma il file che ho aperto è di 1 GiB e io ho 4 GiB di ram. :confused:
Ci sono una serie di fattori che possono limitare la quantità di memoria utilizzabile da un processo. Banalmente, i limiti (http://ss64.com/bash/ulimit.html) imposti dal sistema operativo.
Spiego l'algoritmo che ho utilizzato:
…
Separando la lettura delle righe dalla conta delle parole/caratteri potresti distribuire il carico su più core. Le righe sono tutte indipendenti tra loro quindi non c'è bisogno di alcuna sincronizzazione tra i vari thread. Le prestazioni scalerebbero quasi linearmente con il numero di processori usati. In questo caso forse è un po' forzato visto che quello che fai è semplice e sei comunque limitato dal disco. È comunque un approccio interessante e l'esperienza potrebbe sempre servirti in futuro.
Vincenzo1968
05-02-2013, 10:31
Separando la lettura delle righe dalla conta delle parole/caratteri potresti distribuire il carico su più core. Le righe sono tutte indipendenti tra loro quindi non c'è bisogno di alcuna sincronizzazione tra i vari thread. Le prestazioni scalerebbero quasi linearmente con il numero di processori usati. In questo caso forse è un po' forzato visto che quello che fai è semplice e sei comunque limitato dal disco. È comunque un approccio interessante e l'esperienza potrebbe sempre servirti in futuro.
Ottimo suggerimento! Grazieeeeee :D
Lo provo subito. Su Linux ho un dual core e quindi dovrei dimezzare i tempi. :D
Su Windows 8 ho quattro processori.
:yeah: :winner: :yeah:
EDIT: a proposito, su Windows so come creare e avviare più thread. Su Linux le api quali sono?
cdimauro
05-02-2013, 10:47
Cerca "pthread".
Vincenzo1968
05-02-2013, 11:25
Trovato questi:
https://computing.llnl.gov/tutorials/pthreads/
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
In attesa del libro "Advanced Linux Programming". La terza edizione dovrebbe uscire a marzo. L'edizione corrente è vecchiotta: 2005 :cry:
:D
L'unica cosa che fa UTF è specificare quale sia la rappresentazione binaria delle varie lettere quando le vai a scrivere su disco. Non si preoccupa della conversione da un tipo di codifica ad un'altro. Quando apri il file e dici a python che questo è utf8 ma dentro ci sono byte che, se interpretati con quella codifica, non hanno senso è chiaro che ti da errore.
Si ma allora qual è il significato di tutti sti encoding?
Si occupano solo di trasformare i byte grezzi non codificati?
E se leggo un file ( in python ) così:
open(file, 'rb')
Non dovrebbe trattarsi di una semplice sequenza di byte ( senza codifica ne niente )?
ll problema è che quando richiami le tue funzioni, queste alla fine riavvolgono il file, tu poi leggi i primi 1024 byte, e quindi la stringa che ottieni è sempre non vuota.
È vero che io faccio tornare il cursore a 0 alla fine di ogni funzione, ma è anche vero che prima di farlo, salvo la posizione corrente, e che poi al termine delle funzioni, do un:
fp.seek(currentPosition)
Che dovrebbe essere 1024 ( se ho preso il buffer da 1024 ).
Mi aspetto che al prossimo giro di while, il file pointer riprenda da 1024 byte fino a 1024+1024 :stordita:
Ecco, il problema è forse quello: NON devi lavorare come stessi usando il C. Python è diverso, ha i suoi strumenti, e dovresti modellare il codice in funzione di ciò.
Si ma capisci che non è facile sapere se una cosa esiste già o no?
Potrei stare a leggere ore e ore la documentazione ufficiale, spulciare le librerie e vedere se hanno quello che mi serve. Potrei googlare la cosa ( e forse trovare ciò che mi serve ) o chiedere a voi.
È tempo che perdo, anche se poi la soluzione si rivela migliore della mia :O
Il guaio di sti linguaggi con miliardi di librerie è che uno nuovo non sa mai dove andare...
Tipo, la libreria Counter: ma che ne so che in python c'è sta cosa.. Voglio dire, contare i caratteri o contare in generale è una cosa talmente banale che non mi aspettavo ci fosse una pappa pronta per farlo.. :D
Ovviamente devi conoscere meglio Python, altrimenti finisci che vai a scrivere codice C, appunto, quando c'è di meglio e di più semplice a disposizione. Devi sviluppare, insomma, una mentalità da pythonista. ;)Si, il problema è questo, inesperienza :D
È anche per questo che sto cercando di fare sto programma in python e non in C, anche se probabilmente con quest'ultimo raggiungerei un risultato migliore che in python.
Credo che dipenda dalla terza funzione invocata (countWords), che oltre a leggere l'intero file (e quindi consuma un bel po' di memoria già solo per questo) lo suddivide poi in parole, generando una mega lista finale.
Per processori a 64 bit, i puntatori e gli interi utilizzati internamente da Python nelle sue strutture occupano 8 byte ciascuno. Inoltre Python "internizza" (utilizza sempre lo stesso oggetto) soltanto le stringhe vuote o quelle che hanno soltanto un carattere, per cui in TUTTI gli altri casi vengono generati nuovi oggetti stringa (ognuno mi sembra che occupi almeno 32 byte).
Quindi non faccio fatica a immaginare che la memoria della tua macchina sia stata saturata.
Benchmark homemade :asd:
@Vincenzo1968: Il primo link che hai messo è quello che ti serve, tutto il resto che trovi su internet, sono esercizi di stile..
Vincenzo1968
05-02-2013, 11:51
È tempo che perdo, anche se poi la soluzione si rivela migliore della mia :O
...
Si, il problema è questo, inesperienza :D
È anche per questo che sto cercando di fare sto programma in python e non in C, anche se probabilmente con quest'ultimo raggiungerei un risultato migliore che in python.
Se applichi l'algoritmo che ho usato io, secondo me, ottieni prestazioni simili ai programmi in C ;)
Anche l'utilizzo delle risorse è più efficiente: soltanto 4 Kb di memoria.
Dunque il mio consiglio è: lascia perdere il pythonismo in questo caso. Questo è il caso di usare il C-tonismo. Abbiamo visto che col pythonismo, per i file grossi, ci pappiamo tutta la memoria.
E m'era venuto un colpo, all'inizio, leggendo "Ucciso". Ho detto: "che è successo? chi hanno ucciso?". Poi ho capito che Ubuntu mi traduce i messaggi in italiano, quindi "ucciso" stava per killed, processo terminato. :D
;)
Vincenzo1968
05-02-2013, 14:53
Ecco:
http://img22.imageshack.us/img22/1476/c19b02mypythonversion.jpg
import sys
def fileSize(n):
F = open(n,'r')
F.seek(0,2)
sz = F.tell()
F.seek(0,0)
F.close()
return sz
currPos = 0
nRows = 0
dimcurr = 0
dimBuffer = 4096
dimFile = fileSize(sys.argv[1])
f = file(sys.argv[1], 'rb')
while dimcurr < dimFile:
r = f.read(dimBuffer)
dimcurr += dimBuffer
while currPos < len(r) :
if r[currPos] == "\n" :
nRows += 1
currPos += 1
currPos = 0
f.close()
print "\nIl file contiene ", nRows, " righe\n"
Purtroppo col file da 1 GiB ci mette un sacco di tempo. :confused:
Vincenzo1968
05-02-2013, 15:04
Cacchio, non me l'aspettavo:
http://img194.imageshack.us/img194/4025/c19b02file1gib.jpg
:cry:
Vincenzo1968
05-02-2013, 15:19
provo ad aumentare le dimensioni del buffer:
dimBuffer = 1024 * 64
Vediamo che succede.
Vincenzo1968
05-02-2013, 15:25
Succede che non succede niente:
http://img10.imageshack.us/img10/7707/pythonschifio.jpg
Comunque il suo lavoro lo fa, senza esaurire la memoria. Almeno quello. ;)
Provo a implementarlo in Ruby.
È lento perché non è python. Quello è C mascherato.
Questo è python ed è 120 volte più veloce della tua versione. ;)
import sys;
lines = 0
with open(sys.argv[1], 'r') as file:
for line in file.xreadlines():
lines += 1
print 'ci sono %d righe' % lines
Vincenzo1968
05-02-2013, 15:48
È lento perché non è python. Quello è C mascherato.
Questo è python ed è 120 volte più veloce della tua versione. ;)
import sys;
lines = 0
with open(sys.argv[1], 'r') as file:
for line in file.xreadlines():
lines += 1
print 'ci sono %d righe' % lines
Perfetto, lo provo subito.
Mi posteresti anche l'equivalente in Ruby? Io lo faccio in "C mascherato da Ruby".
Così confrontiamo i tempi di tutt'e quattro le versioni.
:D
EDIT: Eh ma gli altri conteggi? Parole, parola più lunga, riga più lunga? Io ho messo solo il conteggio delle righe perché sono niubbo.
EDIT: In effetti c'impiega 1,8 secondi. Ma il resto? Parole, parola più lunga, riga più lunga?
Perfetto, lo provo subito.
Mi posteresti anche l'equivalente in Ruby? Io lo faccio in "C mascherato da Ruby".
Non ho ruby per provarlo e non mi ricordo se è argv[1] o argv[0]. Prova te.
File.open(ARGV[1]) do |file|
lines = file.each_line.inject(0) do |c, line|
c += 1
end
puts "ci sono #{lines} righe"
end
EDIT: Eh ma gli altri conteggi? Parole, parola più lunga, riga più lunga? Io ho messo solo il conteggio delle righe perché sono niubbo.
EDIT: In effetti c'impiega 1,8 secondi. Ma il resto? Parole, parola più lunga, riga più lunga?
Io ti ho fatto la traccia. Ora finiscilo. :D
Vincenzo1968
05-02-2013, 16:22
c19b02Vicius.rb:1:in `initialize': can't convert nil into String (TypeError)
from c19b02Vicius.rb:1:in `open'
from c19b02Vicius.rb:1:in `<main>'
Ah no, bisognava passare ARGV[0] anziché ARGV[1].
Vincenzo1968
05-02-2013, 16:43
Non ho ruby per provarlo e non mi ricordo se è argv[1] o argv[0]. Prova te.
File.open(ARGV[1]) do |file|
lines = file.each_line.inject(0) do |c, line|
c += 1
end
puts "ci sono #{lines} righe"
end
Io ti ho fatto la traccia. Ora finiscilo. :D
Comunque ci ha già provato Kwb e abbiamo visto che Python esaurisce la memoria. O c'è qualche altro modo?
È la split che fa il danno nel codice di Kwb. Non c'è qualche altro modo di contare le parole?
def countWords(fp):
p=fp.read().split()
print 'Ci sono {} parole nel file di testo' .format(len(p))
fp.seek(0)
EDIT: Scusate... Sto scrivendo delle boiate..
Vincenzo1968
05-02-2013, 17:28
Comunque, kwb, ci siamo quasi. Se commento le funzioni che usano split, la tua applicazione ci mette circa 20 secondi che non è niente male(è più veloce di wc).
countChars(fp)
countLines(fp)
#countWords(fp)
longLine(fp)
#longWord(fp)
Bisogna trovare il modo di non utilizzare split per il conteggio delle parole.
Vincenzo1968
05-02-2013, 17:37
Cesare dixit: "Visto che si parla di effettuare dei conteggi, ti consiglio di usare la classe Counter del modulo collections, che fa proprio al caso tuo."
Questa me l'ero persa. Come si usa la classe Counter?
EDIT: Sono riuscito a usarla per contare le righe:
fp=open(sys.argv[1],'r')
cnt = collections.Counter()
for lines in fp.read():
cnt[lines] += 1
print 'Ci sono : %d righe' % (cnt[lines])
fp.close()
Per contare le parole come si fa?
Vincenzo: http://docs.python.org/2/library/collections.html#collections.Counter
Vi dico che ho masterato il problema.
ORA ARRIVO! :cool:
Vincenzo1968
05-02-2013, 18:16
Vincenzo: http://docs.python.org/2/library/collections.html#collections.Counter
Vi dico che ho masterato il problema.
ORA ARRIVO! :cool:
Meraviglioso! :D
cdimauro
05-02-2013, 18:31
Si ma allora qual è il significato di tutti sti encoding?
Si occupano solo di trasformare i byte grezzi non codificati?
E se leggo un file ( in python ) così:
open(file, 'rb')
Non dovrebbe trattarsi di una semplice sequenza di byte ( senza codifica ne niente )?
Esattamente, ma i byte come li interpreti? Col codec giusto, riesci a farlo, perché sa come gestire e generare i simboli (Unicode) corretti.
Per fare un esempio, se hai un testo codificato come Latin-1, e lo leggi specificando Mac-Roman come encoding, sai cosa succede? Che anche se non ti viene sollevata nessuna eccezione, quando vai a visualizzare il risultato della lettura otterrai dei caratteri sballati. Questo perché Mac-Roman e Latin-1 fanno corrispondere simboli diversi allo stesso valore del byte che è stato letto.
È vero che io faccio tornare il cursore a 0 alla fine di ogni funzione, ma è anche vero che prima di farlo, salvo la posizione corrente, e che poi al termine delle funzioni, do un:
fp.seek(currentPosition)
Che dovrebbe essere 1024 ( se ho preso il buffer da 1024 ).
Mi aspetto che al prossimo giro di while, il file pointer riprenda da 1024 byte fino a 1024+1024 :stordita:
Per favore, posta il codice completo, perché mi sono incartato. Così lo analizzo e cerco di capire cosa c'è che non va.
Si ma capisci che non è facile sapere se una cosa esiste già o no?
Potrei stare a leggere ore e ore la documentazione ufficiale, spulciare le librerie e vedere se hanno quello che mi serve. Potrei googlare la cosa ( e forse trovare ciò che mi serve ) o chiedere a voi.
È tempo che perdo, anche se poi la soluzione si rivela migliore della mia :O
Il guaio di sti linguaggi con miliardi di librerie è che uno nuovo non sa mai dove andare...
Tipo, la libreria Counter: ma che ne so che in python c'è sta cosa.. Voglio dire, contare i caratteri o contare in generale è una cosa talmente banale che non mi aspettavo ci fosse una pappa pronta per farlo.. :D
Si, il problema è questo, inesperienza :D
È anche per questo che sto cercando di fare sto programma in python e non in C, anche se probabilmente con quest'ultimo raggiungerei un risultato migliore che in python.
Purtroppo l'esperienza è importante a prescindere dal linguaggio, ma non ti credere che conosca tutti i metodi degli oggetti, e tutte le funzioni o classi della libreria standard. Ne ho una buona visione, e so cercare velocemente quello che mi serve.
Se applichi l'algoritmo che ho usato io, secondo me, ottieni prestazioni simili ai programmi in C ;)
Anche l'utilizzo delle risorse è più efficiente: soltanto 4 Kb di memoria.
Dunque il mio consiglio è: lascia perdere il pythonismo in questo caso. Questo è il caso di usare il C-tonismo. Abbiamo visto che col pythonismo, per i file grossi, ci pappiamo tutta la memoria.
Purtroppo non conosci Python e giudichi troppo in fretta, come ti ha mostrato Vicius.
Nel miei precedenti messaggi in cui discutevo dei problemi di memoria, e in cui suggerivo l'approccio (line-based) da usare, c'era già la soluzione sia ai problemi di occupazione di memoria che delle prestazioni.
Non voglio dilungarmi, ma il concetto che voglio far passare è il seguente: i metodi, le funzioni, e le classi che Python mette a disposizione non sono stati messi lì per caso, o esclusivamente per evitare di scrivere parecchio codice. Non si capirebbe, altrimenti, per quale motivo TUTTI gli oggetti standard di Python (leggi: tutti i metodi o le proprietà esposti) siano scritti in C, come pure diversi moduli della libreria standard: sarebbe stato sufficiente fare lo stesso, ma lasciandoli in puro Python, no?
Invece sono stati scritti così per ottimizzare l'esecuzione e/o lo spazio occupato. Altrimenti un metodo come readline, ad esempio, sarebbe lento quanto la tua implementazione; ergo: Python non avrebbe avuto tutto questo successo, poiché sarebbe stato troppo inefficiente per codice di produzione.
Cacchio, non me l'aspettavo:
http://img194.imageshack.us/img194/4025/c19b02file1gib.jpg
:cry:
Io sì, ma ho preferito che ti facessi male da solo. :asd:
È lento perché non è python. Quello è C mascherato.
Questo è python ed è 120 volte più veloce della tua versione. ;)
import sys;
lines = 0
with open(sys.argv[1], 'r') as file:
for line in file.xreadlines():
lines += 1
print 'ci sono %d righe' % lines
Molto interessante la soluzione con xreadlines. Avevo dimenticato l'esistenza di questo metodo.
EDIT: Eh ma gli altri conteggi? Parole, parola più lunga, riga più lunga? Io ho messo solo il conteggio delle righe perché sono niubbo.
EDIT: In effetti c'impiega 1,8 secondi. Ma il resto? Parole, parola più lunga, riga più lunga?
Sì può fare senza ricorrere all'approccio C-like. :cool:
Comunque ci ha già provato Kwb e abbiamo visto che Python esaurisce la memoria. O c'è qualche altro modo?
È la split che fa il danno nel codice di Kwb. Non c'è qualche altro modo di contare le parole?
def countWords(fp):
p=fp.read().split()
print 'Ci sono {} parole nel file di testo' .format(len(p))
fp.seek(0)
Sì, c'è un altro modo: la split. Ma usata come si deve. :fiu:
Comunque, kwb, ci siamo quasi. Se commento le funzioni che usano split, la tua applicazione ci mette circa 20 secondi che non è niente male(è più veloce di wc).
countChars(fp)
countLines(fp)
#countWords(fp)
longLine(fp)
#longWord(fp)
Bisogna trovare il modo di non utilizzare split per il conteggio delle parole.
Bisogna trovare il modo di usarla bene, invece. Io l'avevo suggerito anche prima; molto prima. ;)
Cesare dixit: "Visto che si parla di effettuare dei conteggi, ti consiglio di usare la classe Counter del modulo collections, che fa proprio al caso tuo."
Questa me l'ero persa. Come si usa la classe Counter?
EDIT: Sono riuscito a usarla per contare le righe:
fp=open(sys.argv[1],'r')
cnt = collections.Counter()
for lines in fp.read():
cnt[word] += 1
print 'Ci sono : %d righe' % (cnt[lines])
Per contare le parole come si fa?
Ricava le parole. Gli ingredienti li hai quasi tutti. La split, ormai spero sia chiaro che si debba usare, no? Pensateci un po'.
Vincenzo1968
05-02-2013, 18:46
Ragazzi, con la classe Counter ci vogliono 14 minuti solo per contare le righe:
http://img692.imageshack.us/img692/672/counterschifio.jpg
import sys
import codecs as cd
import collections
fp=open(sys.argv[1],'r')
cnt = collections.Counter()
for lines in fp.read():
cnt[lines] += 1
print 'Ci sono : %d righe' % (cnt[lines])
#countChars(fp)
#countLines(fp)
#countWords(fp)
#longLine(fp)
#longWord(fp)
fp.close()
Ok, ci sono.
Alcune note prima di postare il codice: causa sta storia della codifica dei caratteri, il conto è quasi giusto. Ho cercato di escludere cose che non erano caratteri ( vedrete il codice ).
Per l'apertura del file, smanettate voi perchè io non ho ancora capito la questione... :muro:
# -*- coding: mac-roman -*-
import sys
import codecs as cd
def fileSize(fp):
fp.seek(0,2)
result=fp.tell()
fp.seek(0)
return result
lines=[]
words=[]
chars=0
buffer=4096
currentDim=0
f=''
longestLine=''
longestWord=''
#fp=cd.open(sys.argv[1],'rb',encoding='mac-roman')
fp=open(sys.argv[1],'rb')
totSize=fileSize(fp)
while currentDim < totSize:
f+=fp.read(buffer)
lines=f.split('\n')
currentDim+=buffer
fp.close()
#Righe
print 'Righe: ',len(lines)
for i in lines:
words+=i.split(' ')
#Parole
for i in words:
if i == '' or i == '\r':
words.remove(i)
print 'Parole: ',len(words)
#Caratteri
for i in words:
chars+=len(i)
print 'Caratteri: ', chars
#Riga lunga
for i in lines:
if len(longestLine) < len(i):
longestLine = i
print 'La riga piu\' lunga e\':\n\t', longestLine,'\nCaratteri: ',len(longestLine)
for i in words:
if len(longestWord) < len(i):
longestWord = i
print 'La parola piu\' lunga e\': ', longestWord,'\nHa {} caratteri'.format(len(longestWord))
@cdimauro: Volevo usare i counter, ma devo dire che non avrei saputo come impiegarli... :stordita:
@Vincenzo1968: Se non funziona abbandono la nave, lo dico in anticipo. Ho terminato il tempo a disposizione :(
Vincenzo1968
05-02-2013, 18:55
Cesare, io qui non mi "faccio male da solo", io qui mi diverto.
Sarebbe utile se tu ogni tanto postassi due righe di codice. Come vedi si trattava di due righe(alla lettera: DUE) di codice per l'esempio della classe Counter. Ma, io, essendo niubbo, ho dovuto faticare un pochino prima di capire come funzionava.
Se ogni tanto postassi qualcosina non sarebbe male. Lo dico nell'interesse degli appassionati di Python(e, come ben sai, sono in tanti qui).
Da parte mia me ne potrei stracatafottere di Python. Mi tengo il C e buona notte ai suonatori(anzi ai programmatori).
;)
Esattamente, ma i byte come li interpreti? Col codec giusto, riesci a farlo, perché sa come gestire e generare i simboli (Unicode) corretti.
Per fare un esempio, se hai un testo codificato come Latin-1, e lo leggi specificando Mac-Roman come encoding, sai cosa succede? Che anche se non ti viene sollevata nessuna eccezione, quando vai a visualizzare il risultato della lettura otterrai dei caratteri sballati. Questo perché Mac-Roman e Latin-1 fanno corrispondere simboli diversi allo stesso valore del byte che è stato letto.
Bene, ma se io apro sto benedetto file così:
fp=codecs.open(file,'rb',encoding='utf-8')
Non dovrebbero esserci problemi nella visualizzazione, indipendentemente dal tipo di codifica usata sul file.
Perchè se prendo un semplice ammasso di byte ( 'rb' ), questi dovrebbero essere facili da mappare in utf-8, no?
Oppure ( forse inizio ad intuire la questione ), i byte, per essere letti come byte senza codifica, devono essere prima decodificati dalla codifica in cui sono e poi ricodificati come servono? :stordita:
Vincenzo1968
05-02-2013, 19:00
Ok, ci sono.
Alcune note prima di postare il codice: causa sta storia della codifica dei caratteri, il conto è quasi giusto. Ho cercato di escludere cose che non erano caratteri ( vedrete il codice ).
Per l'apertura del file, smanettate voi perchè io non ho ancora capito la questione... :muro:
# -*- coding: mac-roman -*-
import sys
import codecs as cd
def fileSize(fp):
fp.seek(0,2)
result=fp.tell()
fp.seek(0)
return result
lines=[]
words=[]
chars=0
buffer=4096
currentDim=0
f=''
longestLine=''
longestWord=''
#fp=cd.open(sys.argv[1],'rb',encoding='mac-roman')
fp=open(sys.argv[1],'rb')
totSize=fileSize(fp)
while currentDim < totSize:
f+=fp.read(buffer)
lines=f.split('\n')
currentDim+=buffer
fp.close()
#Righe
print 'Righe: ',len(lines)
for i in lines:
words+=i.split(' ')
#Parole
for i in words:
if i == '' or i == '\r':
words.remove(i)
print 'Parole: ',len(words)
#Caratteri
for i in words:
chars+=len(i)
print 'Caratteri: ', chars
#Riga lunga
for i in lines:
if len(longestLine) < len(i):
longestLine = i
print 'La riga piu\' lunga e\':\n\t', longestLine,'\nCaratteri: ',len(longestLine)
for i in words:
if len(longestWord) < len(i):
longestWord = i
print 'La parola piu\' lunga e\': ', longestWord,'\nHa {} caratteri'.format(len(longestWord))
@cdimauro: Volevo usare i counter, ma devo dire che non avrei saputo come impiegarli... :stordita:
@Vincenzo1968: Se non funziona abbandono la nave, lo dico in anticipo. Ho terminato il tempo a disposizione :(
Kwb, mi sa che ci siamo :D Questi i risultati sul file piccolo da 9 righe:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time python c19b02KwbNew.py filePiccolo.txt
Righe: 10
Parole: 32
Caratteri: 244
La riga piu' lunga e':
Quest'altra riga contiene parole all'interno di {parentesi graffe}.
Caratteri: 67
La parola piu' lunga e': #$££$%$%%£££$$
Ha 19 caratteri
real 0m0.099s
user 0m0.044s
sys 0m0.016s
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$
Adesso lo provo col file da 1 GiB. ;)
Vincenzo1968
05-02-2013, 19:18
Purtroppo cattive notizie almeno per quanto riguarda i tempi: è da più di dieci minuti che l'ho avviato e ancora il programma è in esecuzione.
Comunque non si blocca, non viene "ucciso". ;)
Porca mignotta proprio non si riesce a venirne a capo con python?
http://www.hwupgrade.org/public/style_emoticons/default/rage.png
Vincenzo1968
05-02-2013, 19:23
Niente, ho dovuto forzare l'uscita chiudendo il terminale. Ancora non terminava.
Mo lo provo su un file da 100 MB.
Vincenzo1968
05-02-2013, 19:30
E comunque, Cesare, il mio algoritmo è velocissimo in C(solo 7 secondi su un file da 1 GiB; e trova tutto: numero righe, numero parole, riga più lunga, parola più lunga). È con Python che ci mette 6 minuti(solo per trovare il numero di righe!). Che cacchio fa Python?
Se ho bisogno di gestire file binari e debbo usare read e write al posto di readlines?
cdimauro
05-02-2013, 19:33
Mi spiace, ma stasera non ce la faccio a darvi una mano: non sto bene, e mi sto mettendo a letto.
Se domani sono in grado di intendere e di volere, e non avete ancora risolto, cerco di scrivere qualche riga.
Al momento una dritta veloce per contare le righe: non date in pasto l'intero contenuto del file (.read()) all'oggetto Counter. Leggete una riga alla volta, usando xreadlines(), come ha fatto Vicius, e una volta che avete la riga, datela in pasto al Counter.
Per le parole: per ogni riga letta, splittatela, in modo da ottenere una lista di parole (è quel che fa il metodo split, appunto). A questo punto usate un altro oggetto Counter dedicato alle parole, scorrendo una alla volta le parole ottenete dal precedente split. C'è un'altra soluzione, ma al momento preferisco non parlarne.
Per i caratteri è banale: scorrete un carattere alla volta la riga letta, e lo date in pasto al Counter creato appositamente per i caratteri.
Ultima cosa: NON USATE I BUFFER MODELLO C. Altrimenti i tempi che ottenete sono quelli che sono già stati ottenuti.
Buona notte.
Vincenzo1968
05-02-2013, 19:40
Niente nemmeno con un file da 100 MB riesce a terminare entro dieci minuti.
Provo con un file da 10 MB.
EDIT:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ ./c19AnonimoVeneziano1 fileA_100MB.txt -D10MB
Files loaded, it took: 0.040000 seconds
File processing finished, it took: 0.100000 seconds
Final file output finished, it took: 0.040000 seconds
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time python c19b02KwbNew.py fileA_10MB.txt
Traceback (most recent call last):
File "c19b02KwbNew.py", line 21, in <module>
fp=open(sys.argv[1],'rb')
IOError: [Errno 2] No such file or directory: 'fileA_10MB.txt'
real 0m0.058s
user 0m0.052s
sys 0m0.004s
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ ./c19AnonimoVeneziano1 fileA_10MB.txt -D10MB
Files loaded, it took: 0.060000 seconds
File processing finished, it took: 0.220000 seconds
Final file output finished, it took: 0.050000 seconds
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time python c19b02KwbNew.py fileA_10MB.txt
Righe: 48857
Parole: 1737027
Caratteri: 8748227
La parola piu' lunga e': ................................................................................................................................................................................................................................................
Ha 240 caratteri
real 0m54.973s
user 0m54.699s
sys 0m0.232s
Boh, io c'ho provato :muro:
Sinceramente non so come fare.. :mc:
Devo dire che ero molto fiducioso su questo codice scritto, pensavo fosse molto meglio ( o così sembrava... ).
Effettivamente anche a me un file da 10MB ci mette circa 1 minuto:
real 0m56.455s
user 0m54.759s
sys 0m1.564s
Eppure boh, ero convinto fosse più veloce, anche perchè la lettura del file viene eseguita una e una sola volta.. Mha :(
EDIT: Mmmmmmm... Mi sto ricredendo.
Pensavo che il problema principale fosse il leggere da file, in realtà anche agire sui dati già in memoria è un problema... Infatti per creare la lista words ci mette parecchio... Non so come fare...
EDIT2: Ho analizzato un po' la situa.
Il codice che ho scritto io, ci mette per preparare la prima lista 33.5 secondi con un file da 10MB....
EDIT 3: Ora va meglio! È lo split che è una cagna e ci mette una vita... Comunque:
import sys
import codecs as cd
import time
def fileSize(fp):
fp.seek(0,2)
result=fp.tell()
fp.seek(0)
return result
lines=[]
words=[]
chars=0
buffer=4096
currentDim=0
f=''
longestLine=''
longestWord=''
#fp=cd.open(sys.argv[1],'rb')
fp=open(sys.argv[1],'rb')
totSize=fileSize(fp)
while currentDim < totSize:
f+=fp.read(buffer)
currentDim+=buffer
fp.close()
lines=f.split('\n')
print 'Chiudo il file a: ', time.clock()
#Righe
print 'Righe: ',len(lines)
for i in lines:
words+=i.split(' ')
for i in lines:
if len(longestLine) < len(i):
longestLine=i
print 'La riga piu\' lunga e\':\n\t', longestLine,'\nHa {} caratteri: '.format(len(longestLine))
#Parole
for i in words:
if i == '' or i == '\r':
words.remove(i)
print 'Parole: ',len(words)
#Caratteri
for i in words:
chars+=len(i)
if len(longestWord) < len(i):
longestWord = i
print 'La parola piu\' lunga e\': ', longestWord,'\nHa {} caratteri'.format(len(longestWord))
print 'Caratteri: ', chars
Impiega 30secondi per un file da 10MB
È ancora troppo ma è meglio...
Vincenzo1968
05-02-2013, 21:41
Kwb, comunque noi ci abbiamo provato. Ora tocca agli esperti di Python postare un po' di codice. Dopo 30 pagine sarebbe pure ora.
Io mi sono rotto dei consigli: fai così, fai colà, usa questo, usa quello.
In pratica io le mie conclusioni su Python le ho già tratte, e sono queste: Python non è adatto per gestire file di grosse dimensioni. Fa schifo da questo punto di vista.
A meno che qualcuno non mi faccia cambiare idea ma coi fatti, ma col codice postato. Basta chiacchiere. Come si suol dire dalle mie parti, le chiacchiere stanno a zero.
Grazie comunque per aver partecipato, per averci messo l'anima. ;)
Casomai noi che programmiamo anche in C, ci arrangiamo con questo linguaggio per i file grossi. Loro, quelli che programmano solo coi linguaggi ad alto livello, s'attaccano al tram. ;)
Ma, ripeto, spero tanto, nell'interesse di tutti(e molti, qui, sono affezionati a questo linguaggio), che qualche esperto mi faccia cambiare idea e si decida finalmente a postarla questa benedetta soluzione in Python(se esiste una soluzione).
;)
Kwb, comunque noi ci abbiamo provato. Ora tocca agli esperti di Python postare un po' di codice. Dopo 30 pagine sarebbe pure ora.
Io mi sono rotto dei consigli: fai così, fai colà, usa questo, usa quello.
La gente partecipa se ha tempo.
Se non ha tempo, da consigli se riesce :)
Ora non c'è da dare la colpa ai draghi di python perchè io o te non siamo capaci ad usarlo :D
Io c'ho provato, è andata male, bon. ;)
In pratica io le mie conclusioni su Python le ho già tratte, e sono queste: Python non è adatto per gestire file di grosse dimensioni. Fa schifo da questo punto di vista.
A meno che qualcuno non mi faccia cambiare idea ma coi fatti, ma col codice postato. Basta chiacchiere. Come si suol dire dalle mie parti, le chiacchiere stanno a zero.
Mi sono letto un po' di cose sullo string matching in python. Ci sono alcune funzioni che possono tornare utili ( ma che devo provare perchè non so quanto meglio possano fare di una ricerca pura come ho fatto, C-Style ).
Tieni conto però che ci mette così tanto per eliminare il superfluo, infatti le parti problematiche sono queste due:
#Parole
for i in words:
if i == '' or i == '\r':
words.remove(i)
print 'Parole: ',len(words)
#Caratteri
for i in words:
chars+=len(i)
if len(longestWord) < len(i):
longestWord = i
Credo che se si riuscisse a trovare un qualche modo che riesca a togliere i caratteri 'stupidi' in maniera rapida ( mooolto più rapida della mia di adesso ) il programma potrebbe tener testa anche ai più veloci.
Chiaro, si tratta di avere un qualche suggerimento da parte di qualcuno esperto :D
Casomai noi che programmiamo anche in C, ci arrangiamo con questo linguaggio per i file grossi. Loro, quelli che programmano solo coi linguaggi ad alto livello, s'attaccano al tram. ;)
Se parteciperò ad un altro contest, penso lo farò sempre in python.
Non mi interessa essere il migliore ( almeno non per ora ), ma imparare ad usare il linguaggio scelto per bene..
Vincenzo1968
05-02-2013, 23:51
Ho preso il codice di Kwb e l'ho modificato secondo i consigli di Vicius. Finalmente abbiamo una versione di Python con tempi accettabili anche su un file da 1 GiB:
http://img405.imageshack.us/img405/8012/kwbandme.jpg
import sys
import string
def fileSize(fp):
fp.seek(0,2)
result=fp.tell()
fp.seek(0)
return result
currWordLen = 0
maxWordLen = 0
currLineLen = 0
maxLineLen = 0
lines = 0
words = 0
chars = 0
longestWord = ''
fp = open(sys.argv[1], 'r')
chars = fileSize(fp)
with open(sys.argv[1], 'r') as file:
for line in file.xreadlines():
list = string.split(line)
words += len(list)
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
lines += 1
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word
fp.close()
print 'Nel file ci sono {} caratteri: '.format(chars)
print 'Nel file ci sono {} righe: '.format(lines)
print 'La riga piu\' lunga ha {} caratteri: '.format(maxLineLen)
print 'Nel file ci sono {} parole: '.format(words)
print 'La parola piu\' lunga ha {} caratteri: '.format(maxWordLen)
print 'Ecco una delle parole piu\' lunghe: {} '.format(longestWord)
Bisogna sistemarlo. Come parola più lunga restituisce ".................................................... etc etc" :D come la versione JavaScript di Vicius.
cdimauro
06-02-2013, 08:19
Il codice che calcola la parola più lunga mi sembra corretto. Non vedo perché dovrebbe essere sistemato. Ho aggiunto anche il calcolo della linea più lunga, che era richiesto nel punto B.2.
Di seguito ho dato una sistemata al tuo codice, rendendolo più "pythonico":
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
def Main():
def fileSize(f):
f.seek(0, 2)
result = f.tell()
f.seek(0)
return result
currWordLen = maxWordLen = currLineLen = maxLineLen = lines = words = chars = 0
longestWord = longestLine = ''
with open(sys.argv[1], 'r') as f:
chars = fileSize(f)
for line in f:
lines += 1
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
longestLine = line
list = line.split()
words += len(list)
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word
print 'Nel file ci sono {} caratteri: '.format(chars)
print 'Nel file ci sono {} righe: '.format(lines)
print 'La riga più lunga ha {} caratteri: '.format(maxLineLen)
print 'Ecco una delle righe più lunghe: {} '.format(longestLine)
print 'Nel file ci sono {} parole: '.format(words)
print 'La parola più lunga ha {} caratteri: '.format(maxWordLen)
print 'Ecco una delle parole più lunghe: {} '.format(longestWord)
Main()
Se ti rileggi i miei precedenti messaggi, quello che hai realizzato ricalca all'incirca le indicazioni che avevo fornito.
L'unica cosa diversa è l'uso dell'oggetto Counter, che non serve. Avevo capito che servisse contare il numero di volte che i caratteri, le parole, le linee, ecc. ricorrono nel testo, e in tal caso l'oggetto Counter capita a fagiolo.
Alcune considerazioni. Ho tolto di mezzo il modulo string, che è deprecato, perché tutte le stringhe hanno già il metodo split, e quindi basta richiamarlo. Ho tolto anche xreadlines(), perché per iterare un file riga per riga è sufficiente specificare direttamente l'oggetto file nel for. Altra cosa, ho messo tutto dentro la funzione Main, perché in questo modo tutte le variabili assegnate al suo interno diventano locali, e quindi l'accesso è molto più veloce rispetto alle variabili globali / built-in, che sono quelle che vengono create al "top level" di un modulo; tenetelo presente per il futuro. Infine, ho sistemato l'uso del file, che adesso viene aperto soltanto una volta.
Vincenzo, mi spiace che ti sia seccato, ma mi sembra di essere stato chiaro: io non partecipo ai contest. Ho fornito dei suggerimenti in modo da cercare di sfruttare meglio Python, e alla fine tu ci sei arrivato, mi pare, no?
Anche i tuoi giudizi prematuri e preconcetti su Python mi sembra siano rientrati con la tua ultima versione: il codice "pythonico" si è mostrato più efficiente, e di molto, rispetto a quello "C-like" che avevate scritto prima, al contrario delle previsioni infauste.
Ora, non è che ho goduto nel vederti sbattere la testa con la tua versione C-like. Immaginavo come sarebbe andata a finire, perché conosco molto bene gli "internal" della macchina virtuale di Python. Tu, però, eri troppo convinto della superiorità dell'approccio "C-like", per cui ho preferito che toccassi con mano la situazione reale. Tutto qui.
Adesso torno un po' a letto a riposare, perché sto ancora male. Più tardi mi ricollego. Buona giornata.
Vincenzo1968
06-02-2013, 08:50
Ecco perché non è corretto:
http://img18.imageshack.us/img18/4654/c19b02mycsolution.jpg
La parola più lunga è lunga 27 byte. A meno di non voler considerare parola la stringa:
"..................................................................................................................."
;)
Vincenzo1968
06-02-2013, 09:07
Vincenzo, mi spiace che ti sia seccato, ma mi sembra di essere stato chiaro: io non partecipo ai contest. Ho fornito dei suggerimenti in modo da cercare di sfruttare meglio Python, e alla fine tu ci sei arrivato, mi pare, no?
Anche i tuoi giudizi prematuri e preconcetti su Python mi sembra siano rientrati con la tua ultima versione: il codice "pythonico" si è mostrato più efficiente, e di molto, rispetto a quello "C-like" che avevate scritto prima, al contrario delle previsioni infauste.
Ora, non è che ho goduto nel vederti sbattere la testa con la tua versione C-like. Immaginavo come sarebbe andata a finire, perché conosco molto bene gli "internal" della macchina virtuale di Python. Tu, però, eri troppo convinto della superiorità dell'approccio "C-like", per cui ho preferito che toccassi con mano la situazione reale. Tutto qui.
Adesso torno un po' a letto a riposare, perché sto ancora male. Più tardi mi ricollego. Buona giornata.
Il mio non è un approccio C-Like. È un algoritmo che utilizza un automa a stati finiti. Ed è l'approccio migliore, in generale, come mostrano i tempi della mia applicazione(più veloce anche di wc, l'applicazione fornita su Linux). È il metodo che utilizzano i compilatori per l'analisi lessicale.
Anche in C avrei potuto utilizzare il metodo della lettura riga per riga con fgets. E infatti a WarDuck era giustamente venuto il dubbio che forse era il caso di utilizzarlo, visto che funzioni come strstr sono implementate con algoritmi efficienti come Boyer-Moore.
Ho fatto la prova. Risultato: fgets e strstr 50 secondi circa; automa a stati finiti, 7 secondi.
Quindi l'algoritmo è risultato essere il migliore. Ed ero convinto che anche con Python o con qualsiasi altro linguaggio, l'applicazione dell'algoritmo avrebbe dato risultati migliori. Invece sembra che python non gestisca efficientemente la lettura/scrittura di blocchi di byte grezzi con read/write.
Ma a questo punto è colpa di Python, non dell'algoritmo, non dell'automa a stati finiti.
Ora la domanda è: se avessimo bisogno di trattare dati grezzi? File binari, non di testo? C'è un modo efficiente di trattarli in Python?
Auguri di pronta guarigione e spero di tornare a leggerti presto. Non sono d'accordo col 99% delle cose che dici ma è ugualmente stimolante leggerti. ;)
Vincenzo1968
06-02-2013, 09:22
Tempi nettamente migliori per la versione di Cesare che batte la versione JavaScript di Vicius(ma non wc):
http://img201.imageshack.us/img201/1338/c19b02cesareversion.jpg
:D
Edit: c'è sempre da sistemare il conteggio della parola più lunga(e la stampa di una delle parole più lunghe).
Vincenzo1968
06-02-2013, 09:55
L'unica cosa diversa è l'uso dell'oggetto Counter, che non serve. Avevo capito che servisse contare il numero di volte che i caratteri, le parole, le linee, ecc. ricorrono nel testo, e in tal caso l'oggetto Counter capita a fagiolo.
Ah benissimo, questo possiamo metterlo nel punto B.4: Conteggio delle occorrenze di ogni parola trovata nel file. Stampa, in ordine alfabetico, delle ventuno(o trentaquattro) parole più frequenti.
;)
Ho preso il codice di Kwb e l'ho modificato secondo i consigli di Vicius. Finalmente abbiamo una versione di Python con tempi accettabili anche su un file da 1 GiB:
http://img405.imageshack.us/img405/8012/kwbandme.jpg
import sys
import string
def fileSize(fp):
fp.seek(0,2)
result=fp.tell()
fp.seek(0)
return result
currWordLen = 0
maxWordLen = 0
currLineLen = 0
maxLineLen = 0
lines = 0
words = 0
chars = 0
longestWord = ''
fp = open(sys.argv[1], 'r')
chars = fileSize(fp)
with open(sys.argv[1], 'r') as file:
for line in file.xreadlines():
list = string.split(line)
words += len(list)
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
lines += 1
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word
fp.close()
print 'Nel file ci sono {} caratteri: '.format(chars)
print 'Nel file ci sono {} righe: '.format(lines)
print 'La riga piu\' lunga ha {} caratteri: '.format(maxLineLen)
print 'Nel file ci sono {} parole: '.format(words)
print 'La parola piu\' lunga ha {} caratteri: '.format(maxWordLen)
print 'Ecco una delle parole piu\' lunghe: {} '.format(longestWord)
Bisogna sistemarlo. Come parola più lunga restituisce ".................................................... etc etc" :D come la versione JavaScript di Vicius.
Scusate eh, ma mi avete fatto una testa tanta con sto buffer, e poi lo avete campato via appena ho chiuso baracca e burattini? :mbe: :D
Il codice che calcola la parola più lunga mi sembra corretto. Non vedo perché dovrebbe essere sistemato. Ho aggiunto anche il calcolo della linea più lunga, che era richiesto nel punto B.2.
Di seguito ho dato una sistemata al tuo codice, rendendolo più "pythonico":
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
def Main():
def fileSize(f):
f.seek(0, 2)
result = f.tell()
f.seek(0)
return result
currWordLen = maxWordLen = currLineLen = maxLineLen = lines = words = chars = 0
longestWord = longestLine = ''
with open(sys.argv[1], 'r') as f:
chars = fileSize(f)
for line in f:
lines += 1
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
longestLine = line
list = line.split()
words += len(list)
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word
print 'Nel file ci sono {} caratteri: '.format(chars)
print 'Nel file ci sono {} righe: '.format(lines)
print 'La riga più lunga ha {} caratteri: '.format(maxLineLen)
print 'Ecco una delle righe più lunghe: {} '.format(longestLine)
print 'Nel file ci sono {} parole: '.format(words)
print 'La parola più lunga ha {} caratteri: '.format(maxWordLen)
print 'Ecco una delle parole più lunghe: {} '.format(longestWord)
Main()
Se ti rileggi i miei precedenti messaggi, quello che hai realizzato ricalca all'incirca le indicazioni che avevo fornito.
L'unica cosa diversa è l'uso dell'oggetto Counter, che non serve. Avevo capito che servisse contare il numero di volte che i caratteri, le parole, le linee, ecc. ricorrono nel testo, e in tal caso l'oggetto Counter capita a fagiolo.
Alcune considerazioni. Ho tolto di mezzo il modulo string, che è deprecato, perché tutte le stringhe hanno già il metodo split, e quindi basta richiamarlo. Ho tolto anche xreadlines(), perché per iterare un file riga per riga è sufficiente specificare direttamente l'oggetto file nel for. Altra cosa, ho messo tutto dentro la funzione Main, perché in questo modo tutte le variabili assegnate al suo interno diventano locali, e quindi l'accesso è molto più veloce rispetto alle variabili globali / built-in, che sono quelle che vengono create al "top level" di un modulo; tenetelo presente per il futuro. Infine, ho sistemato l'uso del file, che adesso viene aperto soltanto una volta.
Ma scusate...
L'utilizzo di with cambia così pesantemente le cose? :mbe: No perchè come aveva fatto giustamente notare Vincenzo, split ( usato da me ) era lentissimo se elaborava i dati mentre gli arrivavano.
Ho detto, ok lo tolgo, l'ho tolto dalla parte dove si legge l'intero file e l'ho sparato fuori, e in effetti ha velocizzato l'esecuzione ( di parecchio!! ).
E ora, voi mi venite a dire ( mostrare più che altro ), che bastava mettere un dannato with per rendere velocisticamente accettabile il programma?? :mbe: :mbe:
Non mi pare ci sia una grossa differenza tra ciò che ho scritto io e ciò che avete scritto voi ( VICIUS, cdimauro ), eppure la differenza in termini di tempo è abissale :muro:
Vincenzo1968
06-02-2013, 10:30
L'automa a stati finiti si apprezza meglio su un file di 5 GiB:
http://img843.imageshack.us/img843/1433/c19b02resultson5gib.jpg
:D
Vabbé che è merito anche del C, ma buona parte del merito va all'algoritmo, al metodo, all'automa.
Non è un peccato che Python non debba gestire efficientemente blocchi di byte grezzi?
P.S.: la versione JavaScript di Vicius non l'ho messa ché avrei fatto notte :D
Vincenzo1968
06-02-2013, 10:34
Scusate eh, ma mi avete fatto una testa tanta con sto buffer, e poi lo avete campato via appena ho chiuso baracca e burattini? :mbe: :D
:asd:
Kwb, io ti chiedo scusa ma l'ho fatto in assoluta buona fede: ero assolutamente convinto che la versione Python con lettura/scrittura su blocchi da 4096 byte fosse più efficiente.
Ma abbiamo visto che Python(Python, non l'algoritmo, non l'automa) tratta la cosa in maniera inefficiente. :boh:
:D
Basta, da te non voglio più consigli su python, ne sai quanto me :asd:
Tra l'altro, com è che il tuo in C rimuove le parole stupide tipo '....................................' ecc..? L'hai detto tu di toglierle?
No perchè se dovessimo spulciare poi le liste create in python per cercare i 'refusi' mi sa che i tempi saliranno esponenzialmente... :sofico:
( Poi arriverà il drago-python di turno che utilizzerà la libreria nascosta che risolverà la situazione in un attimo :D )
Vincenzo1968
06-02-2013, 11:08
Merito dell'automa che riconosce i vari tipi di parole, esattamente come fa un analizzatore lessicale in un compilatore. ;)
Si, i tempi si dovrebbero allungare un pochettino ma non credo in maniera esponenziale.
Non l'ho detto esplicitamente ma sarai d'accordo con me che "..........." non è una parola. :D
;)
Merito dell'automa che riconosce i vari tipi di parole, esattamente come fa un analizzatore lessicale in un compilatore. ;)
Si, i tempi si dovrebbero allungare un pochettino ma non credo in maniera esponenziale.
Non l'ho detto esplicitamente ma sarai d'accordo con me che "..........." non è una parola. :D
;)
Ah, ho realizzato ora che automa a stati finiti è la traduzione di finite state machine :doh:
Sto studiando sta cosa in un corso di elettronica, credo che il principio sia lo stesso ( definizione di un diagramma pre-implementazione ) ma l'approccio finale sia ben diverso.
Vincenzo1968
06-02-2013, 11:38
Non m'intendo di elettronica, ma se è "finite state machine", è(dovrebbe essere) quello. ;)
L'automa calcola tutto quanto con complessità O(n) :D
Vincenzo1968
06-02-2013, 11:44
Basta, da te non voglio più consigli su python, ne sai quanto me :asd:
:asd: ah no, tu ne sai molto più di me! Io non so un tubo di Python :D
Vincenzo1968
06-02-2013, 12:16
Sto modificando il mio codice C in moda da applicare il suggerimento di Vicius:
https://computing.llnl.gov/tutorials/pthreads/
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Sto modificando il mio codice C in moda da applicare il suggerimento di Vicius:
https://computing.llnl.gov/tutorials/pthreads/
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Vabbè, utilizzando i thread si velocizza l'operazione con qualunque linguaggio.
Credo che su questo siamo tutti d'accordo.
Ne vale la pena però? :confused:
EDIT: Ci avevo pensato ieri notte ad implementarli con python.
Poi mi sono reso conto che non c'avevo lo sbatti di fare un lavoro così probabilmente tedioso e seccante per un contest.
Tra l'altro se la gestione dei thread ( ne ho fatto solo un assaggio in C, coi pthread ) è come quella in C è veramente un, come si dice in Inglese, 'pain in the ass..
cdimauro
06-02-2013, 13:33
Ecco perché non è corretto:
http://img18.imageshack.us/img18/4654/c19b02mycsolution.jpg
La parola più lunga è lunga 27 byte. A meno di non voler considerare parola la stringa:
"..................................................................................................................."
;)
Sì, l'avevo intuito. Ma per me quella rimane una parola come tutte le altre. Le parole sono suddivise generalmente dal whitespace. A meno che non decidiamo di buttare via la punteggiatura, ma nel testo del problema non era specificato.
Il mio non è un approccio C-Like. È un algoritmo che utilizza un automa a stati finiti. Ed è l'approccio migliore, in generale, come mostrano i tempi della mia applicazione(più veloce anche di wc, l'applicazione fornita su Linux). È il metodo che utilizzano i compilatori per l'analisi lessicale.
Anche in C avrei potuto utilizzare il metodo della lettura riga per riga con fgets. E infatti a WarDuck era giustamente venuto il dubbio che forse era il caso di utilizzarlo, visto che funzioni come strstr sono implementate con algoritmi efficienti come Boyer-Moore.
Ho fatto la prova. Risultato: fgets e strstr 50 secondi circa; automa a stati finiti, 7 secondi.
Quindi l'algoritmo è risultato essere il migliore. Ed ero convinto che anche con Python o con qualsiasi altro linguaggio, l'applicazione dell'algoritmo avrebbe dato risultati migliori.
Anche se fosse stato così, in Python hai comunque quei metodi a disposizione, per cui... perché non usarli? Il problema, come hai potuto vedere, è stato risolto in poco tempo e anche in maniera elegante.
Invece sembra che python non gestisca efficientemente la lettura/scrittura di blocchi di byte grezzi con read/write.
Ma a questo punto è colpa di Python, non dell'algoritmo, non dell'automa a stati finiti.
Ora la domanda è: se avessimo bisogno di trattare dati grezzi? File binari, non di testo? C'è un modo efficiente di trattarli in Python?
Non è Python di per sé il problema, ma la particolare implementazione che stai usando. Credo che per questo tipo di problematiche PyPy dovrebbe fare un lavoro nettamente migliore.
Auguri di pronta guarigione e spero di tornare a leggerti presto. Non sono d'accordo col 99% delle cose che dici ma è ugualmente stimolante leggerti. ;)
Grazie, ma oggi sto messo proprio male. Ho passato buona parte della mattinata a letto. Una cosa che odio assolutamente, visto che la mente non la posso spegnere (anche se non è che funzioni così bene :asd: ).
Ah benissimo, questo possiamo metterlo nel punto B.4: Conteggio delle occorrenze di ogni parola trovata nel file. Stampa, in ordine alfabetico, delle ventuno(o trentaquattro) parole più frequenti.
;)
Credo che con Counter dovresti risolvere per tutti i punti che hai elencato.
Scusate eh, ma mi avete fatto una testa tanta con sto buffer, e poi lo avete campato via appena ho chiuso baracca e burattini? :mbe: :D
Al contrario: io che t'avevo detto? Non usare i buffer.
Ma scusate...
L'utilizzo di with cambia così pesantemente le cose? :mbe: No perchè come aveva fatto giustamente notare Vincenzo, split ( usato da me ) era lentissimo se elaborava i dati mentre gli arrivavano.
Ho detto, ok lo tolgo, l'ho tolto dalla parte dove si legge l'intero file e l'ho sparato fuori, e in effetti ha velocizzato l'esecuzione ( di parecchio!! ).
E ora, voi mi venite a dire ( mostrare più che altro ), che bastava mettere un dannato with per rendere velocisticamente accettabile il programma?? :mbe: :mbe:
Non è il with che ha dato l'impulso: quello si occupa soltanto di finalizzare correttamente la chiusura della risorsa (file) aperta, garantendoti che alla fine del blocco, qualunque cosa succeda in mezzo, venga richiamata la f.close().
Non mi pare ci sia una grossa differenza tra ciò che ho scritto io e ciò che avete scritto voi ( VICIUS, cdimauro ), eppure la differenza in termini di tempo è abissale :muro:
Il tuo problema è che tu caricavi l'intero file in memoria, e su quel mega blocco di testo richiamavi la split, quindi suddividendo l'intero file in parole (e, a questo punto, perdendo anche la fine di ogni riga).
L'approccio di Vicius, invece, era line-based, come avevo suggerito. Perché la xreadlines() non carica l'intero file in memoria, ma ti restituisce soltanto una riga alla volta. Su questa, poi, applichi la split, che ricava soltanto le parole di quella specifica riga.
Come vedi l'approccio è enormemente diverso, e tale è anche il risultato.
Basta, da te non voglio più consigli su python, ne sai quanto me :asd:
Tra l'altro, com è che il tuo in C rimuove le parole stupide tipo '....................................' ecc..? L'hai detto tu di toglierle?
No perchè se dovessimo spulciare poi le liste create in python per cercare i 'refusi' mi sa che i tempi saliranno esponenzialmente... :sofico:
( Poi arriverà il drago-python di turno che utilizzerà la libreria nascosta che risolverà la situazione in un attimo :D )
Non ricordo che ci sia una libreria per gestire automi a stati finiti. Ma conoscendo Reymond Hettinger (il guru dietro le implementazione dei dizionari, i set, i Counter, e molto altro), magari qualcosa se la sarà sparata.
Credo, però, di non aver visto nulla nella libreria standard.
Quando avrò un po' più di lucidità mentale, farò qualche ricerca. Al momento ritorno nel sarcofago a riposare. :D
Vabbè, utilizzando i thread si velocizza l'operazione con qualunque linguaggio.
Credo che su questo siamo tutti d'accordo.
Ne vale la pena però? :confused:
Sì. Ma tu usa il modulo multiprocessing, e non threading, se vuoi sfruttare eventuali core addizionali. I thread generalmente girano su un solo core, in Python (almeno per adesso :p ).
Vincenzo1968
06-02-2013, 13:39
E il bello è che l'algoritmo per gli automi a stati finiti è di una estrema semplicità:
Eccolo, tratto dal Dragon Book, in pseudo-code:
s = s0;
c = nextchar();
while ( c != eof )
{
s = move(s, c);
c = nextchar();
}
if ( s is in F )
return "yes";
else
return "no";
Il tutto si riduce a un ciclo while... :D
Dietro ci sta tutta una portentosa teoria, con rigorosissime(e complicatissime) dimostrazioni matematiche. Ma, in pratica, si tratta d'implementare un ciclo while :asd:
Vincenzo1968
06-02-2013, 13:40
Minna post-fiume di Cesare! Verso le 17.30 finirò di leggerlo. :D
Vincenzo1968
06-02-2013, 13:47
Modificato il punto B.2:
Punto B.2:
Si scriva un programmino simile a quello presente nella distribuzioni Linux
per contare i caratteri, le parole, le righe, la riga più lunga e la parola più
lunga(quest'ultima cosa il comando wc non la fa):
http://img33.imageshack.us/img33/3691/c19b02wc.jpg
Le parole dovranno essere parole di senso compiuto. "---------" o "........" o "£$%*/*&&&" non sono parole di senso compiuto.
"parola", "ciao", "hello" invece si, sono parole di senso compiuto. ;)
Si veda, inoltre, questo post(grazie a msangi): http://www.hwupgrade.it/forum/showpost.php?p=38985909&postcount=618.
Così è più chiaro. Ragazzi ma un po' d'elasticità no? Non era chiaro fin dall'inizio che per parole intendevo parole di senso compiuto della lingua italiana, inglese, turca, cinese, norvegese? Di qualunque lingua purché di senso compiuto?
Ne avevamo discusso pure con Vicius quando presentò la sua versione JavaScript. Non avete scuse, su, datevi da fare :O
;)
Sì, l'avevo intuito. Ma per me quella rimane una parola come tutte le altre. Le parole sono suddivise generalmente dal whitespace. A meno che non decidiamo di buttare via la punteggiatura, ma nel testo del problema non era specificato. Anche io sono d'accordo con te. Tecnicamente una parola è una sequenza di caratteri contornata da due spazi ( uno a destra e l'altro a sinistra, o newline se è fine riga )
Al contrario: io che t'avevo detto? Non usare i buffer. Tra tutte le cose che ho letto, questa me l'ero persa. :(
Il tuo problema è che tu caricavi l'intero file in memoria, e su quel mega blocco di testo richiamavi la split, quindi suddividendo l'intero file in parole (e, a questo punto, perdendo anche la fine di ogni riga). Si il guaio è che ( colpa di Vincenzo ) mi era fissato che si dovesse usare il buffer. Avevo difficoltà a capire come fare a usare la readline ( la xreadline è deprecata, c'è un metodo alternativo col for ) specificando il buffer...
Non ricordo che ci sia una libreria per gestire automi a stati finiti. Ma conoscendo Reymond Hettinger (il guru dietro le implementazione dei dizionari, i set, i Counter, e molto altro), magari qualcosa se la sarà sparata.
Credo, però, di non aver visto nulla nella libreria standard.
Quando avrò un po' più di lucidità mentale, farò qualche ricerca. Al momento ritorno nel sarcofago a riposare. :D
Attenzione :asd: Si scoprirà qualcosa di clamoroso, me lo sento...
Sì. Ma tu usa il modulo multiprocessing, e non threading, se vuoi sfruttare eventuali core addizionali. I thread generalmente girano su un solo core, in Python (almeno per adesso :p ).
È ancora buona pratica utilizzare il multiprocessing invece del multithreading?
Mi era stato detto che ormai il multiprocessing è morto: parlando di C, durante un corso universitario mi è stato caldamente sconsigliato di utilizzare i processi ( sebbene allora avessi dei problemi da risolvere coi processi e i segnali :read: ) perchè veramente ingestibili per certe cose ( confermo ).
Voi che ne pensate?
Modificato il punto B.2:
Così è più chiaro. Ragazzi ma un po' d'elasticità no? Non era chiaro fin dall'inizio che per parole intendevo parole di senso compiuto della lingua italiana, inglese, turca, cinese, norvegese? Di qualunque lingua purché di senso compiuto?
Ne avevamo discusso pure con Vicius quando presentò la sua versione JavaScript. Non avete scuse, su, datevi da fare :O
;)
Cosa intendi per parola di senso compiuto?
Si deve controllare che sia una sequenza di caratteri alfabetici o ci si deve basare su un qualche dizionario?
Vincenzo1968
06-02-2013, 14:07
Cosa intendi per parola di senso compiuto?
Si deve controllare che sia una sequenza di caratteri alfabetici o ci si deve basare su un qualche dizionario?
La prima che hai detto: stringa di caratteri alfabetici.
Potremmo utilizzare dei dizionari ma dove li troviamo? E poi non complichiamoci troppo la vita. ;)
Quindi caratteri alfabetici ma che comprendano anche le lettere accentate: à è ì ò ù e tutti i caratteri con accenti stravaganti che si usano in certe lingue(si veda tabella codici ascii).
Anche se dovesse venire fuori questa: "dgfhetrywy" noi la considereremmo parola di senso compiuto perché costituita da caratteri alfabetici.
Questo: "%&£,,,,???" invece no.
;)
Vincenzo1968
06-02-2013, 14:51
Vabbè, utilizzando i thread si velocizza l'operazione con qualunque linguaggio.
Credo che su questo siamo tutti d'accordo.
Ne vale la pena però? :confused:
EDIT: Ci avevo pensato ieri notte ad implementarli con python.
Poi mi sono reso conto che non c'avevo lo sbatti di fare un lavoro così probabilmente tedioso e seccante per un contest.
Tra l'altro se la gestione dei thread ( ne ho fatto solo un assaggio in C, coi pthread ) è come quella in C è veramente un, come si dice in Inglese, 'pain in the ass..
Se ne vale la pena? Io sul mio dual core dimezzo i tempi(già favolosi) del mio automino. :D
Nell'altro computer, con quattro core a disposizione, riduco i tempi a un quarto: quattro volte più veloce di com'è adesso!
:yeah: :winner: :yeah:
Voglio vedere, adesso, come lo adattate il codice "pythonico" per il multithreading... A meno che non sia possibie leggere le righe separatamente con readline e readlines. :D
Vi asfalto alla grande. Vi stracatasfalto! :D
È bella questa metafora dell'asfaltatina, vero? Io ho preso a utilizzarla anche nella vita reale, coi miei colleghi e financo col mio capo(che è fissato col C#): "Ti asfalto, capo". :D
Debbo ringraziare Vicius anche per questo.
:D
clockover
06-02-2013, 15:26
Siccome l'ho fatto solo oggi il programmino per il contest, stavo cercando un po di cose che mi sono perso in questa discussione che sta diventando enorme :D
1) E' stato scelto un programma per il punto 1? Qual'è?
2) Dove trovo il successivo punto?
Sono un ritardatario lo so :mc:
Mi ricordate come generare i file? Vorrei provare una cosa. :D
Vincenzo1968
06-02-2013, 15:54
http://img28.imageshack.us/img28/5152/pypycesare.jpg
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Vincenzo1968
06-02-2013, 15:55
Mi ricordate come generare i file? Vorrei provare una cosa. :D
Ci sono le nostre versioni per il punto a(in C e in Java). Se ti scoccia compilare i sorgenti, dammi un attimo che impacchetto tutti gli eseguibili e te li posto.
Sei su Linux o su Windows?
Vincenzo1968
06-02-2013, 15:58
Siccome l'ho fatto solo oggi il programmino per il contest, stavo cercando un po di cose che mi sono perso in questa discussione che sta diventando enorme :D
1) E' stato scelto un programma per il punto 1? Qual'è?
2) Dove trovo il successivo punto?
Sono un ritardatario lo so :mc:
È stato scelto come vincitore? No, ancora non abbiamo fatto la classifica. Comunque il più veloce è risultato quello di Repne scasb(la versione n° 1, il primo che ha postato).
Il successivo punto è sempre nel primo post. ;)
Spara il link ai sorgenti, a compilare ci penso io. :D
Vincenzo1968
06-02-2013, 16:02
Spara il link ai sorgenti, a compilare ci penso io. :D
Ok, dammi un attimino. ;)
Vincenzo1968
06-02-2013, 16:11
Ecco il link ai sorgenti di noi tutti:
http://www.filedropper.com/contest19sourcetar
;)
Ok thx... stasera (dopo The Following, rigorosamente :O) mi dedico alla cosa. :D
Vincenzo1968
06-02-2013, 16:49
http://img442.imageshack.us/img442/1769/jython.jpg
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Vincenzo1968
06-02-2013, 17:28
Asphalting!
https://computing.llnl.gov/tutorials/pthreads/
This simple example code creates 5 threads with the pthread_create() routine. Each thread prints a "Hello World!" message, and then terminates with a call to pthread_exit().
Example Code - Pthread Creation and Termination
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Se ne vale la pena? Io sul mio dual core dimezzo i tempi(già favolosi) del mio automino. :D
Nell'altro computer, con quattro core a disposizione, riduco i tempi a un quarto: quattro volte più veloce di com'è adesso!
:yeah: :winner: :yeah:
Intendevo se ne valeva la pena scomodare i thread per questo contest, che diano un vantaggio reale era evidente anche senza provare..
Voglio vedere, adesso, come lo adattate il codice "pythonico" per il multithreading... A meno che non sia possibie leggere le righe separatamente con readline e readlines. :D
Non mi ci cimento, non c'ho sbatti di buttarmi nel multithreading/processing
Vi asfalto alla grande. Vi stracatasfalto! :D
Beh, dal momento che usi C, anche con una magra implementazione penso si possano ottenere buoni risultati ( migliori rispetto a quelli ottenibili in python ).
clockover
06-02-2013, 18:18
Ho preso un post a caso per il punto B1 --> http://www.hwupgrade.it/forum/showpost.php?p=38928781&postcount=288
ma per il punto B1 non bisognava stampare sia la riga che la colonna dove veniva trovata la parola?
Vincenzo1968
06-02-2013, 18:54
Ho preso un post a caso per il punto B1 --> http://www.hwupgrade.it/forum/showpost.php?p=38928781&postcount=288
ma per il punto B1 non bisognava stampare sia la riga che la colonna dove veniva trovata la parola?
Si ma strada facendo Vicius faceva stampare solo la riga con Lucene e io mi sono adattato. Tu fai come vuoi. Stampa solo la riga o la riga e la colonna.
;)
Vincenzo1968
07-02-2013, 09:49
http://img836.imageshack.us/img836/5680/cythonerror.jpg
:confused:
sudo apt-get install python-dev
cdimauro
07-02-2013, 10:15
Modificato il punto B.2:
Così è più chiaro. Ragazzi ma un po' d'elasticità no? Non era chiaro fin dall'inizio che per parole intendevo parole di senso compiuto della lingua italiana, inglese, turca, cinese, norvegese? Di qualunque lingua purché di senso compiuto?
Ne avevamo discusso pure con Vicius quando presentò la sua versione JavaScript. Non avete scuse, su, datevi da fare :O
;)
In tal caso basterà aggiungere la seguente riga:
line = line.translate(None, '0123456789,.:;&')
Prima del pezzo di codice che esegue lo split della riga per ricavare le parole.
Aggiungete gli altri caratteri da cancellare: ne ho scritti soltanto alcuni, per mostrare come fare.
Attenzione :asd: Si scoprirà qualcosa di clamoroso, me lo sento...
Per gli automi a stati finiti non c'è nulla nella libreria standard.
È ancora buona pratica utilizzare il multiprocessing invece del multithreading?
Mi era stato detto che ormai il multiprocessing è morto: parlando di C, durante un corso universitario mi è stato caldamente sconsigliato di utilizzare i processi ( sebbene allora avessi dei problemi da risolvere coi processi e i segnali :read: ) perchè veramente ingestibili per certe cose ( confermo ).
Voi che ne pensate?
Perché non hai visto il modulo multiprocessing. :)
Dagli un'occhiata, e vedrai che gestire carichi di lavoro da distribuire sui vari core della CPU non è così complicato.
http://img442.imageshack.us/img442/1769/jython.jpg
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Aggiungi la seguente riga all'inizio del sorgente (subito dopo le righe di commento):
from __future__ import with_statement
Vincenzo1968
07-02-2013, 10:17
sudo apt-get install python-dev
Si ce l'ho la versione python-dev. Bisognava indicare espicitamente i percorsi al compilatore, ma adesso ottengo errori del linker:
http://img29.imageshack.us/img29/4543/cython01.jpg
http://img580.imageshack.us/img580/2278/cython02.jpg
:confused:
Perché non hai visto il modulo multiprocessing. :)
Dagli un'occhiata, e vedrai che gestire carichi di lavoro da distribuire sui vari core della CPU non è così complicato.
Io stavo giocherellando con gevent (http://www.gevent.org/).. solo che ieri ho potuto dedicare poco tempo allo 'svago'. :asd:
Vincenzo1968
07-02-2013, 10:26
Aggiungi la seguente riga all'inizio del sorgente (subito dopo le righe di commento):
from __future__ import with_statement
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time jython c19b02CesareVersion.py
Traceback (most recent call last):
File "c19b02CesareVersion.py", line 49, in <module>
Main()
File "c19b02CesareVersion.py", line 19, in Main
longestWord = longestLine = ''
IndexError: index out of range: 1
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
import sys
def Main():
def fileSize(f):
f.seek(0, 2)
result = f.tell()
f.seek(0)
return result
currWordLen = maxWordLen = currLineLen = maxLineLen = lines = words = chars = 0
longestWord = longestLine = ''
with open(sys.argv[1], 'r') as f:
chars = fileSize(f)
for line in f:
lines += 1
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
longestLine = line
list = line.split()
words += len(list)
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word
f.close()
print '\nNel file ci sono {} caratteri.'.format(chars)
print 'Nel file ci sono {} righe.'.format(lines)
print 'La riga più lunga ha {} caratteri.'.format(maxLineLen)
print 'Nel file ci sono {} parole.'.format(words)
print 'La parola più lunga ha {} caratteri.'.format(maxWordLen)
print 'Ecco una delle parole più lunghe: {} '.format(longestWord)
Main()
Vincenzo1968
07-02-2013, 10:39
In tal caso basterà aggiungere la seguente riga:
line = line.translate(None, '0123456789,.:;&')
Prima del pezzo di codice che esegue lo split della riga per ricavare le parole.
Aggiungete gli altri caratteri da cancellare: ne ho scritti soltanto alcuni, per mostrare come fare.
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time python c19b02CesareVersion.py fileA_5GiB.txt
Nel file ci sono 5368709120 caratteri.
Nel file ci sono 24786789 righe.
La riga più lunga ha 21997 caratteri.
Nel file ci sono 873896327 parole.
La parola più lunga ha 36 caratteri.
Ecco una delle parole più lunghe: httpwwwliberliberitbibliotecalicenze
real 4m40.564s
user 4m32.669s
sys 0m6.840s
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
import sys
def Main():
def fileSize(f):
f.seek(0, 2)
result = f.tell()
f.seek(0)
return result
currWordLen = maxWordLen = currLineLen = maxLineLen = lines = words = chars = 0
longestWord = longestLine = ''
with open(sys.argv[1], 'r') as f:
chars = fileSize(f)
for line in f:
lines += 1
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
longestLine = line
line = line.translate(None, '0123456789,.:;&_%£"\'?()[]{}-+*/')
list = line.split()
words += len(list)
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word
f.close()
print '\nNel file ci sono {} caratteri.'.format(chars)
print 'Nel file ci sono {} righe.'.format(lines)
print 'La riga più lunga ha {} caratteri.'.format(maxLineLen)
print 'Nel file ci sono {} parole.'.format(words)
print 'La parola più lunga ha {} caratteri.'.format(maxWordLen)
print 'Ecco una delle parole più lunghe: {} '.format(longestWord)
Main()
Vincenzo1968
07-02-2013, 10:48
http://img577.imageshack.us/img577/6523/pypyjython.jpg
Ma in sostanza pypy che ottimizzazioni applica? Multithreading? Dimezza i tempi.
clockover
07-02-2013, 10:55
Si scriva un programmino simile a quello presente nella distribuzioni Linux per contare i caratteri, le parole, le righe, la riga più lunga e la parola più lunga(quest'ultima cosa il comando wc non la fa)
Per caratteri cosa si intende? Solo numeri e lettere o anche punteggiatura, trattini, ecc...
Vincenzo1968
07-02-2013, 11:01
Per caratteri cosa si intende? Solo numeri e lettere o anche punteggiatura, trattini, ecc...
Con questo file:
Esempio file di piccolissime dimensioni.
Questa riga contiene parole dentro (parentesi).
Anche questa contiene [parentesi], ma quadre.
Quest'altra riga contiene parole all'interno di {parentesi graffe}.
Riga con caratteri strani: #$££$%$%%£££$$ *****$$$|||||&&&&&.
Ciao.
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time wc -w -l -L filePiccolo.txt
9 32 67 filePiccolo.txt
real 0m0.018s
user 0m0.000s
sys 0m0.004s
wc restituisce 9 righe, 32 parole, 67 la lunghezza della riga più lunga. ;)
Pure il mio restituisce 32 parole:
http://img401.imageshack.us/img401/1985/c19b02mysolution.jpg
Pure la versione di Cesare restituisce 32 parole:
http://img844.imageshack.us/img844/1338/c19b02cesareversion.jpg
clockover
07-02-2013, 11:09
Quindi a parte \t \r \n \f e lo spazio vuoto devo contare tutto
Vincenzo1968
07-02-2013, 11:19
Quindi a parte \t \r \n \f e lo spazio vuoto devo contare tutto
Non ho capito. Se dici il numero totale di caratteri nel file, devi contare tutto, anche \t \n \r e \f.
Per il conteggio del numero delle parole devi escludere le parole che contengono i caratteri strani(ma includere quelle che contengono caratteri accentati, compresi i caratteri con accenti stravaganti):
http://www.oppo.it/tabelle/tabella_ascii.htm
http://www.oppo.it/tabelle/img/ascii.gif
In pratica sono considerati caratteri validi, per il conteggio delle parole, i caratteri compresi tra i seguenti codici ascii:
da 128 a 154
da 181 a 183
da 208 a 216
da 224 a 337
Oltre, naturalmente, ai normali caratteri alfabetici:
da 65 a 90
da 97 a 122.
;)
clockover
07-02-2013, 11:37
Per il conteggio del numero delle parole devi escludere le parole che contengono i caratteri strani(ma includere quelle che contengono caratteri accentati, compresi i caratteri con accenti stravaganti:
http://www.oppo.it/tabelle/tabella_ascii.htm
http://img341.imageshack.us/img341/3551/codiciascii.jpg
Per quanto riguarda il numero dei caratteri allora ok... devo contare tutto
E' un po vaga come cosa invece il conteggio delle parole... per me una parola del tipo ¬¼ non è una parola. Guardando la tabella che mi hai linkato, quali posso e quali non posso prendere? E le punteggiature attaccate ad una parola? Ad esempio "casa!" devo contare 4 di lunghezza o 5?
Edit
Mi hai anticipato :)
Vincenzo1968
07-02-2013, 11:40
Per quanto riguarda il numero dei caratteri allora ok... devo contare tutto
E' un po vaga come cosa invece il conteggio delle parole... per me una parola del tipo ¬¼ non è una parola. Guardando la tabella che mi hai linkato, quali posso e quali non posso prendere? E le punteggiature attaccate ad una parola? Ad esempio "casa!" devo contare 4 di lunghezza o 5?
Edit
Mi hai anticipato :)
;)
Per la punteggiatura, no, non la devi considerare. Nel tuo esempio la parola è "casa"; dunque, lunghezza = 4.
;)
Altro esempio: nel file piccolo postato in precedenza, queste sono considerate due parole, non una:
Quest'altra
Parola 1: "Quest"
Parola 2: "altra".
Per chi ha voglia di provare in Java. Le parole si possono estrarre così:
Pattern words = Pattern.compile("\\p{L}+");
Matcher matcher = words.matcher("stringa.con (1)la++++Regà!");
while (matcher.find()) {
System.out.println(matcher.group());
}
Che stampa
stringa
con
la
Regà
La regexp non ha bactracking. Sotto il cofano viene probabilmente generato un dfa quindi la stringa è esaminata in O(n). "\p{L}" matcha tutti i simboli che nello standard unicode hanno la proprietà letter. Questo significa che oltre ai normali caratteri dell'alfabeto funziona anche con lingue come cinese, russo, coreano ecc.
clockover
07-02-2013, 12:02
Con questo file:
Esempio file di piccolissime dimensioni.
Questa riga contiene parole dentro (parentesi).
Anche questa contiene [parentesi], ma quadre.
Quest'altra riga contiene parole all'interno di {parentesi graffe}.
Riga con caratteri strani: #$££$%$%%£££$$ *****$$$|||||&&&&&.
Ciao.
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time wc -w -l -L filePiccolo.txt
9 32 67 filePiccolo.txt
real 0m0.018s
user 0m0.000s
sys 0m0.004s
wc restituisce 9 righe, 32 parole, 67 la lunghezza della riga più lunga. ;)
Pure il mio restituisce 32 parole:
http://img401.imageshack.us/img401/1985/c19b02mysolution.jpg
Pure la versione di Cesare restituisce 32 parole:
http://img844.imageshack.us/img844/1338/c19b02cesareversion.jpg
Non so la tua versione ma ho provato quella di cdmauro ed non funziona bene allora... prova ad aggiungere qualche segno di punteggiatura vicino a "piccolissime"
Esempio file di ....../|¼|||||||||||¹///piccolissime!!!!!!!!!!!!!!!!! dimensioni.
Questa riga contiene parole dentro (parentesi).
Anche questa contiene [parentesi], ma quadre.
Quest'altra riga contiene parole all'interno di {parentesi graffe}.
Riga con caratteri strani: #$££$%$%%£££$$ *****$$$|||||&&&&&.
Ciao.
Vincenzo1968
07-02-2013, 12:09
Comunque Cython è interessante. Io non sapevo che prendesse il codice py e lo traducesse in codice c. Pensavo funzionasse in modo simile a pypy o Jython.
A questo punto la cosa si fa interessante. Abbiamo visto che C tratta in modo efficiente la lettura di blocchi di byte grezzi. E dunque la mia versione python, non pythonica, potrebbe risultare molto più veloce grazie a Cython.
Chi mi spiega come risolvo il problema col linker per il codice C generato da Cython?
E Jython? Come lo risolvo il problema?
Vincenzo1968
07-02-2013, 12:14
Non so la tua versione ma ho provato quella di cdmauro ed non funziona bene allora... prova ad aggiungere qualche segno di punteggiatura vicino a "piccolissime"
Esempio file di ....../|¼|||||||||||¹///piccolissime!!!!!!!!!!!!!!!!! dimensioni.
Questa riga contiene parole dentro (parentesi).
Anche questa contiene [parentesi], ma quadre.
Quest'altra riga contiene parole all'interno di {parentesi graffe}.
Riga con caratteri strani: #$££$%$%%£££$$ *****$$$|||||&&&&&.
Ciao.
La mia e wc restituiscono correttamente 32:
http://img402.imageshack.us/img402/8751/c19b02meandwc.jpg
In effetti la versione di Cesare restituisce 32 ma non restituisce correttamente la parola più lunga:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time pypy c19b02CesareVersion.py filePiccolo.txt
Nel file ci sono 322 caratteri.
Nel file ci sono 9 righe.
La riga più lunga ha 84 caratteri.
Nel file ci sono 32 parole.
La parola più lunga ha 43 caratteri.
Ecco una delle parole più lunghe: |�|||||||||||�piccolissime!!!!!!!!!!!!!!!!!
Vincenzo1968
07-02-2013, 12:21
Per chi ha voglia di provare in Java. Le parole si possono estrarre così:
Pattern words = Pattern.compile("\\p{L}+");
Matcher matcher = words.matcher("stringa.con (1)la++++Regà!");
while (matcher.find()) {
System.out.println(matcher.group());
}
Che stampa
stringa
con
la
Regà
La regexp non ha bactracking. Sotto il cofano viene probabilmente generato un dfa quindi la stringa è esaminata in O(n). "\p{L}" matcha tutti i simboli che nello standard unicode hanno la proprietà letter. Questo significa che oltre ai normali caratteri dell'alfabeto funziona anche con lingue come cinese, russo, coreano ecc.
E il resto del codice? Io volentieri lo scriverei ma non lo so fare :boh:
:D
Vincenzo1968
07-02-2013, 12:53
clockover, se vuoi provare la mia applicazione ma ti secca compilare il sorgente, da qui puoi scaricare l'eseguibile per Linux a 64 bit:
http://www.filedropper.com/c19b02vincenzo1968newtar
Questa invece è la versione a 32 bit(sempre per Linux):
http://www.filedropper.com/c19b02vincenzo1968new32tar
;)
clockover
07-02-2013, 13:10
clockover, se vuoi provare la mia applicazione ma ti secca compilare il sorgente, da qui puoi scaricare l'eseguibile per Linux a 64 bit:
http://www.filedropper.com/c19b02vincenzo1968newtar
Questa invece è la versione a 32 bit(sempre per Linux):
http://www.filedropper.com/c19b02vincenzo1968new32tar
;)
No no tranquillo :) è solo che ero un po confuso riguardo a quello che dovevo fare, allora ho preso il primo codice a portata di mano e ho fatto un po di prove.
Il mio problema comunque è la codifica dei caratteri. Voi che codifica avete usato?
Vincenzo1968
07-02-2013, 13:18
Questi invece sono gli eseguibili della mia applicazione per il punto B.2 a 32 e 64 bit per Windows:
http://www.filedropper.com/c19b02win
Compilati con Visual Studio 2010. Per cui, se avete un sistema operativo vecchio(XP?), per eseguirli potrebbe essere necessario installare le dll ridistribuibili del compilatore; le potete scaricare gratuitamente da qui:
http://www.microsoft.com/it-it/download/details.aspx?id=5555
;)
Vincenzo1968
07-02-2013, 13:21
No no tranquillo :) è solo che ero un po confuso riguardo a quello che dovevo fare, allora ho preso il primo codice a portata di mano e ho fatto un po di prove.
Il mio problema comunque è la codifica dei caratteri. Voi che codifica avete usato?
Io uso, in C, blocchi di byte grezzi, per cui non debbo preoccuparmi della codifica. A meno che Vicius non voglia distribuire la mia applicazione ai suoi amici cinesi(e quindi dovrei preoccuparmi dei caratteri unicode).
Per python c'è stata una lunga discussione nelle quattro/cinque pagine precedenti.
;)
Vincenzo1968
07-02-2013, 13:43
Ho sistemato la versione di Cesare:
http://img577.imageshack.us/img577/1338/c19b02cesareversion.jpg
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
import sys
def Main():
def fileSize(f):
f.seek(0, 2)
result = f.tell()
f.seek(0)
return result
currWordLen = maxWordLen = currLineLen = maxLineLen = lines = words = chars = 0
longestWord = longestLine = ''
with open(sys.argv[1], 'r') as f:
chars = fileSize(f)
for line in f:
lines += 1
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
longestLine = line
line = line.translate(None, '0123456789,.:;&_%£"?()[]{}-+*/\\/¼!|¹')
list = line.split()
words += len(list)
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word
f.close()
print '\nNel file ci sono {} caratteri.'.format(chars)
print 'Nel file ci sono {} righe.'.format(lines)
print 'La riga più lunga ha {} caratteri.'.format(maxLineLen)
print 'Nel file ci sono {} parole.'.format(words)
print 'La parola più lunga ha {} caratteri.'.format(maxWordLen)
print 'Ecco una delle parole più lunghe: {} '.format(longestWord)
Main()
Raga', io però mi sono scocciato. Lo dico in tono assolutamente non polemico.
È gia pesante prendere i codici di tutti, provarli e prendere i tempi.
Quindi i consigli vanno benissimo, gli spezzoni di codice pure, ma io d'ora innanzi provo soltanto codice completo.
Se c'è qualcuno che vuol mettere in atto consigli e suggerimenti altrui, posti il codice completo e io lo provo, se necessario lo compilo, e prendo i tempi.
;)
Vincenzo1968
07-02-2013, 14:14
http://img825.imageshack.us/img825/1193/asfalto.jpg
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/*
http://www.gnu.org/software/libc/manual/html_node/Processor-Resources.html
*/
long GetProcessors()
{
//long nProcs = -1;
long nProcs_max = -1;
#ifdef _WIN32
SYSTEM_INFO info;
//GetSystemInfo(&info);
GetNativeSystemInfo(&info);
nProcs_max = info.dwNumberOfProcessors;
#else
//nProcs_max = sysconf(_SC_NPROCESSORS_ONLN);
nProcs_max = sysconf(_SC_NPROCESSORS_CONF);
#endif
return nProcs_max;
}
int main()
{
long nProcs = -1;
nProcs = GetProcessors();
if ( nProcs < 1 )
{
printf("\nImpossibile determinare il numero di processori.\n");
}
else
{
printf("\nIl numero di processori presenti in questa macchina: %ld.\n", nProcs);
if ( nProcs > 1 )
{
printf("\nStracatasfaltiamo tutti.\n\n");
}
else
{
printf("\nAsfaltiamo tutti.\n\n");
}
}
}
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Vincenzo1968
07-02-2013, 16:43
Ecco la classifica provvisoria per il punto B.2, in attesa delle altre soluzioni:
http://img202.imageshack.us/img202/4804/c19b02classificatemp01.jpg
http://img687.imageshack.us/img687/2703/c19b02classifica01.jpg
http://img585.imageshack.us/img585/5530/c19b02classifica02.jpg
;)
Per gli automi a stati finiti non c'è nulla nella libreria standard.
Fa già ridere il fatto che tu abbia controllato :asd:
Perché non hai visto il modulo multiprocessing. :)
Dagli un'occhiata, e vedrai che gestire carichi di lavoro da distribuire sui vari core della CPU non è così complicato.
Al di là di quello che concerne python, volevo capire se attualmente le pratiche di buona programmazione considerano il multiprocessing ancora valido ( indipendentemente dal linguaggio usato ) e un'opzione aggiuntiva alla pratica del multithreading.
Al di là di quello che concerne python, volevo capire se attualmente le pratiche di buona programmazione considerano il multiprocessing ancora valido ( indipendentemente dal linguaggio usato ) e un'opzione aggiuntiva alla pratica del multithreading.
Si certo e sta pure tornando di moda. Alcuni dei progetti più interessanti degli ultimi anni come nginx e nodejs non supportano il multi-threading per scelta. Fanno uso di i/o asincrono per non bloccare il processo e riescono comunque a gestire più richieste contemporaneamente. In alcuni casi non dovendo creare e gestire la sincronizzazione di decine di migliaia di thread diversi hanno anche prestazioni incredibilmente migliori rispetto a server classici.
Vincenzo1968
07-02-2013, 18:58
Si certo e sta pure tornando di moda. Alcuni dei progetti più interessanti degli ultimi anni come nginx e nodejs non supportano il multi-threading per scelta. Fanno uso di i/o asincrono per non bloccare il processo e riescono comunque a gestire più richieste contemporaneamente. In alcuni casi non dovendo creare e gestire la sincronizzazione di decine di migliaia di thread diversi hanno anche prestazioni incredibilmente migliori rispetto a server classici.
nodejs?
http://img202.imageshack.us/img202/4804/c19b02classificatemp01.jpg
8 minuti... :read:
http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Avevo cominciato a fare il punto A (in C++), ma dato che non ho tempo mi sa che devo rinunciare :/.
Comunque l'idea di base era quella di usare il memory mapped I/O, e cercare di fare il meno possibile copie (in lettura).
In particolare l'idea era quella di crearsi delle coppie <puntatore, lunghezza riga> che identificassero una riga nel file (anche qui, senza copiare nulla).
Tutto usando memoria quanto più possibile statica, evitando allocazioni.
A quel punto si generano i numeri di riga e si vanno a scrivere le righe nel file fin quando le condizioni sulla size non venivano soddisfatte...
Considerate comunque le operazioni da fare sui singoli caratteri, allora forse è il caso di implementare il DFA come diceva Vincenzo.
Però se volete ottenere il massimo, dovete riuscire a fare il meno possibile copie ed allocazioni.
Si certo e sta pure tornando di moda. Alcuni dei progetti più interessanti degli ultimi anni come nginx e nodejs non supportano il multi-threading per scelta. Fanno uso di i/o asincrono per non bloccare il processo e riescono comunque a gestire più richieste contemporaneamente. In alcuni casi non dovendo creare e gestire la sincronizzazione di decine di migliaia di thread diversi hanno anche prestazioni incredibilmente migliori rispetto a server classici.
Seriamente?? :eek:
Anvedi che mi hanno detto delle cacate nei corsi universitari :asd:
cdimauro
08-02-2013, 08:33
E' il quarto giorno con la febbre, ma oggi mi sento un po' meglio. Per cui rispondo ad alcuni messaggi, e poi mi fiondo sulla roba che mi devo smazzare, dopo tre giorni di "ferie forzate".
Io stavo giocherellando con gevent (http://www.gevent.org/).. solo che ieri ho potuto dedicare poco tempo allo 'svago'. :asd:
Ne ho sentito parlare molto bene. D'altra parte già da qualche tempo ci si è focalizzati sul concetto di greenlet e di fiber per ottimizzare le prestazioni dei server, con eccellenti risultati in termini di scalabilità.
Non credo, però, che in questo specifico contest possano essere d'aiuto.
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time jython c19b02CesareVersion.py
Traceback (most recent call last):
File "c19b02CesareVersion.py", line 49, in <module>
Main()
File "c19b02CesareVersion.py", line 19, in Main
longestWord = longestLine = ''
IndexError: index out of range: 1
Francamente l'errore che ha fornito è assolutamente fuorviante, perché in quella riga segnalata non c'è nessun indice. Non so cos'abbia combinato Jython...
http://img577.imageshack.us/img577/6523/pypyjython.jpg
Ma in sostanza pypy che ottimizzazioni applica? Multithreading? Dimezza i tempi.
No, integra un compilatore JIT online che traduce i bytecode Python in binario x86 (e x64, ARM, e credo ci sia qualche esperimento coi PowerPC). Inoltre esegue il "tracing" delle classi che, ove possibile, vengono convertite internamente in una sorta di struct C, migliorando sia l'occupazione di memoria che i tempi d'accesso ai campi.
Ci sono davvero tantissime ottimizzazioni che sono state messe in piedi in questi anni, e i risultati si vedono, particolarmente con codice che esegue number crunching.
Altra chicca, hanno già integrato il supporto alle "software transactional memory" (STM) per supportare meglio i sistemi multicore. Python ha sempre avuto problemi in tal senso, a causa della famigerata GIL. Con le software transaction la GIL verrà del tutto rimossa, perché diverrà obsoleta. Al momento il supporto alle STM è esclusivamente software, per cui è molto lento, le prestazioni di un sistema quadcore, con PyPy che gira in questa modalità, sono all'incirca quelle di un solo core che non ne fa uso. Ma fra qualche mese arriverà il nuovo core di Intel, Haswell, che integrerà il supporto in hardware, e lì ci sarà di che divertirsi con PyPy e il multicore.
Non ho capito. Se dici il numero totale di caratteri nel file, devi contare tutto, anche \t \n \r e \f.
Per il conteggio del numero delle parole devi escludere le parole che contengono i caratteri strani(ma includere quelle che contengono caratteri accentati, compresi i caratteri con accenti stravaganti):
http://www.oppo.it/tabelle/tabella_ascii.htm
http://www.oppo.it/tabelle/img/ascii.gif
In pratica sono considerati caratteri validi, per il conteggio delle parole, i caratteri compresi tra i seguenti codici ascii:
da 128 a 154
da 181 a 183
da 208 a 216
da 224 a 337
Oltre, naturalmente, ai normali caratteri alfabetici:
da 65 a 90
da 97 a 122.
;)
Quella non è la tabella ASCII, ma è la code page del vecchio DOS.
Visto che i file sono codificati in Latin-1 (ISO-8859-1), è meglio usare questa (http://en.wikipedia.org/wiki/Latin-1#Codepage_layout) come riferimento.
Comunque Cython è interessante. Io non sapevo che prendesse il codice py e lo traducesse in codice c. Pensavo funzionasse in modo simile a pypy o Jython.
A questo punto la cosa si fa interessante. Abbiamo visto che C tratta in modo efficiente la lettura di blocchi di byte grezzi. E dunque la mia versione python, non pythonica, potrebbe risultare molto più veloce grazie a Cython.
Sì, specialmente se fornisci degli "hint" al codice Cython, in modo da dirgli il tipo di qualche variabile. Il resto lo farà lui.
Chi mi spiega come risolvo il problema col linker per il codice C generato da Cython?
Purtroppo non l'ho mai provato, per cui non ti so dire.
E Jython? Come lo risolvo il problema?
Come già detto, è oscuro. Non è un errore che mi aspetto per quella riga di codice, perché non ha senso.
La mia e wc restituiscono correttamente 32:
http://img402.imageshack.us/img402/8751/c19b02meandwc.jpg
In effetti la versione di Cesare restituisce 32 ma non restituisce correttamente la parola più lunga:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time pypy c19b02CesareVersion.py filePiccolo.txt
Nel file ci sono 322 caratteri.
Nel file ci sono 9 righe.
La riga più lunga ha 84 caratteri.
Nel file ci sono 32 parole.
La parola più lunga ha 43 caratteri.
Ecco una delle parole più lunghe: |�|||||||||||�piccolissime!!!!!!!!!!!!!!!!!
Ho visto i nuovi casi che hai citato, e la translate usata va modificata necessariamente in questo modo:
line = line.translate('')
Dove al posto della stringa '' va sostituita una stringa di esattamente 256 caratteri, che serve per "traslare" tutti i caratteri che hanno una precisa codifica (posizione all'interno della stringa di 256 caratteri) in un preciso carattere.
Si definisce prima del loop la stringa di conversione di 256 caratteri in questo modo:
TranslationTable = ' ' * 65 + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + ' ' * 6 + 'abcdefghijklmnopqrstuvwxyz' + ' ' * 69 + ''.join(chr(i) for i in xrange(192, 215)) + ' ' * 2 + ''.join(chr(i) for i in xrange(217, 247)) + ' ' * 2 + ''.join(chr(i) for i in xrange(249, 256))
E poi la si usa così nel codice:
line = line.translate(TranslationTable)
L'idea è quella di sostituire tutti i caratteri indesiderati con lo spazio, lasciando poi che sia la successiva split a "farli fuori" in maniera pulita.
La tabella di conversione dovrebbe essere a posto. A me risulta di 256 caratteri, e con un controllo veloce su alcuni pezzi sembra che le posizioni dei caratteri coincidano.
Ho sistemato la versione di Cesare:
http://img577.imageshack.us/img577/1338/c19b02cesareversion.jpg
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
import sys
def Main():
def fileSize(f):
f.seek(0, 2)
result = f.tell()
f.seek(0)
return result
currWordLen = maxWordLen = currLineLen = maxLineLen = lines = words = chars = 0
longestWord = longestLine = ''
with open(sys.argv[1], 'r') as f:
chars = fileSize(f)
for line in f:
lines += 1
currLineLen = len(line)
if currLineLen > maxLineLen:
maxLineLen = currLineLen
longestLine = line
line = line.translate(None, '0123456789,.:;&_%£"?()[]{}-+*/\\/¼!|¹')
list = line.split()
words += len(list)
for word in list:
currWordLen = len(word)
if currWordLen > maxWordLen:
maxWordLen = currWordLen
longestWord = word
f.close()
print '\nNel file ci sono {} caratteri.'.format(chars)
print 'Nel file ci sono {} righe.'.format(lines)
print 'La riga più lunga ha {} caratteri.'.format(maxLineLen)
print 'Nel file ci sono {} parole.'.format(words)
print 'La parola più lunga ha {} caratteri.'.format(maxWordLen)
print 'Ecco una delle parole più lunghe: {} '.format(longestWord)
Main()
Raga', io però mi sono scocciato. Lo dico in tono assolutamente non polemico.
È gia pesante prendere i codici di tutti, provarli e prendere i tempi.
Quindi i consigli vanno benissimo, gli spezzoni di codice pure, ma io d'ora innanzi provo soltanto codice completo.
Se c'è qualcuno che vuol mettere in atto consigli e suggerimenti altrui, posti il codice completo e io lo provo, se necessario lo compilo, e prendo i tempi.
;)
Ma infatti tu pensa alla versione C. Se c'è qualcuno che vorrà cimentarsi con Python, io gli fornirò qualche suggerimento, nel caso dovesse essere necessario.
Si certo e sta pure tornando di moda. Alcuni dei progetti più interessanti degli ultimi anni come nginx e nodejs non supportano il multi-threading per scelta. Fanno uso di i/o asincrono per non bloccare il processo e riescono comunque a gestire più richieste contemporaneamente. In alcuni casi non dovendo creare e gestire la sincronizzazione di decine di migliaia di thread diversi hanno anche prestazioni incredibilmente migliori rispetto a server classici.
Infatti. La gente è convinta che la soluzione a tutti i problemi di scalabilità sia rappresentata dai thread. Niente di più falso.
Stackless insegna. E non è un caso che il suo modello sia stato copiato pari pari dal nuovo linguaggio di Google, Go.
Seriamente?? :eek:
Anvedi che mi hanno detto delle cacate nei corsi universitari :asd:
Se non si aggiornano, è normale. All'università ci sono un sacco di menti brillanti, ma purtroppo anche il frutto del baronato che piazza incapaci che poi fanno danni...
Se non si aggiornano, è normale. All'università ci sono un sacco di menti brillanti, ma purtroppo anche il frutto del baronato che piazza incapaci che poi fanno danni...
Guarda, è vero.
Il corso è tenuto da un professore ( e già definirlo tale è più che un complimento ) che proprio baroneggia ancora su quei 2/3 corsi che gli hanno assegnato.
Questa delucidazione sui thread/process mi è stata data da un ragazzo che mi ha assistito durante le sessioni di laboratorio: l'ho trovato molto più preparato del professore, per cui mi sono fidato, forse condizionato anche dall'aver toccato con mano i processi e segnali in C ( Linux ) e la difficoltà nel gestirli correttamente.
Ci sta però, inesperienza da parte sua magari.
Mi fido di ciò che dite :D anche perchè mi sembrate tutti molto preparati ( e probabilmente ci lavorate pure con ste cose, quindi l'esperienza l'avete ); quello che so è che se dovrò usare i processi, non lo farò in C :asd:
Avevo cominciato a fare il punto A (in C++), ma dato che non ho tempo mi sa che devo rinunciare :/.
Comunque l'idea di base era quella di usare il memory mapped I/O, e cercare di fare il meno possibile copie (in lettura).
In particolare l'idea era quella di crearsi delle coppie <puntatore, lunghezza riga> che identificassero una riga nel file (anche qui, senza copiare nulla).
Tutto usando memoria quanto più possibile statica, evitando allocazioni.
A quel punto si generano i numeri di riga e si vanno a scrivere le righe nel file fin quando le condizioni sulla size non venivano soddisfatte...
Considerate comunque le operazioni da fare sui singoli caratteri, allora forse è il caso di implementare il DFA come diceva Vincenzo.
Però se volete ottenere il massimo, dovete riuscire a fare il meno possibile copie ed allocazioni.
E' un tentativo che ho abbozzato ma non funziona molto bene. Il collo di bottiglia non e' la copia della memoria, ma la lettura/scrittura su disco.
Con memoria mappata e' vero che in teoria elimini una copia, ma non hai un buon controllo su quando/come fare il flush.
Per la lettura del testo da generare il discorso e' un po' piu' articolato.
Se il testo da usare e' maggiore della memoria a disposizione conviene la mappatura per evitare trashing, altrimenti ci si mette molto meno a caricatre di fila tutto in memoria e poi usare quello.
Vincenzo1968
08-02-2013, 15:31
Ragazzi comunque il punto A non è importante. Il contest è sui metodi di full text search.
Il punto A serve soltanto per creare file di grosse(e/o grossissime) dimensioni da utilizzare per i sottopunti del punto B.
;)
clockover
08-02-2013, 15:48
Ragazzi comunque il punto A non è importante. Il contest è sui metodi di full text search.
Il punto A serve soltanto per creare file di grosse(e/o grossissime) dimensioni da utilizzare per i sottopunti del punto B.
;)
Sto imparando Perl :D se vuoi provare se funziona per il punto B1
#!/bin/perl
use strict;
use warnings;
if( scalar @ARGV lt 2 ){
print "./puntoB1.pl FILE_INPUT PAROLA_DA_CERCARE [-i]\n";
die;
}
my $CASE_SENSITIVE = 1;
$CASE_SENSITIVE = 0 if scalar @ARGV == 3 and grep { "-i" } @ARGV;
print "CASE INSENSITIVE\n" if not $CASE_SENSITIVE;
open my $FILE_HANDLE, "<", $ARGV[0] or die "Errore apertura file di input: $!";
my $line_number = 1;
my $matched = 0;
my @OUTPUT = ();
my $tmp_matched = 0;
if( $CASE_SENSITIVE ){
while( <$FILE_HANDLE> ){
if( $tmp_matched = /$ARGV[1]/g ){
$matched += $tmp_matched;
push @OUTPUT, $line_number if scalar @OUTPUT < 11;
}
$line_number++;
}
}
else{
while( <$FILE_HANDLE> ){
if( $tmp_matched = /$ARGV[1]/ig ){
$matched += $tmp_matched;
push @OUTPUT, $line_number if scalar @OUTPUT < 11;
}
$line_number++;
}
}
print "Trovate $matched occorrenze\nPrimi 10 risultati\n";
foreach( @OUTPUT ){
print "Trovato in riga $_\n";
}
Vincenzo1968
08-02-2013, 16:21
Ok, clockover ;)
Prima debbo capire come funziona Perl, però :D
The_ouroboros
08-02-2013, 16:22
http://shop.oreilly.com/product/9780596004927.do?green=8F8C349E-34C9-55F6-9889-573FD4D2C74F&intcmp=af-mybuy-9780596004927.IP
Vincenzo1968
08-02-2013, 16:25
http://shop.oreilly.com/product/9780596004927.do?green=8F8C349E-34C9-55F6-9889-573FD4D2C74F&intcmp=af-mybuy-9780596004927.IP
Nientedimeno clockover deve aspettare che mi arrivi il libro? :D
Lo comprerò senz'altro ma per il momento non potreste darmi qualche dritta?
Con che estensione lo debbo salvare il file? E come lo lancio? Lo debbo compilare?
clockover
08-02-2013, 16:28
Ok, clockover ;)
Prima debbo capire come funziona Perl, però :D
Te lo copi in un file di testo con estensione pl, ad esempio programma.pl. Poi hai due possibilità: 1) rendi il file eseguibile con chmod +x programma.pl e poi fai partire il programma da linea di comando, 2) dai da linea di comando "perl programma.pl" ovviamente senza apici
Vincenzo1968
08-02-2013, 16:34
Mi da errore:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ ls *.pl
c19b02Clockover.pl
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time perl c19b02Clockover.pl filePiccolo.txt
Missing right curly or square bracket at c19b02Clockover.pl line 39, at end of line
syntax error at c19b02Clockover.pl line 39, at EOF
Execution of c19b02Clockover.pl aborted due to compilation errors.
:cry:
http://img515.imageshack.us/img515/2103/clockover.jpg
clockover
08-02-2013, 16:36
Mi da errore:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ ls *.pl
c19b02Clockover.pl
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time perl c19b02Clockover.pl filePiccolo.txt
Missing right curly or square bracket at c19b02Clockover.pl line 39, at end of line
syntax error at c19b02Clockover.pl line 39, at EOF
Execution of c19b02Clockover.pl aborted due to compilation errors.
:cry:
deve essere andata perduta una parentesi, dai uno sguardo alla riga 39, ora ci guardo anche io di nuovo, forse perchè stavo smadonnando un po con le mie nuove conoscenze di Vim e mi sono bruciato qualcosa :D
edit
dovrebbe essere l'ultima riga... hai fatto bene copia incolla?
edit2
non hai fatto bene copia incolla, dal tuo screenshot dai uno sguardo all'ultima riga :)
Vincenzo1968
08-02-2013, 16:41
Ok, ho messo la graffa nell'ultima riga ma adesso ho questo:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ ls *.pl *.txt
c19b02Clockover.pl fileA_1GiB.txt filePiccolo.txt prova.txt VerificaOutputB02.txt
fileA_10MB.txt fileInputMinimo.txt i_promes.txt psHelp.txt
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time perl c19b02Clockover.pl filePiccolo.txt
./puntoB1.pl FILE_INPUT PAROLA_DA_CERCARE [-i]
Died at c19b02Clockover.pl line 8.
:cry:
Sarà qualche altra minchiata che ho combinato :D
clockover
08-02-2013, 16:46
Ok, ho messo la graffa nell'ultima riga ma adesso ho questo:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ ls *.pl *.txt
c19b02Clockover.pl fileA_1GiB.txt filePiccolo.txt prova.txt VerificaOutputB02.txt
fileA_10MB.txt fileInputMinimo.txt i_promes.txt psHelp.txt
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time perl c19b02Clockover.pl filePiccolo.txt
./puntoB1.pl FILE_INPUT PAROLA_DA_CERCARE [-i]
Died at c19b02Clockover.pl line 8.
:cry:
Sarà qualche altra minchiata che ho combinato :D
E no solo che tu lo hai scambiato per il punto B2, invece questo è il punto B1, che si aspetta il file di input e la parola da cercare, e se vuoi l'opzione -i per renderlo case insensitive
Vincenzo1968
08-02-2013, 16:47
E no solo che tu lo hai scambiato per il punto B2, invece questo è il punto B1, che si aspetta il file di input e la parola da cercare, e se vuoi l'opzione -i per renderlo case insensitive
Si, infatti è questa la minchiata: averlo scambiato per il punto B.2 :D
Provvedo subito a fare la prova e stampo i risultati. ;)
clockover
08-02-2013, 16:48
Si, infatti è questa la minchiata: averlo scambiato per il punto B.2 :D
Provvedo subito a fare la prova e stampo i risultati. ;)
Si ma fai la verifica anche confrontandolo con altri risultati, magari ho sbagliato qualcosa dato che sono un novizio di perl
Vincenzo1968
08-02-2013, 16:54
Bravissimo Clockover, solo 38 secondi col file da 5 GiB. Velocissimo!
http://img254.imageshack.us/img254/1631/c19b01clockover.jpg
:D
clockover
08-02-2013, 16:55
Bravissimo Clockover, solo 38 secondi col file da 5 GiB. Velocissimo!
http://img254.imageshack.us/img254/1631/c19b01clockover.jpg
:D
Ma si trova anche con gli altri risultati?
Vincenzo1968
08-02-2013, 17:05
Ecco il mio:
http://img801.imageshack.us/img801/596/c19b01myresult.jpg
Come vedi i risultati corrispondono. Complimenti: veloce, elegante e compatto. Bravo, bravissimo ;)
Una forza anche 'sto Perl :D
Vicius-Lucene ancora ci batte come tempi per la ricerca ma gliela faremo vedere noi quando avremo implementato l'indice ;)
EDIT: l'unica cosa è che il mio stampa le due occorrenze della parola "notaio" nella riga 1805 e quindi le ultime righe del mio e del tuo differiscono. Ma è una minchiatella. ;)
clockover
08-02-2013, 17:15
Ecco il mio:
http://img801.imageshack.us/img801/596/c19b01myresult.jpg
Come vedi i risultati corrispondono. Complimenti: veloce, elegante e compatto. Bravo, bravissimo ;)
Una forza anche 'sto Perl :D
Vicius-Lucene ancora ci batte come tempi per la ricerca ma gliela faremo vedere noi quando avremo implementato l'indice ;)
EDIT: l'unica cosa è che il mio stampa le due occorrenze della parola "notaio" nella riga 1805 e quindi le ultime righe del mio e del tuo differiscono. Ma è una minchiatella. ;)
E si ho fatto un errore.... penso di averlo trovato subito
if( $CASE_SENSITIVE ){
while( <$FILE_HANDLE> ){
if( $tmp_matched =()= /$ARGV[1]/g ){
$matched += $tmp_matched;
push @OUTPUT, $line_number if scalar @OUTPUT < 11;
}
$line_number++;
}
}
else{
while( <$FILE_HANDLE> ){
if( $tmp_matched =()= /$ARGV[1]/ig ){
$matched += $tmp_matched;
push @OUTPUT, $line_number if scalar @OUTPUT < 11;
}
$line_number++;
}
}
se sostituisci questo blocco con quello vecchio dovrebbe, e dico dovrebbe essere uguale
edit
questo perchè nell'espressione regolare cercava comunque in tutta la riga, ma contava sempre 1, quindi true o false. Adesso ho modificato e dovrebbe contare le occorrenze trovate
Vincenzo1968
08-02-2013, 17:23
Adesso ho questi risultati:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time perl c19b02Clockover.pl fileA_5GiB.txt notaio
Trovate 35634 occorrenze
Primi 10 risultati
Trovato in riga 203
Trovato in riga 1033
Trovato in riga 1075
Trovato in riga 1805
Trovato in riga 3532
Trovato in riga 3611
Trovato in riga 4547
Trovato in riga 4776
Trovato in riga 5108
Trovato in riga 8213
Trovato in riga 8360
real 0m37.851s
user 0m29.754s
sys 0m5.616s
Vincenzo1968
08-02-2013, 17:31
Mi assento un attimino. Vado a comprare le sigarette.
Eh si, ho ripreso a fumare. Due anni che avevo smesso, poi, stupidamente, ci sono ricascato :cry:
clockover
08-02-2013, 18:32
Strana sta cosa però :confused: l'espressione regolare è giusta, il codice lo sto controllando ora e mi sembra ok, continuo a provare un attimo
Vincenzo1968
08-02-2013, 18:37
Strana sta cosa però :confused: l'espressione regolare è giusta, il codice lo sto controllando ora e mi sembra ok, continuo a provare un attimo
Prova con file di piccole dimensioni. Per esempio, creati questo:
ciao notaio
riga di prova
notaio notaio hello
ciao ciao
e vedi se ti trova due occorrenze alla riga 3
clockover
08-02-2013, 18:44
Allora, il secondo codice, quello corretto funziona bene. Ho fatto una prova:
1) mi sono creato un file random di una 10 di mega
2) ho fatto partire il programma per il punto B1 e mi porta N corrispondenze
3) ho aperto il file random con Vim
4) ho dato il seguente comando:%s/notaio//gnal posto di notaio ovviamente metti quello che vuoi
5) il risultato è N
corrispondenze uguali al mio risultato. Provalo con un file di pochi mega che io l'ho provato con un file molto grosso e Vim mi ha bestemmiato contro, anche se ce l'ha fatta lo stesso e con il risultato giusto
Vincenzo1968
08-02-2013, 18:52
http://shop.oreilly.com/product/9780596004927.do?green=8F8C349E-34C9-55F6-9889-573FD4D2C74F&intcmp=af-mybuy-9780596004927.IP
http://akamaicovers.oreilly.com/images/9780596004927/cat.gif
Ordinato! :O
D'ora innanzi avrò due linguaggi a disposizione coi quali asfaltarvi :O
Vincenzo1968
08-02-2013, 19:01
Funge funge:
fileNotaio.txt:
ciao notaio
riga di prova
notaio notaio hello
ciao ciao
http://img801.imageshack.us/img801/619/notaio.jpg
:D
clockover
08-02-2013, 19:20
Funge funge:
fileNotaio.txt:
ciao notaio
riga di prova
notaio notaio hello
ciao ciao
http://img801.imageshack.us/img801/619/notaio.jpg
:D
Si si va bene anche a me, cambia solo nella stampa dei risultati, ma volendo basta cambiare questa riga qui
push @OUTPUT, $line_number if scalar @OUTPUT < 11;
con questa
push @OUTPUT, $line_number . (($tmp_matched > 1)? " $tmp_matched risultati" : "") if scalar @OUTPUT < 10;
Questo è il codice corretto (spero)
#!/bin/perl
use strict;
use warnings;
if( scalar @ARGV lt 2 ){
print "./puntoB1.pl FILE_INPUT PAROLA_DA_CERCARE [-i]\n";
die;
}
my $CASE_SENSITIVE = 1;
$CASE_SENSITIVE = 0 if scalar @ARGV == 3 and grep { "-i" } @ARGV;
print "CASE INSENSITIVE\n" if not $CASE_SENSITIVE;
open my $FILE_HANDLE, "<", $ARGV[0] or die "Errore apertura file di input: $!";
my $line_number = 1;
my $matched = 0;
my @OUTPUT = ();
my $tmp_matched = 0;
if( $CASE_SENSITIVE ){
while( <$FILE_HANDLE> ){
if( $tmp_matched =()= /$ARGV[1]/g ){
$matched += $tmp_matched;
push @OUTPUT, $line_number . (($tmp_matched > 1)? " $tmp_matched risultati" : "") if scalar @OUTPUT < 10;
}
$line_number++;
}
}
else{
while( <$FILE_HANDLE> ){
if( $tmp_matched =()= /$ARGV[1]/ig ){
$matched += $tmp_matched;
push @OUTPUT, $line_number . (($tmp_matched > 1)? " $tmp_matched risultati" : "") if scalar @OUTPUT < 10;
}
$line_number++;
}
}
print "Trovate $matched occorrenze\n";
my $ris = scalar @OUTPUT;
if( not $ris ){
print "Nessun risultato\n";
}
elsif( $ris == 1 ){
print "Trovato un risultato\n";
}
else{
print "Stampa di " . (($ris > 10)? "10 " : "$ris ") . "risultati\n";
foreach( @OUTPUT ){
print "Trovato in riga $_\n";
}
}
Vincenzo1968
08-02-2013, 19:29
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ perl c19b01Clockover.pl fileNotaio.txt notaio
Trovate 3 occorrenze
Stampa di 2 risultati
Trovato in riga 1
Trovato in riga 3 2 risultati
;)
Vicius-Lucene ancora ci batte come tempi per la ricerca ma gliela faremo vedere noi quando avremo implementato l'indice ;)
Io ci ho messo 10 minuti a farlo in java. Quando ci vuole in C? :O
Poi quando arrivate ai tempi di lucene fate un fischio che finisco un piccolo esperimento di qualche giorno fa. Con il file 5 gb...
indice creato in 133439.146 ms. contiene 155022337 righe. occupa 154338712 bytes
warming up the jvm...ok
ho trovato la parola 'ora' in 310 righe. ci ho messo 0.135 ms
:fiufiu:
http://akamaicovers.oreilly.com/images/9780596004927/cat.gif
Ordinato! :O
D'ora innanzi avrò due linguaggi a disposizione coi quali asfaltarvi :O
Perl è il male. Se puoi annulla l'ordine. Sei già stato contaminato da C. Se ti metti a studiare perl è la fine.
clockover
08-02-2013, 19:44
Io sto prendendo questa cosa come un utile allenamento per imparare Perl. Tra l'altro un buon programmatore Perl avrebbe fatto sicuramente meglio di me :D
Una perla di Perl :D
grep{!$l{$_}++} @listio lo so cosa fa, ma quando avrò capito come fa posso dirmi molto soddisfatto
si può scrivere anche cosìkeys %{{ map {$_ => 1} @list }}
In realta' occorre anche molto meno di perl
Un termine di paragone su cui confrontrarsi potrebbe essere una implementazione naive da linea di comando
Ad esempio
time grep -nh notaio filename.txt | cut -f1 -d: | tail
oppure
awk '/ notaio / {print FNR}' filename.txt
Potrebbero essere dei buoni candidati. Il secondo e' più corretto perche' cerca la parola intera (circa).
Già che ci sono, versione da linea di comando del punto B
(sto imbrogliando, non è farina del mio sacco...)
time awk '{
chars += length($0) + 1
words += NF
}
END{ print NR, words, chars }
' prova.dat
Vincenzo1968
08-02-2013, 21:11
Io ci ho messo 10 minuti a farlo in java. Quando ci vuole in C? :O
Poi quando arrivate ai tempi di lucene fate un fischio che finisco un piccolo esperimento di qualche giorno fa. Con il file 5 gb...
indice creato in 133439.146 ms. contiene 155022337 righe. occupa 154338712 bytes
warming up the jvm...ok
ho trovato la parola 'ora' in 310 righe. ci ho messo 0.135 ms
:fiufiu:
Ma è codice tuo o Lucene?
Il fine settimana lo dedico al bunto B.1 con indice Invertito-B+Tree. Lucene ha le ore contate :D
I baffoni te li sei tagliati?
Vincenzo1968
08-02-2013, 21:20
Perl è il male. Se puoi annulla l'ordine. Sei già stato contaminato da C. Se ti metti a studiare perl è la fine.
Perché sarebbe il male?
No seriamente dico. A me ha impressionato la velocità d'esecuzione e la brevità del codice. Ruby è compatto ma non così veloce.
Tu perché lo giudichi negativamente?
Vincenzo1968
08-02-2013, 21:25
Non posso provare i comandi di Marco. Sono sul portatilino. :mad:
Ah si, posso! Avevo dimenticato che grazie alle GnuWin32 ho buona parte dei comandi Linux disponibili anche su Windows. :D
http://img803.imageshack.us/img803/6897/marcogrep.jpg
Ma non riesco a prendere i tempi con ptime.exe :mad:
clockover
08-02-2013, 21:33
Non posso provare i comandi di Marco. Sono sul portatilino. :mad:
tranquillo ci sono tutti se sei su linux
clockover
08-02-2013, 21:36
In realta' occorre anche molto meno di perl
Un termine di paragone su cui confrontrarsi potrebbe essere una implementazione naive da linea di comando
Ad esempio
time grep -nh notaio filename.txt | cut -f1 -d: | tail
oppure
awk '/ notaio / {print FNR}' filename.txt
Potrebbero essere dei buoni candidati. Il secondo e' più corretto perche' cerca la parola intera (circa).
Già che ci sei e sei abbastanza ferrato, sicuramente più di me, perchè grep mi da un risultato cat file.txt | grep -c notaiomentre invece la ricerca all'interno di Vim me ne da un altro
Sto facendo delle prove su un file da 10MB e grep mi da 72 risultati, mentre Vim 80 come il mio script
Vincenzo1968
08-02-2013, 21:39
awk mi da errore:
C:\Contest19\Exe>ptime awk '/ notaio / {print FNR}' fileA_1GiB.txt
ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>
=== awk '/ notaio / {print FNR}' fileA_1GiB.txt ===
awk: '/
awk: ^ invalid char ''' in expression
Execution time: 0.170 s
C:\Contest19\Exe>
http://img803.imageshack.us/img803/6897/marcogrep.jpg
The_ouroboros
08-02-2013, 22:05
prova
cat fileA_1GiB.txt | awk '/notaio/ {print FNR}'
Non posso provare i comandi di Marco. Sono sul portatilino. :mad:
Ah si, posso! Avevo dimenticato che grazie alle GnuWin32 ho buona parte dei comandi Linux disponibili anche su Windows. :D
http://img803.imageshack.us/img803/6897/marcogrep.jpg
Ma non riesco a prendere i tempi con ptime.exe :mad:
Se hai installato mingw dovresti avere anche MSYS (una console unix-like con bash). Prova con quella.
Già che ci sei e sei abbastanza ferrato, sicuramente più di me, perchè grep mi da un risultato cat file.txt | grep -c notaiomentre invece la ricerca all'interno di Vim me ne da un altro
Sto facendo delle prove su un file da 10MB e grep mi da 72 risultati, mentre Vim 80 come il mio script
Lo script mi sembra a posto. Lo confronti con la versione case sensitive giusto ? Con grep -i quanti risultati ottieni ?
clockover
09-02-2013, 07:13
cat out.txt | grep -ic notaio
Risultato = 72
Vim:%s/notaio//gni
Risultato = 80
Idem per il mio script
Vincenzo1968
09-02-2013, 09:00
In realta' occorre anche molto meno di perl
Un termine di paragone su cui confrontrarsi potrebbe essere una implementazione naive da linea di comando
Ad esempio
time grep -nh notaio filename.txt | cut -f1 -d: | tail
oppure
awk '/ notaio / {print FNR}' filename.txt
Potrebbero essere dei buoni candidati. Il secondo e' più corretto perche' cerca la parola intera (circa).
Ohé, grep mi batte di tre secondi:
http://img546.imageshack.us/img546/3534/grepnotaio.jpg
:mbe:
awk:
http://img850.imageshack.us/img850/227/awknotaio.jpg
Vincenzo1968
09-02-2013, 09:29
Io ci ho messo 10 minuti a farlo in java. Quando ci vuole in C? :O
Poi quando arrivate ai tempi di lucene fate un fischio che finisco un piccolo esperimento di qualche giorno fa. Con il file 5 gb...
indice creato in 133439.146 ms. contiene 155022337 righe. occupa 154338712 bytes
warming up the jvm...ok
ho trovato la parola 'ora' in 310 righe. ci ho messo 0.135 ms
:fiufiu:
Versione punto B.1 con Inverted Index:
Passo 1: creare directory dove piazzare i file .c
http://img51.imageshack.us/img51/3466/c19b01invertedindex.jpg
Vedi? :O
http://www.hwupgrade.org/public/style_emoticons/default/patpat.gif
cat out.txt | grep -ic notaio
Risultato = 72
Vim:%s/notaio//gni
Risultato = 80
Idem per il mio script
Ah giusto.
grep -c conta il numero di linee. Se piu' parole sono sulla stessa linea viene considerata una singola occorrenza.
The_ouroboros
09-02-2013, 10:55
cat out.txt | awk 'BEGIN{x=0} /string/{x+=1} END{print "String found ",x," times"}'
The_ouroboros
09-02-2013, 11:24
Questo codice Perl, semplice ma efficace, dovrebbe andare.
#!/usr/bin/perl -w
use v5.12;
my $count;
open (FH, $ARGV[0]);
while(my $w = <FH>) {
my @matches = $w =~ m/(ciao)/g;
$count += scalar(@matches);
}
if ($count == 1) {
say "Found 1 time"
}
else {
say "Found $count times"
}
Con un file cosi
ciao io ciao
ciao
Restituisce
http://i45.tinypic.com/vg34wg.jpg
P.S: ciao era è stringa dummy
Vincenzo1968
09-02-2013, 11:34
cat out.txt | awk 'BEGIN{x=0} /string/{x+=1} END{print "String found ",x," times"}'
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time cat fileA_5GiB.txt | awk 'BEGIN{x=0} /string/{x+=1} END{print "String found ",x," times"}'String found 121800 times
real 0m48.803s
user 0m42.699s
sys 0m17.173s
Che stringa trova? Non c'è la parola "notaio" nel comando che hai postato. :confused:
The_ouroboros
09-02-2013, 11:37
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time cat fileA_5GiB.txt | awk 'BEGIN{x=0} /string/{x+=1} END{print "String found ",x," times"}'String found 121800 times
real 0m48.803s
user 0m42.699s
sys 0m17.173s
Che stringa trova? Non c'è la parola "notaio" nel comando che hai postato. :confused:
se non la metti al posto di string non te la trova.
Mea culpa, forse non ho messo bene in evidenza che andava sostituita :asd:
Vincenzo1968
09-02-2013, 11:40
Questo codice Perl, semplice ma efficace, dovrebbe andare.
#!/usr/bin/perl -w
use v5.12;
my $count;
open (FH, $ARGV[0]);
while(my $w = <FH>) {
my @matches = $w =~ m/(ciao)/g;
$count += scalar(@matches);
}
say "Found $count times"
Con un file cosi
ciao io ciao
ciao
Restituisce
http://i45.tinypic.com/vg34wg.jpg
Ho cambiato nel codice "ciao" con "notaio":
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time perl c19b01Ouro.pl fileA_5GiB.txt
Found 35634 times
real 0m40.840s
user 0m34.650s
sys 0m5.248s
;)
Ohé, grep mi batte di tre secondi:
http://img546.imageshack.us/img546/3534/grepnotaio.jpg
:mbe:
awk:
http://img850.imageshack.us/img850/227/awknotaio.jpg
Beh sia grep che awk usano automi a stati per il match e delle tecniche per minimizzare l'I/O per cui non mi stupisce che funzioni bene per queste cose.
Mi sorprende però awk, visto che c'è una differenza notevole tra la ricerca con spazi attorno e quella senza.. mi aspettavo non fosse molto più lento di grep...
Vincenzo1968
09-02-2013, 11:42
se non la metti al posto di string non te la trova.
Mea culpa, forse non ho messo bene in evidenza che andava sostituita :asd:
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time cat fileA_5GiB.txt | awk 'BEGIN{x=0} /notaio/{x+=1} END{print "String found ",x," times"}'String found 33366 times
real 0m46.699s
user 0m40.211s
sys 0m16.721s
Ragazzi, ricordatevi che sono niubazzo su Linux :D
Vincenzo1968
09-02-2013, 11:45
Beh sia grep che awk usano automi a stati per il match e delle tecniche per minimizzare l'I/O per cui non mi stupisce che funzioni bene per queste cose.
Mi sorprende però awk, visto che c'è una differenza notevole tra la ricerca con spazi attorno e quella senza.. mi aspettavo non fosse molto più lento di grep...
Secondo me awk perde tempo perché stampa ogni riga che trova. Stampa a video un fottìo di righe.
Dite che è una buona idea questo libro per imparare AWK?
http://www.amazon.com/exec/obidos/ASIN/1565922255/deloriesoftware
Vincenzo1968
09-02-2013, 11:50
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time ./c19b01Vincenzo1968New fileA_5GiB.txt notaio
Exact match della stringa: <notaio>
Ho trovato 34984 occorrenze della stringa "notaio".
I primi dieci risultati:
Riga 203
Riga 1033
Riga 1075
Riga 1805
Riga 1805
Riga 3532
Riga 3611
Riga 4547
Riga 4776
Riga 5108
real 0m29.491s
user 0m21.997s
sys 0m5.612s
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time ./c19b01Vincenzo1968New fileA_5GiB.txt notaio --case-insensitive
Exact match della stringa: <notaio>
Ho trovato 35308 occorrenze della stringa "notaio".
I primi dieci risultati:
Riga 203
Riga 1033
Riga 1075
Riga 1805
Riga 1805
Riga 3532
Riga 3611
Riga 4547
Riga 4776
Riga 5108
real 0m40.414s
user 0m34.170s
sys 0m4.964s
vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ time ./c19b01Vincenzo1968New fileA_5GiB.txt notaio --case-insensitive --partial
Partial match della stringa: <notaio>
Ho trovato 35956 occorrenze della stringa "notaio".
I primi dieci risultati:
Riga 203
Riga 1033
Riga 1075
Riga 1805
Riga 1805
Riga 3532
Riga 3611
Riga 4547
Riga 4776
Riga 5108
real 0m37.263s
user 0m29.954s
sys 0m5.168s
:D
The_ouroboros
09-02-2013, 11:56
Dite che è una buona idea questo libro per imparare AWK?
http://www.amazon.com/exec/obidos/ASIN/1565922255/deloriesoftware
io l'ho preso e te lo consiglio oltre al manuale GNU di gawk.
Ci farò un pensiero.
Posso proporre uno sbatti infinito a Vincenzo? :D :stordita:
Perchè non metti in prima pagina i link ai post dei codici dei vari utenti che hanno completato i vari punti con successo ( ad esempio il python di VICIUS per il B2 ).
Perchè se qualcuno volesse poi iniziare a fare il punto B3 partendo da un sorgente già pronto, a cercarlo qua dentro in sto casino non è facile..
Propongo eh, poi se non volete bon :stordita:
Vincenzo1968
09-02-2013, 12:08
Ci farò un pensiero.
Posso proporre uno sbatti infinito a Vincenzo? :D :stordita:
Perchè non metti in prima pagina i link ai post dei codici dei vari utenti che hanno completato i vari punti con successo ( ad esempio il python di VICIUS per il B2 ).
Perchè se qualcuno volesse poi iniziare a fare il punto B3 partendo da un sorgente già pronto, a cercarlo qua dentro in sto casino non è facile..
Propongo eh, poi se non volete bon :stordita:
Ottima idea. Datemi il tempo di comprire i file e uploadarli. ;)
EDIT: No, i link no ché dovrei andare a cercarmi i singoli post e, come dici tu, in 'sto casino, sarebbe follia pura. :D
Ottima idea. Datemi il tempo di comprire i file e uploadarli. ;)
EDIT: No, i link no ché dovrei andare a cercarmi i singoli post e, come dici tu, in 'sto casino, sarebbe follia pura. :D
Si ma metti le ultime versioni e comunque solo quelle che funzionano in tempo ragionevole ( tipo quella fatta da me non è tra queste :asd: ).
Vincenzo1968
09-02-2013, 12:18
Ecco i sorgenti dei partecipanti:
http://www.filedropper.com/c19uploadtar
;)
The_ouroboros
09-02-2013, 12:19
di mio non c'è molto a parte il programmino in perl.
Tra l'altro l'ho fixato così da la giusta dicitura nella found string :cool:
Vincenzo1968
09-02-2013, 12:21
di mio non c'è molto a parte il programmino in perl.
Tra l'altro l'ho fixato così da la giusta dicitura nella found string :cool:
Potevi dirlo prima.
http://www.hwupgrade.org/public/style_emoticons/default/rage.png
Posta il codice che aggiorno il link. ;)
The_ouroboros
09-02-2013, 12:24
#!/usr/bin/perl -w
use v5.12;
my $count;
open (FH, $ARGV[0]);
while(my $w = <FH>) {
my @matches = $w =~ m/(ciao)/g;
$count += scalar(@matches);
}
if ($count == 1) {
say "Found 1 time"
}
else {
say "Found $count times"
}
Vincenzo1968
09-02-2013, 12:31
Eqque qua:
http://www.filedropper.com/c19sourcestar
Ragazzi, io per oggi forse non mi collegherò più(e forse nemmeno domani).
C'è da asfaltare Vicius-Lucene; dunque mi dedicherò interamente all'implementazione dell'Inverted Index per il punto B.1.
Adieu e cavoli vostri(cit.).
:D
Ecco i sorgenti dei partecipanti:
http://www.filedropper.com/c19uploadtar
;)
Eqque qua:
http://www.filedropper.com/c19sourcestar
Ragazzi, io per oggi forse non mi collegherò più(e forse nemmeno domani).
C'è da asfaltare Vicius-Lucene; dunque mi dedicherò interamente all'implementazione dell'Inverted Index per il punto B.1.
Adieu e cavoli vostri(cit.).
:D
Grazie ;)
Vincenzo1968
09-02-2013, 14:14
In buona sostanza io il mio indice lo creo su una sottodirectory della directory dove è piazzato l'eseguibile.
La sottodirectory su chiama "c19b01Index". All'interno di questa creo una sottodirectory chiamata col nome scelto dall'utente per l'indice(nome passato al programma da riga di comando).
Per esempio, se l'utente passa il parametro "--createindex myIndex", il programma crea la cartella "./c19b01Index/myIndex" e all'interno vi piazza il file(o i file, ancora non ho deciso) indice.
;)
int createDirectory(const char* indexName)
{
int status;
char szPath[512];
#if __linux__ || __APPLE__
strcpy(szPath, "./c19b01Index/");
strcat(szPath, directoryName);
mkdir("./c19b01Index", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
chdir("./c19b01Index");
mkdir(indexName, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
status = chdir(indexName);
if ( status != 0 )
{
printf("\nErrore! Impossibile creare la directory\"%s\". Addio!\n", szPath);
return 0;
}
chdir("../..");
//printf("\n\nDirectory \"%s\" creata con successo!\n\n", szPath);
#else
/* Qui il codice per Windows */
#endif
return 1;
}
Ci farò un pensiero.
Posso proporre uno sbatti infinito a Vincenzo? :D :stordita:
Perchè non metti in prima pagina i link ai post dei codici dei vari utenti che hanno completato i vari punti con successo ( ad esempio il python di VICIUS per il B2 ).
Perchè se qualcuno volesse poi iniziare a fare il punto B3 partendo da un sorgente già pronto, a cercarlo qua dentro in sto casino non è facile..
Propongo eh, poi se non volete bon :stordita:
Ottima idea. Datemi il tempo di comprire i file e uploadarli. ;)
EDIT: No, i link no ché dovrei andare a cercarmi i singoli post e, come dici tu, in 'sto casino, sarebbe follia pura. :D
Non sarebbe più comodo aprire un repository su github in cui tutti possono pushare il proprio codice in una sottocartella "personale"?
The_ouroboros
09-02-2013, 14:57
Appoggio l'idea :D
Vincenzo1968
09-02-2013, 15:21
Non sarebbe più comodo aprire un repository su github in cui tutti possono pushare il proprio codice in una sottocartella "personale"?
Ok! Apritelo, io non so come si fa :D Il link per scaricare i sorgenti l'avete. Datemi il link su github che aggiorno la prima pagina.
;)
Questo è il codice completo per creare la directory per il file indice:
int createDirectory(const char* indexName)
{
char szPath[512];
#if __linux__ || __APPLE__
int status;
strcpy(szPath, "./c19b01Index/");
strcat(szPath, indexName);
mkdir("./c19b01Index", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
chdir("./c19b01Index");
mkdir(indexName, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
status = chdir(indexName);
if ( status != 0 )
{
printf("\nErrore! Impossibile creare la directory\"%s\". Addio!\n", szPath);
return 0;
}
chdir("../..");
#else
char szCurrPath[512];
strcpy(szPath, "c19b01Index/");
strcat(szPath, indexName);
GetCurrentDirectory(511, szCurrPath);
CreateDirectory("c19b01Index", NULL);
CreateDirectory(szPath, NULL);
if ( !SetCurrentDirectory(szPath) )
{
printf("\nErrore! Impossibile creare la directory 2\"%s\". Addio!\n", szPath);
return 0;
}
SetCurrentDirectory(szCurrPath);
#endif
return 1;
}
The_ouroboros
09-02-2013, 15:35
https://github.com/hwupgradecontest/contest19
Vincenzo1968
09-02-2013, 15:44
https://github.com/hwupgradecontest/contest19
Azz! Gia fatto! :eek:
Ma come si usa? :D
The_ouroboros
09-02-2013, 15:46
aggiungi un file.
Chi vuole modificarlo lo fa mettendo una descrizione di cosa ha fatto e da li puoi vedere lo storico dei cambiamenti, ritornare indietro o fare un fork lasciando l'oiginale com'era.
Vincenzo1968
09-02-2013, 15:53
Ok, aggiornato il primo post col link a github.
;)
The_ouroboros
09-02-2013, 15:56
c'è posta per te. :fagiano:
The_ouroboros
09-02-2013, 15:59
[OT]
a chi servisse: http://windows.github.com/
Vincenzo1968
09-02-2013, 16:03
Poi dice che i contest non servono a niente. Vedete quante velle cose s'imparano? :D
The_ouroboros
09-02-2013, 16:07
[ot]
e vi dirò di più : Guida tascabile GIT (http://rogerdudler.github.com/git-guide/index.it.html)
e
Piccolo aiutino su github (http://shinworld.altervista.org/wordpress/creare-un-repository-su-github/)
Bella l'idea di github. Ho fatto un fork con le mie due versioni del punto a e aperto una pull request. Domani se ho tempo metto su anche il resto.
The_ouroboros
09-02-2013, 17:18
mergiato con il master :D
The_ouroboros
09-02-2013, 17:47
e ho pure fatto una lieve modifica al mio perl
Vincenzo1968
09-02-2013, 17:54
Bella l'idea di github. Ho fatto un fork con le mie due versioni del punto a e aperto una pull request. Domani se ho tempo metto su anche il resto.
Se mi spiegaste che significa pull request ve ne sarei grato... E che vuol dire fare un fork delle due versioni? E mergiato con il master?
http://www.hwupgrade.org/public/style_emoticons/default/rage.png
The_ouroboros
09-02-2013, 17:57
Se mi spiegaste che significa pull request ve ne sarei grato... E che vuol dire fare un fork delle due versioni? E mergiato con il master?
http://www.hwupgrade.org/public/style_emoticons/default/rage.png
pull request = richiesta di integrare codice
fork = prendo il codice intero, creo un nuovo progetto che parte da questo ma non modifica l'originale
mergiare = accettare e fondere il codice esterno della pull e renderlo parte del master
Meglio? Altrimenti spiego di più... ultimamente sono un pocherello sintetico :doh:
The_ouroboros
09-02-2013, 18:06
[ot]
ricordo che per sottomettere una pull bisogna avere un account su github.
Dopo aver fatto la pull mandate un pm a Vincenzo1968 (o a me, come backup) per essee mergiati
Vincenzo1968
09-02-2013, 18:33
[ot]
ricordo che per sottomettere una pull bisogna avere un account su github.
Dopo aver fatto la pull mandate un pm a Vincenzo1968 (o a me, come backup) per essee mergiati
No a me no che non ne sto capendo un tubo. Chi vuol gestire la cosa insieme a The_ouroboros?
:stordita:
The_ouroboros
09-02-2013, 18:40
dai un occhio alle guide che ho postato sopra.
Cmq fare un merge su github è semplice.
L'interfaccio del sito è semplice :)
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.