PDA

View Full Version : [Vari] Contest 19: Full Text Search(e non solo).


Pagine : 1 [2] 3 4 5

gugoXX
25-01-2013, 20:08
Ho scritto il codice, ma non posso davvero testarlo con file grossi.
Innanzitutto ho un SSD, e non penso che si possa confrontare con gli altri.
Poi di sicuro non vado a fare file da 5GB cosi' a caso...

Vincenzo1968
25-01-2013, 20:09
Come non detto: il mio programma funziona anche con stringhe contenenti spazi. Basta racchiudere la stringa di ricerca tra doppie virgole:


ptime c19b01Vincenzo1968 output.txt "Scacciato Candido dal paradiso terrestre" --case-insensitive

Inizio la ricerca case-insensitive della stringa: Scacciato Candido dal paradiso terrestre
Trovato alla riga 5 colonna 335
Trovato alla riga 8 colonna 882
Trovato alla riga 14 colonna 52
Trovato alla riga 15 colonna 1287
Trovato alla riga 17 colonna 109
[cut] troppo lungo ;)
Trovato alla riga 1226 colonna 360
Trovato alla riga 1229 colonna 109
Trovato alla riga 1231 colonna 1051
Trovato alla riga 1234 colonna 69
Trovato alla riga 1241 colonna 81
Trovato alla riga 1246 colonna 171
Trovato alla riga 1250 colonna 1294
Trovato alla riga 1253 colonna 459
Trovato alla riga 1259 colonna 29
Trovato alla riga 1266 colonna 25
Trovato alla riga 1271 colonna 504
Trovato alla riga 1274 colonna 263
Trovato alla riga 1277 colonna 629
Trovato alla riga 1284 colonna 190
Trovato alla riga 1290 colonna 121
Trovato alla riga 1296 colonna 214

Ho letto 524288 blocchi.

Finito!

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== c19b01Vincenzo1968 output.txt "Scacciato Candido dal paradiso terrestre" --case-insensitive ===

Execution time: 40.110 s


Ma ho un problema coi caratteri accentati. Debbo sistemarlo.

VICIUS
25-01-2013, 21:56
Ho buttato giù qualcosa con lucene. Non fa esattamente quello che chiedono i vari punti ma abbiate pazienza. È un po' che non lo uso e non ho voglia di aprire i docs. :stordita:

Binari (http://cl.ly/MRsS), Sorgenti (http://cl.ly/MQaL)
E un piccolo screenshot che lo mostra in azione. Prego notare l'evidenziazione direttamente nella shell :sofico:

http://f.cl.ly/items/2m2A1z2u0u1m1Z143n0Y/lucene-search.png

Vincenzo1968
25-01-2013, 23:03
Ho scritto il codice, ma non posso davvero testarlo con file grossi.
Innanzitutto ho un SSD, e non penso che si possa confrontare con gli altri.
Poi di sicuro non vado a fare file da 5GB cosi' a caso...

Posta il codice che lo provo da me e pubblico i risultati.

Zippa tutto e mettilo in qualche sito per il file upload, tipo questo:

http://www.filedropper.com/

;)

Vincenzo1968
25-01-2013, 23:03
Grande Vicius!

:yeah: :winner: :yeah:

Vincenzo1968
26-01-2013, 10:30
Per semplificare il punto io proporrei la ricerca di una singola parola senza distinzione tra maiuscole o minuscole con caratteri esclusivamente alfabetici e senza occorrenze parziali (se gli dico di cercare tempo non mi deve trovare temporale).



Esatto. Facciamo così. Però non di una singola parola. Deve trovare la corrispondenza esatta anche se la stringa di ricerca è costituita da una o più parole separate da spazi.


Anzi no, è meglio passare un parametro da riga di comando per le corrispondenze parziali.
Il parametro da passare è: --partial.
Se non viene passato tale parametro il programma trova la corrispondenza esatta.

Dobbiamo confrontarci con Lucene, Indri e Zettair che offrono tante belle funzionalità. E noi? Vogliamo essere da meno? :D

Vincenzo1968
26-01-2013, 10:52
Lucene Build Instructions

Basic steps:
0) Install JDK 1.6 (or greater), Ant 1.8.2+, Ivy 2.2.0
1) Download Lucene from Apache and unpack it
2) Connect to the top-level of your Lucene installation
3) Install JavaCC (optional)
4) Run ant

Step 0) Set up your development environment (JDK 1.6 or greater,
Ant 1.8.2+, Ivy 2.2.0)

We'll assume that you know how to get and set up the JDK - if you
don't, then we suggest starting at http://java.sun.com and learning
more about Java, before returning to this README. Lucene runs with
JDK 1.6 and later.

Like many Open Source java projects, Lucene uses Apache Ant for build
control. Specifically, you MUST use Ant version 1.8.2+.

Ant is "kind of like make without make's wrinkles". Ant is
implemented in java and uses XML-based configuration files. You can
get it at:

http://ant.apache.org

You'll need to download the Ant binary distribution. Install it
according to the instructions at:

http://ant.apache.org/manual

Finally, you'll need to install ivy into your ant lib folder
(~/.ant/lib). You can get it from http://ant.apache.org/ivy/.
If you skip this step, the Lucene build system will offer to do it
for you.

Step 1) Download Lucene from Apache

We'll assume you already did this, or you wouldn't be reading this
file. However, you might have received this file by some alternate
route, or you might have an incomplete copy of the Lucene, so: Lucene
releases are available for download at:

http://www.apache.org/dyn/closer.cgi/lucene/java/

Download either a zip or a tarred/gzipped version of the archive, and
uncompress it into a directory of your choice.

Step 2) From the command line, change (cd) into the top-level directory of your Lucene installation

Lucene's top-level directory contains the build.xml file. By default,
you do not need to change any of the settings in this file, but you do
need to run ant from this location so it knows where to find build.xml.

If you would like to change settings you can do so by creating one
or more of the following files and placing your own property settings
in there:

~/lucene.build.properties
~/build.properties
lucene-x.y/build.properties

The first property which is found in the order with which the files are
loaded becomes the property setting which is used by the Ant build
system.

NOTE: the ~ character represents your user account home directory.

Step 3) Run ant

Assuming you have ant in your PATH and have set ANT_HOME to the
location of your ant installation, typing "ant" at the shell prompt
and command prompt should run ant. Ant will by default look for the
"build.xml" file in your current directory, and compile Lucene.

If you want to build the documentation, type "ant documentation".

For further information on Lucene, go to:
http://lucene.apache.org/

Please join the Lucene-User mailing list by visiting this site:
http://lucene.apache.org/core/discussion.html

Please post suggestions, questions, corrections or additions to this
document to the lucene-user mailing list.

This file was originally written by Steven J. Owens <puff@darksleep.com>.
This file was modified by Jon S. Stevens <jon@latchkey.com>.

Copyright (c) 2001-2005 The Apache Software Foundation. All rights reserved.


Basic steps:
0) Install JDK 1.6 (or greater), Ant 1.8.2+, Ivy 2.2.0
1) Download Lucene from Apache and unpack it
2) Connect to the top-level of your Lucene installation
3) Install JavaCC (optional)
4) Run ant

Non capisco il punto 2. Che significa connect to the top-level of your Lucene installation? E che sono Ant e Ivy?

Vincenzo1968
26-01-2013, 11:04
http://img841.imageshack.us/img841/5159/antivy.jpg

http://img845.imageshack.us/img845/6420/antivy2.jpg

http://img594.imageshack.us/img594/8144/ivyu.jpg

http://img194.imageshack.us/img194/1633/antyl.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

Rimane da capire il punto 2.

Vincenzo1968
26-01-2013, 11:26
http://img849.imageshack.us/img849/149/ivyerror.jpg

'mbé? :mbe:

Ivy l'ho installato...

:confused:

Vincenzo1968
26-01-2013, 11:37
sudo ln -s -T /usr/share/java/ivy.jar /usr/share/ant/lib/ivy.jar

http://img14.imageshack.us/img14/7/ivysolved.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

Vincenzo1968
26-01-2013, 11:50
http://img716.imageshack.us/img716/9245/errorvicius.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

VICIUS
26-01-2013, 13:36
Controlla che il file .jar sia in quella cartella. :)

Vincenzo1968
26-01-2013, 13:54
Anzi no, è meglio passare un parametro da riga di comando per le corrispondenze parziali.
Il parametro da passare è: --partial.
Se non viene passato tale parametro il programma trova la corrispondenza esatta.

Dobbiamo confrontarci con Lucene, Indri e Zettair che offrono tante belle funzionalità. E noi? Vogliamo essere da meno? :D

Esempio:

File prova.txt:
file prova.txt:

Riga 01: Dammi il tempo.
Riga 02: Sta per abbattersi un temporale.
Riga 03: Sta per abbattersi un temporale allucinante.
Riga 04: Il temporale è passato.
Riga 05: Vorrei trovare il tempo per fare tutto.
Riga 06: Questa è una soluzione temporanea.
Riga 07: Ciao ciao.
Riga 08: Adieu e cavoli vostri(cit.).


Output:

./c19b01 prova.txt tempo --case-insensitive

Ricerca non partial della stringa: tempo
Inizio la ricerca case-insensitive della stringa: tempo
Trovato alla riga 1 colonna 19
Trovato alla riga 5 colonna 28

Finito!
./c19b01 prova.txt tempo --case-insensitive --partial

Ricerca partial della stringa: tempo
Inizio la ricerca case-insensitive della stringa: tempo
Trovato alla riga 1 colonna 19
Trovato alla riga 2 colonna 31
Trovato alla riga 3 colonna 31
Trovato alla riga 4 colonna 13
Trovato alla riga 5 colonna 28
Trovato alla riga 6 colonna 34

Finito!

Vincenzo1968
26-01-2013, 13:57
Controlla che il file .jar sia in quella cartella. :)

Non c'è:

http://img259.imageshack.us/img259/6205/viciusjar2.jpg
http://img405.imageshack.us/img405/5127/viciusjar.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

VICIUS
26-01-2013, 14:05
Certo che sei proprio un masochista. Ti ho caricato il file jar già compilato e con tutte le librerie incluse così non devi sbatterti. E tu cosa fai? Ti compili i java a mano? :rotfl:

Vincenzo1968
26-01-2013, 14:08
Certo che sei proprio un masochista. Ti ho caricato il file jar già compilato e con tutte le librerie incluse così non devi sbatterti. E tu cosa fai? Ti compili i java a mano? :rotfl:

Ho decompresso Contest.jar nella cartella Exe ma continua a darmi l'errore.

:confused:

VICIUS
26-01-2013, 14:16
Ho decompresso Contest.jar nella cartella Exe ma continua a darmi l'errore.

:confused:
Chi ti ha detto di decomprimerlo? :muro:

Vincenzo1968
26-01-2013, 14:23
Chi ti ha detto di decomprimerlo? :muro:

http://www.hwupgrade.org/public/style_emoticons/default/rage.png

Vincenzo1968
26-01-2013, 14:27
http://img607.imageshack.us/img607/5476/jarnondecompresso.jpg

Continua a darmi l'errore.

http://www.hwupgrade.org/public/style_emoticons/default/rage.png

VICIUS
26-01-2013, 14:44
Assicurati di essere veramente nella cartella giusta e di scrivere il nome correttamente. Maiuscole/minuscole sono importanti.

Vincenzo1968
26-01-2013, 14:49
Assicurati di essere veramente nella cartella giusta e di scrivere il nome correttamente. Maiuscole/minuscole sono importanti.

Quant'è bello installare programmi scritti in C?

Guarda quant'è semplice:


./configure
make -j2
sudo make install


http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

VICIUS
26-01-2013, 15:12
Quant'è bello installare programmi scritti in C?

Guarda quant'è semplice:


./configure
make -j2
sudo make install


http://www.hwupgrade.org/public/style_emoticons/default/coolface.png
Java è ancora più semplice. Una volta scaricato non devi fare niente. In questo caso sospetto che il problema sia tra lo schermo e la sedia. :asd:

Vincenzo1968
26-01-2013, 15:29
http://www.hwupgrade.org/public/style_emoticons/default/patpat.gif

http://img545.imageshack.us/img545/6871/luceneoutput.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

VICIUS
26-01-2013, 15:52
Bravo. Vedi che non era difficile? :D

Se vuoi giocare un po' dai un occhiata a questa introduzione alla sintassi del query parser standard.
http://lucene.apache.org/core/4_1_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description

Vincenzo1968
26-01-2013, 16:10
prova.txt:

Riga 01: Dammi il tempo.
Riga 02: Sta per abbattersi un temporale.
Riga 03: Sta per abbattersi un temporale allucinante.
Riga 04: Il temporale è passato.
Riga 05: Vorrei trovare il tempo per fare tutto.
Riga 06: Questa è una soluzione temporanea.
Riga 07: Ciao ciao.
Riga 08: Adieu e cavoli vostri(cit.).


http://img11.imageshack.us/img11/4659/c19b01myoutput.jpg


http://img23.imageshack.us/img23/5674/cavoli.jpg


Debbo sistemare solo la faccenda delle vocali accentate. Poi posto il codice.

;)

Vincenzo1968
26-01-2013, 16:11
Bravo. Vedi che non era difficile? :D

Se vuoi giocare un po' dai un occhiata a questa introduzione alla sintassi del query parser standard.
http://lucene.apache.org/core/4_1_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description

Eh ma è in Java...

Java :rolleyes:












Scheeeerzoooooooooooo!!! :D

Gli do un'occhiata. Grazie per il link ;)

Vincenzo1968
26-01-2013, 17:05
Inutile dire che il nostro motore di ricerca dovrà implementare tutte quelle belle caratteristiche illustrate nel link segnalato da Vicius:

http://lucene.apache.org/core/4_1_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Wildcard_Searches

http://lucene.apache.org/core/4_1_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Regexp_Searches

http://lucene.apache.org/core/4_1_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Fuzzy_Searches

http://lucene.apache.org/core/4_1_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Proximity_Searches

http://lucene.apache.org/core/4_1_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Range_Searches

http://lucene.apache.org/core/4_1_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Boosting_a_Term

Il punto B.1 è solo l'inizio...

VICIUS
26-01-2013, 17:49
Cercare di replicare le funzionalità di lucene per un semplice contest è stupido. Non importa quanto siate bravi non riuscirete mai neanche ad avvicinarvi a quello che può fare. Stiamo parlando di uno dei progetti di punta della fondazione apache con 15 anni di sviluppo alle spalle.

Se volete divertirvi ad implementare qualcosa di vostro dovete rimanere su qualcosa di molto semplice e non cercare di combattere contro i mulini a vento.

Definite un paio di regole semplici su come vadano tokenizzate le stringhe. Poi limitatevi ad implementare ricerche di termini singoli e di frasi. Già così di carne al fuoco ce n'è molta.

Vincenzo1968
26-01-2013, 18:36
Risolto caratteri accentati:

http://img69.imageshack.us/img69/4994/risoltocaratteriaccenta.jpg

Domani posto il codice.

Vincenzo1968
26-01-2013, 18:39
Cercare di replicare le funzionalità di lucene per un semplice contest è stupido. Non importa quanto siate bravi non riuscirete mai neanche ad avvicinarvi a quello che può fare. Stiamo parlando di uno dei progetti di punta della fondazione apache con 15 anni di sviluppo alle spalle.

Se volete divertirvi ad implementare qualcosa di vostro dovete rimanere su qualcosa di molto semplice e non cercare di combattere contro i mulini a vento.

Definite un paio di regole semplici su come vadano tokenizzate le stringhe. Poi limitatevi ad implementare ricerche di termini singoli e di frasi. Già così di carne al fuoco ce n'è molta.

Io l'ho detto per farvi spaventare. E infatti te la sei fatta di sopra( o te la sei fatta sotto? Come si dice?).

Scheeeerzooooo :D

Comunque più funzionalità implementiamo meglio è. Ancora ci sono i punti B.2, B.3, etc.

;)

Vincenzo1968
27-01-2013, 11:26
Lucene. File da 5 GiB.

fileA.txt:

http://img856.imageshack.us/img856/7326/tempicreateindexlucene5.jpg

http://img801.imageshack.us/img801/6859/tempilucenefile5gib.jpg

Vincenzo1968
27-01-2013, 13:16
Punto B.1; algoritmo brute force; dimensione file 5 GiB

fileA.txt:
http://img502.imageshack.us/img502/5933/c19b01tempibruteforcevi.jpg

Vincenzo1968
27-01-2013, 13:20
C'è qualcosa che non va o in Lucene o nel mio. Sicuramente nel mio.

Com'è che le prime dieci righe non corrispondono visto che il file utilizzato è lo stesso(fileA.txt)?

Bisognerebbe scrivere un programmino che prenda in input il nome del file e il numero di riga e che stampi la riga selezionata.


EDIT: non corrisponde nemmeno il numero delle occorrenze.

Vincenzo1968
27-01-2013, 13:25
Questo è il mio brute force:

Da compilare(con GCC/Linux) così:

gcc -O3 puntob01.c -o c19b01Vincenzo1968


-O3 leggasi: segno meno seguito da "vocale O maiuscola" seguita dal numero tre.

Volendo è possibile sostituire "gcc" con "clang" o, se l'avete scaricato e installato, col compilatore Intel: "icc".

puntob01.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
#include <stdint.h>
#include <ctype.h>

//#define BLOCK_SIZE 4096
#define BLOCK_SIZE 8192

typedef struct tagFindRec
{
long countFind;
long *arrayRows;
} FindRec;

void MakeIndex(const char *szFileName)
{
long x;
uint64_t sizeData;
uint64_t howPages;
long numread;
long lastBlockLen;
FILE *fp;
unsigned char *myBlock = NULL;

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 = (long)(sizeData - howPages * BLOCK_SIZE);

numread = 0;
while ( numread = fread(myBlock, 1, BLOCK_SIZE, fp) )
{
//numread = fread(myBlock, 1, 4096, fp);
if ( numread < BLOCK_SIZE )
{
//printf("\nHo quasi finito...\n");
//printf("L'ultimo blocco è lungo %ld byte.\n", numread);
//break;
}
//sizeData += numread;
}

if ( lastBlockLen )
{
printf("\nHo letto %ld blocchi.\n", howPages + 1);
//printf("\nHo letto %ld blocchi da 4096 byte\n", howPages + 1);
printf("\nL'ultimo blocco è lungo %ld byte.\n", lastBlockLen);
}
else
{
printf("\nHo letto %ld blocchi.\n", howPages);
//printf("\nHo letto %ld blocchi da 4096 byte\n", howPages);
//printf("L'ultimo blocco è lungo 4096 byte.\n");
}

fclose(fp);
}

int isValidSeparatorChar(unsigned char c)
{
switch (c)
{
case 32:
case 34:
case 39:
case 40:
case 41:
case 44:
case 45:
case 46:
case 58:
case 59:
case 60:
case 62:
case 63:
case 91:
case 93:
case 123:
case 124:
case 125:
case 174:
case 175:
case 240:
case 246:
return 1;
default:
return 0;

}
return 0;
}

void BruteForceSearch(const char *szFileName, unsigned char *szSearch, int bCaseInsensitive, FindRec *myFindRec)
{
long x;
long index1, index2;
long lenStrSearch;
unsigned char lastCharInStringSearch;
uint64_t sizeData;
uint64_t howPages;
//long numread;
long lastBlockLen;
long blockLen;
long blockLenTemp;
long currBlock;
long long int row;
long long int column;
char cPrevious, cNext;
FILE *fp;
unsigned char *myBlock = NULL;
unsigned char *myBlockNext = NULL;

myFindRec->countFind = 0;

lenStrSearch = strlen((char*)szSearch);

lastCharInStringSearch = szSearch[lenStrSearch - 1];

if ( bCaseInsensitive )
{
x = 0;
while ( x < lenStrSearch )
{
if ( szSearch[x] >= 'A' && szSearch[x] <= 'Z' )
szSearch[x] = szSearch[x] + 32;
x++;
}
}

myBlock = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlock )
{
printf("Memoria insufficiente.\n");
return;
}

myBlockNext = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlockNext )
{
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 = (long)(sizeData - howPages * BLOCK_SIZE);

currBlock = 0;
row = column = 1;

while ( blockLen = fread(myBlock, 1, BLOCK_SIZE, fp) )
{
currBlock++;
index1 = 0;
while ( index1 < blockLen )
{
if ( myBlock[index1] == '\n' )
{
row++;
column = 1;
}
else
{
column++;
}

if ( bCaseInsensitive )
{
if ( myBlock[index1] >= 'A' && myBlock[index1] <= 'Z' )
myBlock[index1] = myBlock[index1] + 32;
}

if ( myBlock[index1++] != szSearch[0] )
{
if ( index1 >= 1 )
cPrevious = myBlock[index1 - 1];
else
cPrevious = -1;
continue;
}
else
{
index2 = 1;

if ( bCaseInsensitive )
{
if ( myBlock[index1] >= 'A' && myBlock[index1] <= 'Z' )
myBlock[index1] = myBlock[index1] + 32;
}

while ( szSearch[index2] == myBlock[index1] )
{
index2++;
index1++;
if ( index1 >= blockLen )
{
index1 = 0;
blockLen = fread(myBlock, 1, BLOCK_SIZE, fp);
currBlock++;
if ( blockLen <= 0 )
goto uscita;
}
if ( bCaseInsensitive )
{
if ( myBlock[index1] >= 'A' && myBlock[index1] <= 'Z' )
myBlock[index1] = myBlock[index1] + 32;
}
}
if ( index2 == lenStrSearch ) // Trovato
{
if ( index1 < blockLen )
{
cNext = myBlock[index1];
}
else
{
if ( index1 >= BLOCK_SIZE )
{
blockLenTemp = fread(myBlockNext, 1, BLOCK_SIZE, fp);

#if __linux__ || __APPLE__
fseeko(fp, -BLOCK_SIZE, SEEK_CUR);
#else
_fseeki64(fp, -BLOCK_SIZE, SEEK_CUR);
#endif

if ( blockLenTemp > 0 )
cNext = myBlockNext[0];
else
cNext = ' ';
}
else
{
cNext = myBlock[index1];
}
}
if
(
( szSearch[0] == ' ' || cPrevious == -1 || isValidSeparatorChar(cPrevious) )
&&
( lastCharInStringSearch == ' ' || isValidSeparatorChar(cNext) )
)
{
//myFindRec->countFind++;
if ( myFindRec->countFind < 10 )
{
myFindRec->arrayRows[myFindRec->countFind] = row;
//printf("Trovato alla riga %lld colonna %lld\n", row, column - 1);
}
myFindRec->countFind++;
}
}
}
}
}

uscita:
/*
if ( lastBlockLen )
{
printf("\nHo letto %ld blocchi.\n", howPages + 1);
printf("\nL'ultimo blocco è lungo %ld byte.\n", lastBlockLen);
}
else
{
printf("\nHo letto %ld blocchi.\n", howPages);
}
*/

fclose(fp);
}

void BruteForceSearchPartial(const char *szFileName, unsigned char *szSearch, int bCaseInsensitive, FindRec *myFindRec)
{
long x;
long index1, index2;
long lenStrSearch;
uint64_t sizeData;
uint64_t howPages;
//long numread;
long lastBlockLen;
long blockLen;
long currBlock;
long long int row;
long long int column;
//char c;
FILE *fp;
unsigned char *myBlock = NULL;

myFindRec->countFind = 0;

lenStrSearch = strlen((char*)szSearch);

if ( bCaseInsensitive )
{
x = 0;
while ( x < lenStrSearch )
{
//szSearch[x] = tolower(szSearch[x]);
if ( szSearch[x] >= 'A' && szSearch[x] <= 'Z' )
szSearch[x] = szSearch[x] + 32;
x++;
}
//szSearch[lenStrSearch] = '\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 = (long)(sizeData - howPages * BLOCK_SIZE);

currBlock = 0;
row = column = 1;

while ( blockLen = fread(myBlock, 1, BLOCK_SIZE, fp) )
{
currBlock++;
index1 = 0;
while ( index1 < blockLen )
{
if ( myBlock[index1] == '\n' )
{
row++;
column = 1;
}
else
{
column++;
}

if ( bCaseInsensitive )
{
if ( myBlock[index1] >= 'A' && myBlock[index1] <= 'Z' )
myBlock[index1] = myBlock[index1] + 32;
}

if ( myBlock[index1++] != szSearch[0] )
{
continue;
}
else
{
index2 = 1;

if ( bCaseInsensitive )
{
if ( myBlock[index1] >= 'A' && myBlock[index1] <= 'Z' )
myBlock[index1] = myBlock[index1] + 32;
}

while ( szSearch[index2] == myBlock[index1] )
{
index2++;
index1++;
if ( index1 >= blockLen )
{
index1 = 0;
blockLen = fread(myBlock, 1, BLOCK_SIZE, fp);
currBlock++;
if ( blockLen <= 0 )
goto uscita;
}
if ( bCaseInsensitive )
{
if ( myBlock[index1] >= 'A' && myBlock[index1] <= 'Z' )
myBlock[index1] = myBlock[index1] + 32;
}
}
if ( index2 == lenStrSearch ) // Trovato
{
if ( myFindRec->countFind < 10 )
{
myFindRec->arrayRows[myFindRec->countFind] = row;
//printf("Trovato alla riga %lld colonna %lld\n", row, column - 1);
}
myFindRec->countFind++;
}
}
}
}

uscita:
/*
if ( lastBlockLen )
{
printf("\nHo letto %ld blocchi.\n", howPages + 1);
printf("\nL'ultimo blocco è lungo %ld byte.\n", lastBlockLen);
}
else
{
printf("\nHo letto %ld blocchi.\n", howPages);
}
*/

fclose(fp);
}

void PrintHelp(const char *szProg)
{
printf("\nUso: %s NomeFileInput StringadaRicercare [opzionale: --case-insensitive]\n", szProg);

printf("\nIl parametro opzionale --case-insensitive serve per specificare\n");
printf("se si vuole effettuare una ricerca case-insensitive.\n");
printf("Se non si specifica viene effettuata una ricerca case-sensitive.\n");
}

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

/*
typedef struct tagFindRec
{
long countFind;
long *arrayRows;
} FindRec;
*/

void verificaRighe(const char *szFileName, FindRec *myFindRec)
{
long row = 1;
FILE *fp = NULL;
int k = 0;
int x = 0;
unsigned char *str = NULL;

fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s. Addio!\n", szFileName);
return;
}

str = (char*)malloc(1024*1024);
if ( !str )
{
printf("\nImpossibile allocare la memoria. Addio!\n");
fclose(fp);
return;
}

while (fgets(str, 1024*1024, fp) != NULL)
{
/*
if ( row == myFindRec->arrayRows[x++] )
{
if ( strlen(str) > 0 )
str[strlen(str) - 1] = '\0';
k++;
printf("\nRiga %ld : <%s>\n", row, str);
printf("\n-------------------------------------------------------------------------------------------\n");
if ( x >= 10 )
break;
}
row++;
*/

if ( row == 969 )
{
if ( strlen(str) > 0 )
str[strlen(str) - 1] = '\0';
k++;
printf("\nRiga %ld : <%s>\n", row, str);
printf("\n-------------------------------------------------------------------------------------------\n");
break;
}
row++;
}

fclose(fp);
free(str);
}

int main(int argc, char* argv[])
{
FindRec myFindRec;
char szExeName[256];
unsigned char szSearch[256];
clock_t c_start, c_end;
double TempoImpiegato;
int x;
int bPartial = 0;

if ( argc < 3 )
{

#ifdef __linux__
PrintHelp(argv[0]);
#else
ExtractFileName(argv[0], szExeName);
PrintHelp(szExeName);
#endif

printf("\nPremere INVIO per terminare.");
getc(stdin);

return -1;
}

strcpy((char*)szSearch, argv[2]);

//printf("\nargc = %d\n", argc);
//printf("\nargv[%d] = %s\n", argc-1, argv[argc-1]);

myFindRec.arrayRows = (long *)malloc(sizeof(long) * 10);
if ( !myFindRec.arrayRows )
{
printf("Memoria insufficiente.\n");
return;
}


if ( argc >= 5 )
{
if ( strcmp(argv[4], "--partial") == 0 )
bPartial = 1;
else
bPartial = 0;
}

/*
if ( bPartial )
printf("\nRicerca partial della stringa: <%s>\n", argv[2]);
else
printf("\nRicerca non partial della stringa: <%s>\n", argv[2]);
*/

//BruteForceSearchPartial(argv[1], argv[2], 1);

c_start = clock();
if ( (argc >= 4) && (strcmp(argv[3], "--case-insensitive") == 0) )
{
//printf("\nInizio la ricerca case-insensitive della stringa: <%s>\n", argv[2]);
if ( bPartial )
BruteForceSearchPartial(argv[1], szSearch, 1, &myFindRec);
else
BruteForceSearch(argv[1], szSearch, 1, &myFindRec);

}
else
{
//printf("\nInizio la ricerca case-sensitive della stringa: <%s>\n", argv[2]);
if ( bPartial )
BruteForceSearchPartial(argv[1], szSearch, 0, &myFindRec);
else
BruteForceSearch(argv[1], szSearch, 0, &myFindRec);
}
c_end = clock();

TempoImpiegato = (double)(c_end - c_start) / CLOCKS_PER_SEC;

printf("\nHo trovato %ld occorrenze della stringa \"%s\".\n", myFindRec.countFind, szSearch);
printf("Tempo impiegato -> %5.5f secondi\n\n", TempoImpiegato);

printf("I primi dieci risultati:\n");
for ( x = 0; x < myFindRec.countFind; x++ )
{
printf("Riga %ld\n", myFindRec.arrayRows[x]);
if ( x >= 9 )
break;
}

//verificaRighe(argv[1], &myFindRec);

free(myFindRec.arrayRows);

return 0;
}

VICIUS
27-01-2013, 13:37
C'è qualcosa che non va o in Lucene o nel mio. Sicuramente nel mio.

Com'è che le prime dieci righe non corrispondono visto che il file utilizzato è lo stesso(fileA.txt)?

Bisognerebbe scrivere un programmino che prenda in input il nome del file e il numero di riga e che stampi la riga selezionata.


EDIT: non corrisponde nemmeno il numero delle occorrenze.

Per il numero di occorrenze diverse ci possono essere tanti motivi. Accentate, articoli, punteggiatura strana, spazi mancanti, maiuscole, caratteri di controllo ecc.

Il messaggio che ho scritto è fuorviante. Quelli ritornati da lucene sono in effetti i primi 10 migliori risultati e non le prime 10 occorrenze. I risultati sono ordinati per rilevanza.

Vincenzo1968
27-01-2013, 14:07
Ho verificato la riga 969. Ne riporto solo una parte(ché è lunghissima):


e tu poi ti piglierai pensiero di farla trascrivere sopra un foglio di carta con buon carattere nel primo luogo dove siavi un maestro di scuola: o te la copier� in ogni caso un sagrestano; ma non farla trascrivere da alcun notaio, che costoro hanno


http://www.hwupgrade.org/public/style_emoticons/default/everything_went_better_than_expected.png

Vincenzo1968
27-01-2013, 14:09
Per il numero di occorrenze diverse ci possono essere tanti motivi. Accentate, articoli, punteggiatura strana, spazi mancanti, maiuscole, caratteri di controllo ecc.

Il messaggio che ho scritto è fuorviante. Quelli ritornati da lucene sono in effetti i primi 10 migliori risultati e non le prime 10 occorrenze. I risultati sono ordinati per rilevanza.

Ah ok! Allora sono entrambi corretti. :)

Puoi modificare il codice in modo da fargli ritornare i primi dieci risultati? Cosi lo confrontiamo coi nostri. Dopo non ti scasso più i cabasisi, giuro!

Vincenzo1968
27-01-2013, 14:26
Partial match:
http://img19.imageshack.us/img19/3774/c19b01mytempspartialmat.jpg

Exact match:
http://img39.imageshack.us/img39/9552/c19b01mytempsexactmatch.jpg

Vincenzo1968
27-01-2013, 15:24
prova.txt:

Riga 01: Dammi il tempo.
Riga 02: Sta per abbattersi un temporale.
Riga 03: Sta per abbattersi un temporale allucinante.
Riga 04: Il temporale è passato.
Riga 05: Vorrei trovare il tempo per fare tutto.
Riga 06: Questa è una soluzione temporanea.
Riga 07: Ciao ciao.
Riga 08: Adieu e cavoli vostri(cit.).


http://img819.imageshack.us/img819/1197/outputfilepiccolopartia.jpg

Vincenzo1968
27-01-2013, 15:33
Per il numero di occorrenze diverse ci possono essere tanti motivi. Accentate, articoli, punteggiatura strana, spazi mancanti, maiuscole, caratteri di controllo ecc.

Il messaggio che ho scritto è fuorviante. Quelli ritornati da lucene sono in effetti i primi 10 migliori risultati e non le prime 10 occorrenze. I risultati sono ordinati per rilevanza.

Comunque non ho capito la rilevanza. Rilevanza rispetto a che cosa? Perché quelle righe dovrebbero essere più rilevanti rispetto ad altre che contengono la stessa parola?

VICIUS
27-01-2013, 15:54
Rispetto agli altri documenti presenti nell'indice. Provo a fare un esempio.

Supponi di voler cercare tutti gli articoli in cui sono citati Berlusconi, Bersani e Monti. Nell'indice ci sono solo due documenti. Il primo è un ritaglio di giornale che parla della bocconi. È presente solo monti tra i tre e viene citato una sola volta. Nel secondo invece ci sono tutti e tre i politici e i nomi sono pure ripetuti più volte. Lucene li trova entrambi ma al primo viene assegnato un punteggio più alto rispetto al primo e quindi viene ritornato come primo.

Vincenzo1968
27-01-2013, 16:23
Abbastanza veloce anche su Windows 8:

file output.txt; dimensione 5 GiB; creato col programma di Repne:
http://img203.imageshack.us/img203/8697/c19b01mytempswindows.jpg

Veloce, dico, come brute force, senza utilizzo di un indice.

;)

Vincenzo1968
27-01-2013, 16:24
Rispetto agli altri documenti presenti nell'indice. Provo a fare un esempio.

Supponi di voler cercare tutti gli articoli in cui sono citati Beep!, Bersani e Monti. Nell'indice ci sono solo due documenti. Il primo è un ritaglio di giornale che parla della bocconi. È presente solo monti tra i tre e viene citato una sola volta. Nel secondo invece ci sono tutti e tre i politici e i nomi sono pure ripetuti più volte. Lucene li trova entrambi ma al primo viene assegnato un punteggio più alto rispetto al primo e quindi viene ritornato come primo.

A me viene da vomitare solo a sentirlo nominare il pedonano...

Vincenzo1968
27-01-2013, 16:37
Ho sistemato il codice, c'era un piccolo bug :D

http://img690.imageshack.us/img690/5762/c19b01mytempswindows2.jpg

;)

WarDuck
27-01-2013, 17:20
La ricerca brute-force non ha granché senso IMHO, specie perché se non erro una strstr implementa già Boyer-Moore...

Vincenzo1968
27-01-2013, 17:42
Gugo non si trova:

http://img46.imageshack.us/img46/687/c19b01gugo2.jpg

http://img838.imageshack.us/img838/6038/c19b01gugo.jpg

Vincenzo1968
27-01-2013, 17:44
La ricerca brute-force non ha granché senso IMHO, specie perché se non erro una strstr implementa già Boyer-Moore...

Non è mica la mia versione defitiniva. ;)

Lo so che non ha senso, soprattutto se confrontata con un qualunque algoritmo non brute-force o con indicizzazione come nei casi di Lucene, Indri e Zettair.

Vincenzo1968
27-01-2013, 18:03
C'è da dire che, se uno deve effettuare solo 4/5 ricerche nel file, conviene usare il mio brute-force. Lucene impiega un fottìo di tempo per creare l'indice(quattro minuti e venti per un indice su un file di 1 GiB).

Ma, ovviamente, una volta creato l'indice, ogni successiva ricerca è super-mega-ultra veloce.

Quindi, se le ricerche non si limitano a 4/5, meglio usare Lucene. Almeno per il momento, almeno fino a quando non implementeremo la nostra versione con indici... :D

Vincenzo1968
27-01-2013, 18:22
Che strumenti possiamo utilizzare per misurare a runtime l'utilizzo della quantità di memoria da parte di un programma in esecuzione?

Vincenzo1968
27-01-2013, 19:25
E c'è da dire anche che Lucene va bene nel caso di documenti statici, il cui contenuto non cambia mai nemmeno di una sola virgola.
Se cambia il contenuto del documento bisogna ricostruire l'indice. Per creare l'indice per un file di 5 GiB Lucene ci mette circa 23 minuti( leggasi: ventitre minuti). Col mio brute-force c'impiego circa 40 secondi per terminare la ricerca.

Ve lo immaginate, nei casi reali, con file di 65 GiB e passa, dover ricostruire ogni volta l'indice prima di poter effettuare una ricerca?
Follia pura. Meglio utilizzare brute force(se proprio non si hanno a disposizione altri algoritmi di ricerca).

;)

VICIUS
27-01-2013, 20:35
File da 65gb con un contenuto significativo non ne esistono. Parlo di libri, trascrizioni di trasmissioni, articoli, post, tweet. Anche prendendo opere sconfinate come la divina commedia non si arriva al megabyte. Non ho sotto mano il numero esatto ma la media di quasi 700 milioni di files si aggira sui 3 Kb. Anche se ltimamente si sta abbassando molto velocemente a causa dell'aumento di status update da facebook e twitter. È una statistica un po' falsata perché sarebbe meglio dividerli per tipologia ma rende bene l'idea.

Due cose sugli indici di lucene. Primo non è statico. Una volta indicizzati anche 20 tb di files se un singolo documento cambia non devi ripartire da capo. Basta aggiornare solo quello. A seconda delle esigenze ne esistono di vari tipi. Da quello persistente su disco, come quello che ho usato io, fino al indice specializzato per ricerche su singoli documenti che risiede completamente in ram. Ed ovviamente le prestazioni differiscono di diversi ordini di grandezza. Con un MemoryIndex si può arrivare tranquillamente a 300.000 query al secondo su un normale dual core.

Se parliamo invece di file creati automaticamente, magari dei log da analizzare per la creazione di statistiche e report, la situazione cambia. 65 GB sono pure pochi ma in quel caso lucene semplicemente non è lo strumento adatto. Per il data warehousing è meglio usare hadoop e company.

Vincenzo1968
27-01-2013, 21:29
File da 65gb con un contenuto significativo non ne esistono. Parlo di libri, trascrizioni di trasmissioni, articoli, post, tweet. Anche prendendo opere sconfinate come la divina commedia non si arriva al megabyte. Non ho sotto mano il numero esatto ma la media di quasi 700 milioni di files si aggira sui 3 Kb. Anche se ltimamente si sta abbassando molto velocemente a causa dell'aumento di status update da facebook e twitter. È una statistica un po' falsata perché sarebbe meglio dividerli per tipologia ma rende bene l'idea.

Due cose sugli indici di lucene. Primo non è statico. Una volta indicizzati anche 20 tb di files se un singolo documento cambia non devi ripartire da capo. Basta aggiornare solo quello. A seconda delle esigenze ne esistono di vari tipi. Da quello persistente su disco, come quello che ho usato io, fino al indice specializzato per ricerche su singoli documenti che risiede completamente in ram. Ed ovviamente le prestazioni differiscono di diversi ordini di grandezza. Con un MemoryIndex si può arrivare tranquillamente a 300.000 query al secondo su un normale dual core.

Se parliamo invece di file creati automaticamente, magari dei log da analizzare per la creazione di statistiche e report, la situazione cambia. 65 GB sono pure pochi ma in quel caso lucene semplicemente non è lo strumento adatto. Per il data warehousing è meglio usare hadoop e company.

Che mi venga un colpo!

Ma se nel thread che ha dato vita a questo contest era intervenuto un utente(purtroppo non ricordo il nickname) confermando che al lavoro(azienda editoriale) loro utilizzano file di testo di 65 GiB.

Io avevo ipotizzato dimensioni di 1 GiB nel mondo reale. Poi Cesare aveva sollevato dubbi e fortunatamente(per me) l'utente in questione ha confermato i 65 GiB e passa.

Alla fine le prove le faremo su file da 65 GiB come da mondo reale. ;)

Ah ok, pensavo che modificando il file bisognasse ricostruire interamente l'indice. Allora ok.

:D

EDIT: avevo letto frettolosamente(e, dunque, male):
se un singolo documento cambia non devi ripartire da capo. Basta aggiornare solo quello
Ah! allora è come pensavo io. Su singoli file bisogna ricostruire l'indice. E qui di singoli file da 65 GiB ci occupiamo(come da mondo reale). ;)

VICIUS
27-01-2013, 21:58
Ti ripeto che non esistono. Singoli documenti di quelle dimensioni non hanno ragione di esistere. Potrebbe trattarsi di un archivio con milioni di file ma in quel caso indicizzarli come un singolo elemento non avrebbe senso. Oppure semplicemente non venivano usati per fare ricerche.

Vincenzo1968
27-01-2013, 22:08
http://img694.imageshack.us/img694/1294/strstr.jpg


void findStrStr(const char *szFileName, FindRec *myFindRec, char *szSearch)
{
long row = 1;
FILE *fp = NULL;
int k = 0;
int x = 0;
unsigned char *str = NULL;

fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s. Addio!\n", szFileName);
return;
}

str = (unsigned char*)malloc(16384);
if ( !str )
{
printf("\nImpossibile allocare la memoria. Addio!\n");
fclose(fp);
return;
}

myFindRec->countFind = 0;
while (fgets((char*)str, 16384, fp) != NULL)
{
if ( strstr((char*)str, szSearch) != NULL )
{

if ( myFindRec->countFind < 10 )
{
myFindRec->arrayRows[myFindRec->countFind] = row;
//printf("Trovato alla riga %lld colonna %lld\n", row, column - 1);
}
myFindRec->countFind++;
}
row++;
}

fclose(fp);
free(str);
}

Vincenzo1968
27-01-2013, 22:32
Ti ripeto che non esistono. Singoli documenti di quelle dimensioni non hanno ragione di esistere. Potrebbe trattarsi di un archivio con milioni di file ma in quel caso indicizzarli come un singolo elemento non avrebbe senso. Oppure semplicemente non venivano usati per fare ricerche.

Ni.

Ricordavo male: 15 GiB e non 65:

http://www.hwupgrade.it/forum/showthread.php?p=38835181#post38835181
Qua ne utilizziamo un po', come datafile, il più grosso se non erro si aggira sui 15GB. È un sistema attualmente in via di dismissione. :)


EDIT: Ecco perché ricordavo male:
http://www.hwupgrade.it/forum/newreply.php?do=newreply&p=38835846
Lucene spacca c'è poco da fare. Qui a lavoro abbiamo un indice con tutti gli articoli pubblicati negli ultimi anni dai maggiori quotidiani italiani (circa 900 pubblicazioni). 65 GB con circa 120 milioni di articoli. Mai un problema e ricerche che finiscono sempre in pochi decimi di secondo. Se penso che gira su un clusterino minuscolo con 4 processori e 4 gb di ram. :O

VICIUS
28-01-2013, 05:28
Conferma esattamente quello che ti ho detto. Leggiti con molta attenzione il suo messaggio successivo. Quello che pesa 15 GB è il dump del database. Non sta parlando di un singolo documento di testo ma di un insieme.

Vincenzo1968
28-01-2013, 10:45
Cesare solleva il dubbio:

"Mi pare difficile pensare che elaborino testi di GB di dimensione. Ho un mio amico che fa il sistemista per "La Sicilia", e posso chiedere a lui."

GByTe87 risponde:
"Qua ne utilizziamo un po', come datafile, il più grosso se non erro si aggira sui 15GB. È un sistema attualmente in via di dismissione."

"il più grosso" è uno o no?

Mo mi rileggo(con molta attenzione) il messaggio successivo.

EDIT:

L'esigenza è quella di avere una "staticizzazione" dei dati contenuti su un db.

Un applicativo li estrae dal db, li elabora e li staticizza su file di testo. Un altro applicativo, successivamente, li legge e li trasforma in file "binari" contenenti strutture C, che verranno poi letti dall'applicativo finale (un motore di ricerca custom, scritto in C). Il tutto avviene a frequenza giornaliera.
Però, come dicevo, si tratta di un'architettura pensata ormai dieci anni fa, e che negli ultimi periodi ha dimostrata tutta la sua inadeguatezza, ed è in corso di sostituzione.
(For the lulz, verrà sostituita da Solr + wrapper Python :asd:).

È il dump del database. E allora possiamo utilizzare, per il contest, una cartella contenente una cinquantina di file di testo da 1 GiB ciascuno.

In ogni caso, se i documenti non sono statici e se debbo effettuare una o poche volte(4/5) la ricerca sul file, non conviene utilizzare Lucene. Ci vogliono quattro minuti per creare l'indice su un file da 1 GiB. E anche se i file sono più piccoli la ricerca brute-force impiega molto meno tempo rispetto alla creazione dell'indice.

Vincenzo1968
28-01-2013, 11:24
File da 5 GiB:

http://img521.imageshack.us/img521/1940/c19b01tempistrstr.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png



void findStrStr(const char *szFileName, FindRec *myFindRec, char *szSearch)
{
long row = 1;
FILE *fp = NULL;
int k = 0;
int x = 0;
unsigned char *str = NULL;

fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file %s. Addio!\n", szFileName);
return;
}

str = (unsigned char*)malloc(16384);
if ( !str )
{
printf("\nImpossibile allocare la memoria. Addio!\n");
fclose(fp);
return;
}

myFindRec->countFind = 0;
while (fgets((char*)str, 16384, fp) != NULL)
{
if ( strstr((char*)str, szSearch) != NULL )
{

if ( myFindRec->countFind < 10 )
{
myFindRec->arrayRows[myFindRec->countFind] = row;
//printf("Trovato alla riga %lld colonna %lld\n", row, column - 1);
}
myFindRec->countFind++;
}
row++;
}

fclose(fp);
free(str);
}

int main(int argc, char* argv[])
{
FindRec myFindRec;
char szExeName[256];
unsigned char szSearch[256];
clock_t c_start, c_end;
double TempoImpiegato;
int x;
int bPartial = 0;

if ( argc < 3 )
{

#ifdef __linux__
PrintHelp(argv[0]);
#else
ExtractFileName(argv[0], szExeName);
PrintHelp(szExeName);
#endif

printf("\nPremere INVIO per terminare.");
getc(stdin);

return -1;
}

strcpy((char*)szSearch, argv[2]);

//printf("\nargc = %d\n", argc);
//printf("\nargv[%d] = %s\n", argc-1, argv[argc-1]);

myFindRec.arrayRows = (long *)malloc(sizeof(long) * 10);
if ( !myFindRec.arrayRows )
{
printf("Memoria insufficiente.\n");
return;
}


if ( argc >= 5 )
{
if ( strcmp(argv[4], "--partial") == 0 )
bPartial = 1;
else
bPartial = 0;
}

/*
if ( bPartial )
printf("\nRicerca partial della stringa: <%s>\n", argv[2]);
else
printf("\nRicerca non partial della stringa: <%s>\n", argv[2]);
*/

//BruteForceSearchPartial(argv[1], argv[2], 1);

c_start = clock();
//MakeIndex(argv[1], &myFindRec);
findStrStr(argv[1], &myFindRec, (char*)szSearch);
c_end = clock();
TempoImpiegato = (double)(c_end - c_start) / CLOCKS_PER_SEC;
//printf("Totale righe: %ld\n", myFindRec.countRows);
//printf("La riga piu' lunga e' lunga %ld byte.\n", myFindRec.maxRowLenght);
printf("\nHo trovato %ld occorrenze della stringa \"%s\".\n", myFindRec.countFind, szSearch);
printf("Tempo impiegato con fgets e strstr -> %5.5f secondi\n\n", TempoImpiegato);
printf("I primi dieci risultati:\n");
for ( x = 0; x < myFindRec.countFind; x++ )
{
printf("Riga %ld\n", myFindRec.arrayRows[x]);
if ( x >= 9 )
break;
}




c_start = clock();
if ( (argc >= 4) && (strcmp(argv[3], "--case-insensitive") == 0) )
{
//printf("\nInizio la ricerca case-insensitive della stringa: <%s>\n", argv[2]);
if ( bPartial )
BruteForceSearchPartial(argv[1], szSearch, 1, &myFindRec);
else
BruteForceSearch(argv[1], szSearch, 1, &myFindRec);

}
else
{
//printf("\nInizio la ricerca case-sensitive della stringa: <%s>\n", argv[2]);
if ( bPartial )
BruteForceSearchPartial(argv[1], szSearch, 0, &myFindRec);
else
BruteForceSearch(argv[1], szSearch, 0, &myFindRec);
}
c_end = clock();

TempoImpiegato = (double)(c_end - c_start) / CLOCKS_PER_SEC;

printf("\nHo trovato %ld occorrenze della stringa \"%s\".\n", myFindRec.countFind, szSearch);
printf("Tempo impiegato -> %5.5f secondi\n\n", TempoImpiegato);

printf("I primi dieci risultati:\n");
for ( x = 0; x < myFindRec.countFind; x++ )
{
printf("Riga %ld\n", myFindRec.arrayRows[x]);
if ( x >= 9 )
break;
}

free(myFindRec.arrayRows);

return 0;
}

cdimauro
28-01-2013, 11:37
I dump dei database possono occupare anche TB di spazio, ma quel che conta sono i dati che ci sono dentro, e come vengono utilizzati.

Esempio: ho un dump dell'intero database di questo forum, fermo a circa 3 anni fa. Occupa circa 32GB, ma in mezzo ci sono informazioni sui sottoforum, thread, utenti, e ovviamente anche i messaggi, che difficilmente superano i 64KB (alcuni miei sì, ma siamo là vicino).

Per cui condivido la valutazione di Vicius, e a mio avviso è inutile andare oltre file di 1MB di puro testo, se l'obiettivo è di lavorare a uno scenario quanto più realistico possibile.

Vincenzo1968
28-01-2013, 11:53
Benissimo, allora creeremo una cartella con un fottìo di file della dimensione massima di 1 MB(per un totale di 50 GiB).

Vicius dixit: "65 GB con circa 120 milioni di articoli"

Rimane il fatto che se i file non sono statici e le ricerche da effettuare su ogni file sono poche, il mio brute-force impiega molto meno tempo rispetto alla creazione dell'indice.

Vincenzo1968
28-01-2013, 11:57
Per il momento comunque, per semplificare le cose, rimaniamo con un file da 5 GiB.

Alla fine(punto B.?) applicheremo gli algoritmi al fottìo di file.

;)

Vincenzo1968
28-01-2013, 12:02
Eh ma c'è, in Lucene, la possibilità di indicargli la cartella? O mi debbo creare l'indice per ogni singolo file?

http://www.hwupgrade.org/public/style_emoticons/default/rage.png

Vincenzo1968
28-01-2013, 12:09
Ragazzi, per un esempio di file non statici, pensate a un'azienda che debba elaborare giornalmente i dati di borsa(di tutte le borse del mondo).

L'azienda riceve, ogni giorno, via rete, un fottiò di file con i dati(prezzo di apertura, chiusura, massimo, minimo) dei vari titoli quotati.

Con i dati ricevuti viene aggiornato lo "storico" di ogni singolo titolo.

Etc, etc.

Vincenzo1968
28-01-2013, 12:42
Vi anticipo già che nel contest 20 ci occuperemo dell'elaborazione dei dati di borsa.
In questo contest limitiamoci a file di testo con contenuto statico.

;)

Vincenzo1968
28-01-2013, 14:28
Preelaborazione indice in soli 10 secondi nel file da 1 GiB:

http://img132.imageshack.us/img132/7397/indexpre.jpg

http://img651.imageshack.us/img651/8175/faccine.jpg

Vincenzo1968
28-01-2013, 14:37
In realtà la parola più lunga è lunga 27 byte.
Avevo fatto un errore:


myFindRec->maxWordLenght = maxWordLenght + 1;


Codice corretto:

myFindRec->maxWordLenght = maxWordLenght;


http://img46.imageshack.us/img46/7315/temporeal.jpg

File da 5 GiB:

http://img594.imageshack.us/img594/4890/count5gib.jpg

Vincenzo1968
28-01-2013, 14:49
A questo punto che cosa mi conviene utilizzare? B+Tree? Indice invertito? Hash(hash su file ovviamente)?

Mo li provo tutti. Lucene ha le ore contate(forse)...

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

Vincenzo1968
28-01-2013, 15:19
È arrivato il momento di consultare la Bibbia(bibbia, dico, dell'Informatica):

http://www-cs-faculty.stanford.edu/~uno/don.gif

http://www-cs-faculty.stanford.edu/~uno/

http://www-cs-faculty.stanford.edu/~uno/taocp.html

http://it.wikipedia.org/wiki/Donald_Knuth

http://en.wikipedia.org/wiki/The_Art_of_Computer_Programming

:D


Umorismo informatico

Knuth è un famoso programmatore conosciuto per il suo umorismo informatico:

Paga un premio di 2,56 dollari per ogni errore scoperto nei suoi libri, perché "256 penny sono un dollaro esadecimale". (La sua generosità per gli errori di stampa nel libro 3:16 Bible Texts Illuminated, è stata di 3,16 dollari). Nella maggioranza dei casi gli assegni non vengono riscossi, ma tenuti come 'trofei' simbolici.
I numeri di versione del suo software TEX si avvicinano al numero pi greco; dopo la versione 3, i valori man mano assegnati sono stati 3.1, 3.14, 3.141 e così via. I numeri di versione di Metafont si avvicinano al numero e in maniera simile al precedente. Ha pubblicamente affermato che alla sua morte tutti gli eventuali bug ancora presenti saranno promossi a funzionalità, e che le versioni saranno cristallizzate a π ed e.
Una volta avvisò gli utenti del suo software, "Badate ai bug nel codice suddetto; io ho solo dimostrato che è corretto, non l'ho provato." [2]

In aggiunta ai suoi scritti di informatica, Knuth è anche l'autore di 3:16 Bible Texts Illuminated (1991), ISBN 0-89579-252-4, nel quale cerca di esaminare la Bibbia tramite un processo di "campionamento casuale stratificato", vale a dire un'analisi del capitolo terzo, versetto sedicesimo di ogni libro. Ogni verso è accompagnato da un'interpretazione calligrafica: l'analisi è fornita da un gruppo di calligrafici capeggiati da Hermann Zapf.

Knuth pubblicò il suo primo articolo "scientifico" su un periodico scolastico nel 1957 con il titolo "Potrzebie Sistemi di peso e misura". In esso, definì le unità fondamentali di lunghezza con lo spessore della rivista MAD magazine numero 26, e chiamò la fondamentale unità di misura della forza "whatmeworry" ("chemmimporta", l'intercalare tipico di MAD). La rivista MAD magazine acquistò l'articolo e lo pubblicò nel numero di giugno del 1957.

Vincenzo1968
28-01-2013, 16:29
Comunque, per non sapere né leggere né scrivere, ho ordinato questo libro:

http://www.manning.com/hatcher2/

http://www.manning.com/hatcher2/hatcher2_cover150.jpg

;)

EDIT: il tipo coi baffoni in copertina ritrae Vicius?

cdimauro
28-01-2013, 16:38
Benissimo, allora creeremo una cartella con un fottìo di file della dimensione massima di 1 MB(per un totale di 50 GiB).

Vicius dixit: "65 GB con circa 120 milioni di articoli"

Rimane il fatto che se i file non sono statici e le ricerche da effettuare su ogni file sono poche, il mio brute-force impiega molto meno tempo rispetto alla creazione dell'indice.
Francamente io terrei un file unico con tutti i dati. In questo modo non devi ogni volta aprire e chiudere file in continuazione, ma mantenere aperto un solo file, col server che provvederà poi a eseguire soltanto seek & read dov'è necessario.

In questo modo potrai anche centralizzare e gestire nella maniera migliore gli aggiornamenti dei dati, magari usando il concetto di transazione, in modo tale che l'aggiornamento di dati E indici sia un'operazione atomica (immagina cosa succederebbe altrimenti se un venisse aggiornato un file e non un indice, e in quel momento arrivasse una richiesta).
Ragazzi, per un esempio di file non statici, pensate a un'azienda che debba elaborare giornalmente i dati di borsa(di tutte le borse del mondo).

L'azienda riceve, ogni giorno, via rete, un fottiò di file con i dati(prezzo di apertura, chiusura, massimo, minimo) dei vari titoli quotati.

Con i dati ricevuti viene aggiornato lo "storico" di ogni singolo titolo.

Etc, etc.
Penso sia una problematica comune per un database, a parte il fatto che il prezzo di apertura, chiusura, minimo e massimo vengono calcolati in tempo reale con le classifiche funzione di aggregazione.

E ovviamente gli indici che vengono continuamente aggiornati in base ai nuovi dati.

Vincenzo1968
28-01-2013, 17:05
Penso sia una problematica comune per un database, a parte il fatto che il prezzo di apertura, chiusura, minimo e massimo vengono calcolati in tempo reale con le classifiche funzione di aggregazione.

E ovviamente gli indici che vengono continuamente aggiornati in base ai nuovi dati.

Si ma io intendevo dire di un'azienda che avesse bisogno di avere lo storico dal 1945 ad oggi di ogni titolo quotato.
Per ricavarne dei pattern dei movimenti dei prezzi.

Data mining: argomento del prossimo contest. ;)

cdimauro
28-01-2013, 17:18
Lo trovo difficile, perché dal 1945 a oggi la società e le esigenze dell'umanità, e di conseguenza gli obiettivi delle aziende, sono cambiati abbastanza.

Comunque lo scenario che prospetti dovrebbe essere gestibile senza difficoltà da un database, ma credo che gugoXX possa essere molto più preciso, perché dovrebbe lavorare in quell'ambito, se non ricordo male.

Vincenzo1968
28-01-2013, 17:27
Eh ma noi dai dati estratti dalle serie storiche faremo delle previsioni dei movimenti dei prezzi a una settimana, un mese e un anno.

Vincerà chi riuscirà a incrementare di più(in %) il proprio portafoglio virtuale.

;)

VICIUS
28-01-2013, 18:41
Comunque, per non sapere né leggere né scrivere, ho ordinato questo libro:

http://www.manning.com/hatcher2/

http://www.manning.com/hatcher2/hatcher2_cover150.jpg

;)

EDIT: il tipo coi baffoni in copertina ritrae Vicius?
No non sono io :asd:

Comunque spero che tu abbia avuto l'accortezza di prendere almeno la seconda edizione. Quella linkata è un po' datata.

Vincenzo1968
28-01-2013, 19:47
Si si questa:

http://www.manning.com/hatcher3/

http://www.manning.com/hatcher3/hatcher3_cover150.jpg

:D

Siamo sicuri che non sia tu quello in copertina?

Vincenzo1968
29-01-2013, 12:47
Ci siamo. Lucene ha i minuti contati...

Ma gli altri partecipanti? Repne, AnonimoVeneziano, Tommo, Marcor?

Oh se non interessa a nessuno ditelo che evito di uppare il thread. Domani(o dopodomani) do il mio codice(e gli eseguibili) a Vicius via pm e buonanotte.

;)

Tommo
29-01-2013, 12:50
Io sono stato a una game jam, ho codato come un pazzo per 3 giorni e ora sono indietro col lavoro... non posso che passare :D

Vincenzo1968
29-01-2013, 13:17
Il mio programma crea l'indice molto più velocemente rispetto a Lucene.
Come tempi per la ricerca, una volta creato l'indice, Lucene e il mio si equivalgono(il mio è leggermente più veloce :D ).

Ho utilizzato una versione personalizzata(molto personalizzata) del cosiddetto "indice invertito"(invertito non pervertito): Inverted Index.

Sto implementando le varie funzionalità che Lucene implementa: wildcard character, espressioni regolari, etc.
Inoltre voglio dotarlo di interfaccia utente grafica. Utilizzerò le librerie QT.

Quando sarà pronto(una settimana? un mese?) lo metterò online; aprirò un sito dedicato. Ovviamente freeware e open source.

Poi vi faccio sapere il link.

;)

Vincenzo1968
29-01-2013, 16:27
File da 65gb con un contenuto significativo non ne esistono. Parlo di libri, trascrizioni di trasmissioni, articoli, post, tweet. Anche prendendo opere sconfinate come la divina commedia non si arriva al megabyte. Non ho sotto mano il numero esatto ma la media di quasi 700 milioni di files si aggira sui 3 Kb. Anche se ltimamente si sta abbassando molto velocemente a causa dell'aumento di status update da facebook e twitter. È una statistica un po' falsata perché sarebbe meglio dividerli per tipologia ma rende bene l'idea.

Due cose sugli indici di lucene. Primo non è statico. Una volta indicizzati anche 20 tb di files se un singolo documento cambia non devi ripartire da capo. Basta aggiornare solo quello. A seconda delle esigenze ne esistono di vari tipi. Da quello persistente su disco, come quello che ho usato io, fino al indice specializzato per ricerche su singoli documenti che risiede completamente in ram. Ed ovviamente le prestazioni differiscono di diversi ordini di grandezza. Con un MemoryIndex si può arrivare tranquillamente a 300.000 query al secondo su un normale dual core.

Se parliamo invece di file creati automaticamente, magari dei log da analizzare per la creazione di statistiche e report, la situazione cambia. 65 GB sono pure pochi ma in quel caso lucene semplicemente non è lo strumento adatto. Per il data warehousing è meglio usare hadoop e company.


Benissimo, allora creeremo una cartella con un fottìo di file della dimensione massima di 1 MB(per un totale di 50 GiB).

Vicius dixit: "65 GB con circa 120 milioni di articoli"

Rimane il fatto che se i file non sono statici e le ricerche da effettuare su ogni file sono poche, il mio brute-force impiega molto meno tempo rispetto alla creazione dell'indice.


Porca mignotta, vero è!

Per file piccoli(1-2 MB) posso mantenere l'indice completamente in memoria. E allora Lucene è definitivamente spacciato...

:D

Vincenzo1968
29-01-2013, 16:37
E comunque voglio provare a ridurre i tempi di esecuzione della versione brute-force utilizzando un automa a stati finiti(di tipo deterministico però eh! mica di tipo non deterministico :mbe: )

Vediamo se si riducono i tempi...

Vincenzo1968
29-01-2013, 16:55
Per i file grossi, invece, stavo pensando di creare un indice che sia una via di mezzo fra i B+Tree e gli Inverted Index. Con i B+Tree riduco all'osso l'accesso al disco. E allora tanti saluti Lucene...

VICIUS
29-01-2013, 16:58
Il mio programma crea l'indice molto più velocemente rispetto a Lucene.
Come tempi per la ricerca, una volta creato l'indice, Lucene e il mio si equivalgono(il mio è leggermente più veloce :D ).
Probabilmente è molto lento perché leggo una riga alla volta dal file e poi la indicizzo come documento separato. È un po' una porcata ma è il modo più veloce che ho trovato per stampare il numero di "riga" in cui era stato fatto match.

Vincenzo1968
29-01-2013, 17:25
Probabilmente è molto lento perché leggo una riga alla volta dal file e poi la indicizzo come documento separato. È un po' una porcata ma è il modo più veloce che ho trovato per stampare il numero di "riga" in cui era stato fatto match.

ahhh quindi non è Lucene... La colpa è di chi sta tra Lucene e la sedia(semi cit.)...

http://www.hwupgrade.org/public/style_emoticons/default/patpat.gif


Scheeeerzoooo!!! :D

Appena m'arriva il libro allora vediamo come fare dei Benchmark(così si scrive? :mbe: ) migliori.

;)

Vincenzo1968
29-01-2013, 18:16
In ogni caso sono convinto che la mia applicazione risulterà molto più veloce nella creazione dell'indice rispetto a Lucene.
E anche nelle ricerche(non di molto, ma più veloce) con l'applicazione del B+Tree-Inverted-Index.

Dove sono adesso quelli che "non serve studiare come funzionano i DBMS."...

:D

VICIUS
29-01-2013, 18:19
ahhh quindi non è Lucene... La colpa è di chi sta tra Lucene e la sedia(semi cit.)...

http://www.hwupgrade.org/public/style_emoticons/default/patpat.gif

Sicuramente colpa di chi lo ha scritto. Se smettesse di pensare ai programmi mentre è in fila al banco dei salumi forse gli uscirebbero meglio. :O

Vincenzo1968
29-01-2013, 18:30
Raga' la versione con automa a stati finiti di tipo deterministico risulta più veloce rispetto alla brute-force semplice. E, naturalmente, risulta molto più veloce rispetto all'uso di fgets/strstr.

Dove sono adesso quelli che "non serve studiare la teoria dei linguaggi formali. Non serve studiare le tecniche di parsing e lexing"...

Dove sono?

:D

Vincenzo1968
29-01-2013, 18:31
Sicuramente colpa di chi lo ha scritto. Se smettesse di pensare ai programmi mentre è in fila al banco dei salumi forse gli uscirebbero meglio. :O

Chi è codesto tizio? E ha i baffoni come i tuoi?

Vincenzo1968
29-01-2013, 19:09
E poi: non c'è modo di avviare Lucene come programma autonomo(come Zettair)?

Bisogna utilizzarlo per forza via codice(e, per soprammercato, in Java)?

Java :rolleyes:
Lucene :rolleyes:
Java e Lucene :rolleyes:
Lucene e Java :rolleyes:

:D

Vincenzo1968
29-01-2013, 19:27
Probabilmente è molto lento perché leggo una riga alla volta dal file e poi la indicizzo come documento separato. È un po' una porcata ma è il modo più veloce che ho trovato per stampare il numero di "riga" in cui era stato fatto match.

Mi sorge un dubbio atroce: non è che Lucene indicizza il documento e non l'esatta posizione(riga, colonna) di ogni parola?

No perché se così fosse la mia versione con automa a stati finiti sarebbe di gran lunga superiore... E figuriamoci la versione B+Tree-Inverted-Index.

Com'è il fatto? :mbe:

Vincenzo1968
29-01-2013, 19:43
E ancora: dove diavolo è il file indice creato da Lucene? Zettair crea quattro file indice nella stessa cartella dell'eseguibile. E Lucene? :mbe:

E, poi, ancora: 'mbé? E il piacere, almeno per una volta, di vedere una versione con un linguaggio ad altissimo livello? Ruby, Python, Python + PyPy, Python + Cython, Python + PyPy + Cython? :mbe: Nessuno vuol cimentarsi?

'mbé?

Tommo
29-01-2013, 20:07
Penso che di fronte a progetti mastodontici e senza un chiaro fine mascherati da "contest" la gente si tiri indietro :D
Se posso, un contest è bello quando è un piccolo problema circoscritto da risolvere in poche ore come gioco...
se devo buttare tempo a reimplementare una soluzione standard di mercato preferisco fare qualcosa di produttivo, visto che lo sforzo è lo stesso :D

Vincenzo1968
29-01-2013, 20:26
Penso che di fronte a progetti mastodontici e senza un chiaro fine mascherati da "contest" la gente si tiri indietro :D
Se posso, un contest è bello quando è un piccolo problema circoscritto da risolvere in poche ore come gioco...
se devo buttare tempo a reimplementare una soluzione standard di mercato preferisco fare qualcosa di produttivo, visto che lo sforzo è lo stesso :D

Macché mascherare, macché progetto mastodontico. Sono due righe di codice(in C; e figuriamoci in python o ruby).

Non lo dico in tono polemico. Davvero mi piacerebbe vedere una soluzione in Ruby o Python.
Per il prìo di vederla. ;)

Vincenzo1968
29-01-2013, 20:51
Tratto da Una storia semplice di Leonardo sciascia:

"Il quadro" scappò di dire al brigadiere.
Il commissario lo fulminò di un'occhiata:
"Ti ringrazio, ma ci sarei arrivato senza
il tuo aiuto"
"Ma per carità", disse il brigadiere "non
mi permetterei...". E con ingenuità, confuso,
balbettante, aggiunse: "Lei è laureato".
La battuta, suonando ironica al commissario,
lo fece del tutto inferocire: ma contro
l'uomo della Volvo.
"Mi dispiace ma debbo trattenerla qui.
Abbiamo da fare tanti accertamenti".
...
La laurea in legge era la suprema ambizione
della sua vita, il suo sogno: da candore
dunque quella battuta che al commissario
parve maligna. Ne era ancora risentito,
quando il brigadiere tornò dall'avere
accompagnato in camera di sicurezza l'uomo
della Volvo, le cui urla di protesta
risuonavano ora in tutta la questura.
"Sono laureato eh?... Io non ho ancora
capito se sei davvero uno sprovveduto o
se fingi di esserlo... Laureato! In un
paese dove ormai sono laureati gli uscieri,
i camerieri e persino gli spazzini".
"Mi scusi" - disse sinceramente ma scontro-
samente il brigadiere.


Anch'io, come nel caso del brigadiere di sciasciana memoria, ho scritto candidamente di Python e Ruby: davvero avrei il piacere di vederli in action.

Al limite possiamo pure evitare di prendere i tempi. Ma vediamoli in action, per una buona volta, 'sti benedetti linguaggi ad altissimo livello.

;)

VICIUS
29-01-2013, 20:52
E poi: non c'è modo di avviare Lucene come programma autonomo(come Zettair)?

Bisogna utilizzarlo per forza via codice(e, per soprammercato, in Java)?

Java :rolleyes:
Lucene :rolleyes:
Java e Lucene :rolleyes:
Lucene e Java :rolleyes:

:D

Lanciare una libreria? Hai le idee un po' confuse. :asd:

Mi sorge un dubbio atroce: non è che Lucene indicizza il documento e non l'esatta posizione(riga, colonna) di ogni parola?

No perché se così fosse la mia versione con automa a stati finiti sarebbe di gran lunga superiore... E figuriamoci la versione B+Tree-Inverted-Index.

Com'è il fatto? :mbe:

Perché mai dovrebbe salvare riga e colonna di ogni singola parola? Tutto quello che gli serve per fare il suo lavoro è la posizione all'interno del documento.

Comunque credo di capire come mai hai tutti questi dubbi. Stai confondendo lucene con programmi come grep. Non serve a trovare tutte le occorrenze di un certa parola dentro ad un singolo documento ma tutti i documenti che contengono quella parola.

Vincenzo1968
29-01-2013, 21:04
Lanciare una libreria? Hai le idee un po' confuse. :asd:



Perché mai dovrebbe salvare riga e colonna di ogni singola parola? Tutto quello che gli serve per fare il suo lavoro è la posizione all'interno del documento.

Comunque credo di capire come mai hai tutti questi dubbi. Stai confondendo lucene con programmi come grep. Non serve a trovare tutte le occorrenze di un certa parola dentro ad un singolo documento ma tutti i documenti che contengono quella parola.

E quindi se ho un documento di 1 MB e devo cercare una stringa, Lucene mi dice che la stringa è presente. Poi me la debbo cercare da me la posizione esatta. Giusto?

O sennò debbo fare come hai fatto tu perdendo un fottìo di tempo nella creazione dell'indice. Dico bene?

Non ho le idee confuse. Dico, altri software simili forniscono la libreria da utilizzare via codice ma anche un eseguibile autonomo per effettuare le ricerche. Chi programma in linguaggi diversi da Java che deve fare? E chi non programma proprio che deve fare? Assumere un programmatore? Affidare la commessa a una software house?

Vincenzo1968
29-01-2013, 21:50
Comunque mi pare strana 'sta cosa che Lucene non restituisca la posizione esatta all'interno del documento. Aspetta che mi scarico i sorgenti del libro che ho ordinato e vedo un po'.

Aspetta, aspetta...

Vincenzo1968
30-01-2013, 00:08
Ho buttato giù qualcosa con lucene. Non fa esattamente quello che chiedono i vari punti ma abbiate pazienza. È un po' che non lo uso e non ho voglia di aprire i docs. :stordita:

Binari (http://cl.ly/MRsS), Sorgenti (http://cl.ly/MQaL)
E un piccolo screenshot che lo mostra in azione. Prego notare l'evidenziazione direttamente nella shell :sofico:

http://f.cl.ly/items/2m2A1z2u0u1m1Z143n0Y/lucene-search.png

Pure questo post è fuorviante. Sembra quasi che sia Lucene a evidenziare le parole con un colore diverso(e quindi sembra che rilevi l'esatta posizione, riga e colonna, delle stringhe trovate).

Invece sei tu che l'hai fatto con apposito codice Java successivo alla ricerca. O no?

E comunque il punto B.1 parlava(e parla) chiaro:


B.1:
Si realizzi un programmino che, data in input una stringa di ricerca, indichi l'esatta posizione (riga e colonna) nel file creato al punto A.

Si prendano separatamente i tempi per la creazione dell'indice e quelli per la ricerca.

Se volete utilizzare un algoritmo brute force, senza creare l'indice, siete liberi di farlo.


Potevi dirlo subito: "guardate che con Lucene non si può fare ciò che richiede il punto B.1".
E io ti avrei risposto: "Benissimo, allora ci confronteremo con Lucene nel punto B.2".

Pregasi notare: "si realizzi un programmino" non "si realizzi un progetto mastodontico".

;)

Vincenzo1968
30-01-2013, 00:20
Penso che di fronte a progetti mastodontici e senza un chiaro fine mascherati da "contest" la gente si tiri indietro :D
Se posso, un contest è bello quando è un piccolo problema circoscritto da risolvere in poche ore come gioco...
se devo buttare tempo a reimplementare una soluzione standard di mercato preferisco fare qualcosa di produttivo, visto che lo sforzo è lo stesso :D

Non riuscivo ad addormentarmi; mi frullava nella testa quel "mascherati".

Non capisco cosa ci sia da mascherare. Cosa dovrei mascherare e per quale minchia di motivo?
Se per caso ti riferisci al fatto che voglio implementare le caratteristiche avanzate di programmi come Lucene, ebbene, non ho mica detto che dobbiamo farlo tutti quanti. Quella è una cosa che voglio fare io. Qui si tratta di scrivere un programmino di poche righe per la ricerca su file di testo.

Programma mastodontico senza un chiaro fine e, per soprammercato, mascherato da contest. :rolleyes:

Mastodontico! :rotfl:

Se non vuoi buttare tempo evita di scrivere minchiate per favore. Vai a fare qualcosa di produttivo che è meglio per tutti. ;)

Tommo
30-01-2013, 02:16
Il mascherato non implicava assolutamente un doppio fine da parte tua, tranquillo, ma solo un mero essere definito come qualcosa che non è :read:

Molto semplicemente, secondo me lo "scope" è troppo ampio e troppo poco definito per essere un contest interessante, tant'è che è anche abbastanza difficile confrontare le prestazioni relative dei vari programmi (a parte il punto 1).
Comunque è ovviamente imo, non serve che ci perdi il sonno :asd:

VICIUS
30-01-2013, 06:29
E quindi se ho un documento di 1 MB e devo cercare una stringa, Lucene mi dice che la stringa è presente. Poi me la debbo cercare da me la posizione esatta. Giusto?

O sennò debbo fare come hai fatto tu perdendo un fottìo di tempo nella creazione dell'indice. Dico bene?
Giusto.

Non ho le idee confuse. Dico, altri software simili forniscono la libreria da utilizzare via codice ma anche un eseguibile autonomo per effettuare le ricerche. Chi programma in linguaggi diversi da Java che deve fare? E chi non programma proprio che deve fare? Assumere un programmatore? Affidare la commessa a una software house?
Mi spieghi che senso ha fornire un frontend che fa un milionesimo di quello che permette la libreria? Poi ti lega ad un certo formato di indice con certi campi ed al tipo di query che hanno scelto altri. Se voglio tenere l'indice in memoria che faccio? E se i documenti che voglio indicizzare sono diverse? Se voglio cambiare il comportamento delle query?

Di più alto livello c'è solr che permette di configurare le cose via xml e ci mette sopra un'interfaccia web. Via http poi lo usi da dove ti pare. Persino da shell.

Comunque mi pare strana 'sta cosa che Lucene non restituisca la posizione esatta all'interno del documento. Aspetta che mi scarico i sorgenti del libro che ho ordinato e vedo un po'.

Aspetta, aspetta...
Non lo fa.

Pure questo post è fuorviante. Sembra quasi che sia Lucene a evidenziare le parole con un colore diverso(e quindi sembra che rilevi l'esatta posizione, riga e colonna, delle stringhe trovate).

Invece sei tu che l'hai fatto con apposito codice Java successivo alla ricerca. O no?
Ed infatti è proprio lucene. Io non ho fatto altro che prendere il "pezzo" usato per evidenziare in html e sostituire i tag <b> con le giuste stringhe per colorare il testo sulla shell.
…new SimpleHTMLFormatter("\033[31m", "\033[0m")…

E comunque il punto B.1 parlava(e parla) chiaro:



Potevi dirlo subito: "guardate che con Lucene non si può fare ciò che richiede il punto B.1".
E io ti avrei risposto: "Benissimo, allora ci confronteremo con Lucene nel punto B.2".

Pregasi notare: "si realizzi un programmino" non "si realizzi un progetto mastodontico".

;)
L'ho scritto molto chiaramente nel messaggio. Se poi hai problemi di comprensione perché leggi troppo in fretta non è mica colpa mia :O

shinya
30-01-2013, 07:57
Non riuscivo ad addormentarmi; mi frullava nella testa quel "mascherati".

Non capisco cosa ci sia da mascherare. Cosa dovrei mascherare e per quale minchia di motivo?
Se per caso ti riferisci al fatto che voglio implementare le caratteristiche avanzate di programmi come Lucene, ebbene, non ho mica detto che dobbiamo farlo tutti quanti. Quella è una cosa che voglio fare io. Qui si tratta di scrivere un programmino di poche righe per la ricerca su file di testo.

Programma mastodontico senza un chiaro fine e, per soprammercato, mascherato da contest. :rolleyes:

Mastodontico! :rotfl:

Se non vuoi buttare tempo evita di scrivere minchiate per favore. Vai a fare qualcosa di produttivo che è meglio per tutti. ;)

"IL PALLONE E' MIO E DECIDO IO!" (cit.)

cdimauro
30-01-2013, 08:57
Idem. Ho altri progetti di gran lunga più interessanti a cui mi sto dedicando, e il poco tempo che ho me lo gestisco come meglio credo.

Comunque Python lo si impara velocemente, e lo si usa altrettanto velocemente. Ma ovviamente non è veloce, per cui, visto che finora c'è stata la gara a chi otteneva il tempo migliore (come al solito: è sempre così in questi contest), non ha alcun senso usarlo.

Detto in altri termini, questo tipo di contest sono pensati per linguaggi come C/C++, C#, Java, Delphi, ecc. Magari qualcuno potrebbe cimentarsi con un po' di assembly, visto che ci siamo. Certamente non per linguaggi che sono pensati per una rapida prototipazione, a scapito delle prestazioni, e che tuttavia nel mondo reale trovano ugualmente spazio anche in scenari di "number crunching" (in questo periodo sto smanettando con soddisfazione con Google App Engine).

Vincenzo1968
30-01-2013, 10:06
Il mascherato non implicava assolutamente un doppio fine da parte tua, tranquillo, ma solo un mero essere definito come qualcosa che non è :read:

Molto semplicemente, secondo me lo "scope" è troppo ampio e troppo poco definito per essere un contest interessante, tant'è che è anche abbastanza difficile confrontare le prestazioni relative dei vari programmi (a parte il punto 1).
Comunque è ovviamente imo, non serve che ci perdi il sonno :asd:

Ehm Tommo,

onestamente comincio ad averne abbastanza di queste critiche. Troppo ampio e troppo poco definito? Questo contest nasce da una precedente discussione nella quale si criticavano i contest per la loro inutilità. Qui ci occupiamo di qualcosa di utile: full text search. È una cosa che serve nel mondo reale.
Non si capisce perché ti sei lanciato con tanto entusiasmo e adesso te ne esci con queste argomentazioni. Potevi evitare fin da subito di partecipare.

Poi che dire dei contest precedenti? Il contest 3, il 4? Sono problemi ben più difficili di quello che stiamo affrontando qui. E su argomenti più specialistici, più di nicchia. All'epoca non ne avevi di cose più produttive da fare?

E guardate che sono pieno di lavoro anch'io. Finitela con questi continui accenni alla perdita di tempo. Sembra che voi siate occupatissimi in cose importanti e io cazzeggi tutto il giorno con le minchiatelle.
Pure io sono in mille faccende affaccendato, al lavoro, eppure riesco a trovare il tempo per i contest.

E, infine, la critica per il fatto che ci occupiamo di argomenti cosidetti "well studied". Ma che significa? Solo perché qualcuno ha già realizzato un software meraviglioso non dovremmo occuparcene anche noi? Di che ci dobbiamo occupare? Solo di argomenti non trattati? Magari l'argomento del contest 20 lo troverai interessante: data mining. È un argomento non well-studied; ci si può sbizzarrire a trovare soluzioni originali. Vedremo stavolta che v'inventerete.

Vincenzo1968
30-01-2013, 10:17
Mo la scrivo io una versione in Python. I tempi li confronteremo con PyPy e Cython.
Avevamo discusso se si riuscissero a ottenere notevoli incrementi nelle prestazioni usando queste due... queste due? Librerie?

Poi, però, non venite a scassarmi i cabasisi dicendo che il codice non è pythonico.

kwb
30-01-2013, 10:29
Comunque Python lo si impara velocemente, e lo si usa altrettanto velocemente. Ma ovviamente non è veloce, per cui, visto che finora c'è stata la gara a chi otteneva il tempo migliore (come al solito: è sempre così in questi contest), non ha alcun senso usarlo.

Detto in altri termini, questo tipo di contest sono pensati per linguaggi come C/C++, C#, Java, Delphi, ecc. Magari qualcuno potrebbe cimentarsi con un po' di assembly, visto che ci siamo. Certamente non per linguaggi che sono pensati per una rapida prototipazione, a scapito delle prestazioni..
Uff, e io che mi stavo quasi convincendo di provare a fare qualcosa... :fagiano:
Scherzi a parte, non per andare off-topic, ma come diavolo è possibile che Java sia più veloce ( sensibilmente?? :stordita: ) di python se entrambi sono linguaggi interpretati?

P.S: Sto seguendo il contest con parecchio interesse

cdimauro
30-01-2013, 10:40
Ehm Tommo,

onestamente comincio ad averne abbastanza di queste critiche. Troppo ampio e troppo poco definito? Questo contest nasce da una precedente discussione nella quale si criticavano i contest per la loro inutilità. Qui ci occupiamo di qualcosa di utile: full text search. È una cosa che serve nel mondo reale.
Non si capisce perché ti sei lanciato con tanto entusiasmo e adesso te ne esci con queste argomentazioni. Potevi evitare fin da subito di partecipare.

Poi che dire dei contest precedenti? Il contest 3, il 4? Sono problemi ben più difficili di quello che stiamo affrontando qui. E su argomenti più specialistici, più di nicchia. All'epoca non ne avevi di cose più produttive da fare?

E guardate che sono pieno di lavoro anch'io. Finitela con questi continui accenni alla perdita di tempo. Sembra che voi siate occupatissimi in cose importanti e io cazzeggi tutto il giorno con le minchiatelle.
Pure io sono in mille faccende affaccendato, al lavoro, eppure riesco a trovare il tempo per i contest.
Devi accettare il fatto che c'è gente che le può reputare minchiatelle, e preferisca dedicarsi a cose che per lui (perché la questione è sempre soggettiva) siano più interessanti.

Mo la scrivo io una versione in Python. I tempi li confronteremo con PyPy e Cython.
Avevamo discusso se si riuscissero a ottenere notevoli incrementi nelle prestazioni usando queste due... queste due? Librerie?
Sono rispettivamente una nuova implementazione di Python, e un compilatore che genera estensioni importabili poi da Python.

Intanto sviluppa il codice in Python, poi farlo girare con CPython o PyPy è esattamente la stessa cosa. Per Cython c'è un po' di lavoro in più da fare.
Poi, però, non venite a scassarmi i cabasisi dicendo che il codice non è pythonico.
Quindi non accetteresti nemmeno suggerimenti? Va bene.
Uff, e io che mi stavo quasi convincendo di provare a fare qualcosa... :fagiano:
Scherzi a parte, non per andare off-topic, ma come diavolo è possibile che Java sia più veloce ( sensibilmente?? :stordita: ) di python se entrambi sono linguaggi interpretati?

P.S: Sto seguendo il contest con parecchio interesse
In realtà sono le specifiche implementazioni a poter essere interpretate o compilate.

Esistono compilatori Java che generano eseguibili, e lo stesso vale per Python.

Ecco, in quest'ultimo caso potrebbe essere utile al contest l'uso di Shedskin (http://code.google.com/p/shedskin/).

Vincenzo1968
30-01-2013, 10:41
...
P.S: Sto seguendo il contest con parecchio interesse

Minchia, meno male!
M'aveva assalito il dubbio che fossi l'unico a interessarmi dell'argomento. Invece siamo almeno in due!

http://www.hwupgrade.org/public/style_emoticons/default/everything_went_better_than_expected.png

Vincenzo1968
30-01-2013, 10:42
Idem. Ho altri progetti di gran lunga più interessanti a cui mi sto dedicando, e il poco tempo che ho me lo gestisco come meglio credo.
...


E 'ndirindingheté!

VICIUS
30-01-2013, 10:46
Uff, e io che mi stavo quasi convincendo di provare a fare qualcosa... :fagiano:
Scherzi a parte, non per andare off-topic, ma come diavolo è possibile che Java sia più veloce ( sensibilmente?? :stordita: ) di python se entrambi sono linguaggi interpretati?

P.S: Sto seguendo il contest con parecchio interesse

Se parliamo della jvm di sun/oracle usa un compilatore jit dalla fine del '96. Solo la 1.0 mi pare fosse interpretata.

Vincenzo1968
30-01-2013, 10:46
Quindi non accetteresti nemmeno suggerimenti? Va bene.

Suggerimenti e critiche costruttive si. Sono qui per questo: per imparare. L'ho ripetuto centanaia di volte e continuerò a ripeterlo fino alla noia.

Una volta mi sono arrischiato(non in un contest) a postare un codice in C# e sono stato subissato di critiche perché era troppo "C style"...

kwb
30-01-2013, 10:51
In realtà sono le specifiche implementazioni a poter essere interpretate o compilate.

Esistono compilatori Java che generano eseguibili, e lo stesso vale per Python.

Ecco, in quest'ultimo caso potrebbe essere utile al contest l'uso di Shedskin (http://code.google.com/p/shedskin/).
Ho letto brevemente l'introduzione.
Sembra tuttavia che usandolo si sia limitati parecchio:
"Besides the typing restriction, programs cannot freely use the Python standard library (although about 25 common modules, such as random and re, are currently supported). Also, not all Python features, such as nested functions and variable numbers of arguments, are supported."


Minchia, meno male!
M'aveva assalito il dubbio che fossi l'unico a interessarmi dell'argomento. Invece siamo almeno in due!

http://www.hwupgrade.org/public/style_emoticons/default/everything_went_better_than_expected.png
Si, purtroppo non c'ho tempo... Ma mi diverte parecchio seguire sto contest, specialmente per i diversi approcci e linguaggi che avete usato..

Vincenzo1968
30-01-2013, 10:51
Uff, e io che mi stavo quasi convincendo di provare a fare qualcosa... :fagiano:
Scherzi a parte, non per andare off-topic, ma come diavolo è possibile che Java sia più veloce ( sensibilmente?? :stordita: ) di python se entrambi sono linguaggi interpretati?

P.S: Sto seguendo il contest con parecchio interesse

Non so come funzioni Python. Java ha il compilatore Just in Time. E sembrerebbe che Oracle abbia fatto un gran bel lavoro con le ultime versioni.
L'abbiamo visto nel punto A. La versione Java di Vicius ha ottenuto gli stessi tempi delle versioni C; solo leggermente più lenta ma di poco, ma di pochissimo. Su Windows, però, Repne è riuscita a fregarci tutti quanti con la sua versione n° 1. :D

kwb
30-01-2013, 10:56
Se parliamo della jvm di sun/oracle usa un compilatore jit dalla fine del '96. Solo la 1.0 mi pare fosse interpretata.
Uhm... Sono rimasto indietro? :stordita:
Comunque sia, chiudiamola qui, la mia ignoranza è off-topic qua :)

Non so come funzioni Python. Java ha il compilatore Just in Time. E sembrerebbe che Oracle abbia fatto un gran bel lavoro con le ultime versioni.
L'abbiamo visto nel punto A. La versione Java di Vicius ha ottenuto gli stessi tempi delle versioni C; solo leggermente più lenta ma di poco, ma di pochissimo. Su Windows, però, Repne è riuscita a fregarci tutti quanti con la sua versione n° 1. :D
Eh lo so, infatti ho pensato che VICIUS avesse fatto un'eccellente implementazione.
M'aspettavo uno strapotere C, considerando la mole di dati da analizzare/generare.. Invece...

EDIT: Non per togliere meriti a VICIUS eh :asd:
Credevo semplicemente che Java fosse mastodontico ( anche perchè per esperienze vissute ho avuto quest'impressione, e anzi, linguaggi come python mi sono parsi più rapidi ) e che quindi VICIUS avesse fatto un'eccellente implementazione

Vincenzo1968
30-01-2013, 11:02
Ed infatti è proprio lucene. Io non ho fatto altro che prendere il "pezzo" usato per evidenziare in html e sostituire i tag <b> con le giuste stringhe per colorare il testo sulla shell.
…new SimpleHTMLFormatter("\033[31m", "\033[0m")…


Ma, immediatamente prima:


Non lo fa.


Lo fa o non lo fa? Mi vuoi proprio fuorviare? :D

Vincenzo1968
30-01-2013, 11:05
Uhm... Sono rimasto indietro? :stordita:
Comunque sia, chiudiamola qui, la mia ignoranza è off-topic qua :)


Eh lo so, infatti ho pensato che VICIUS avesse fatto un'eccellente implementazione.
M'aspettavo uno strapotere C, considerando la mole di dati da analizzare/generare.. Invece...

Anche questo, sicuramente, si: è merito anche di Vicius che ha svolto un ottimo lavoro. Ma se non ci fosse stato il compilatore just in time, i tempi sarebbero stati diversi. Te ne rendi conto quando avvii l'applicazione. La prima volta impiega molto più tempo. La seconda volta è già più veloce e, dalla terza volta in poi, è veloce quanto le applicazioni in C(tranne, sempre, il caso Repne/Windows).

Vincenzo1968
30-01-2013, 11:17
'mbé? dove mi debbo documentare per Python? Che tutorial online debbo seguire? Che libri debbo comprare?

Il libro che ha in firma Cesare si riferisce a una versione troppo vecchia di Python; la 1.5 mi pare. O va bene lo stesso?

C'aggià fa?

kwb
30-01-2013, 11:21
'mbé? dove mi debbo documentare per Python? Che tutorial online debbo seguire? Che libri debbo comprare?

Il libro che ha in firma Cesare si riferisce a una versione troppo vecchia di Python; la 1.5 mi pare. O va bene lo stesso?

C'aggià fa?

Per python c'è l'ottima guida sul sito ufficiale.
http://www.python.org/doc/

Credo che Python 2.7 vada bene, il 3.3 è l'ultimo, ma io userei il 2.7.3 che magari qualche libreria aggiuntiva non è compatibile con quest'ultimo ( dico eh, non sono sicuro ). cdimauro saprà indirizzarti sicuramente meglio di me ( in quanto tempo fa è lui ad aver indirizzato me :D )

C'è pure il sito italiano ufficiale, con la guida in italiano.
Arriva però fino alla 2.7.3: http://docs.python.it/

VICIUS
30-01-2013, 11:23
Lo fa o non lo fa? Mi vuoi proprio fuorviare? :D
Io una mezza idea su come faccia senza salvarsi le posizioni esatte ce l'ho. Approfondire la questione non mi interessa. Ci sono i sorgenti. Se vuoi indagare puoi fallo da solo :Prrr:

Vincenzo1968
30-01-2013, 11:24
Per python c'è l'ottima guida sul sito ufficiale.
http://www.python.org/doc/

Credo che Python 2.7 vada bene, il 3.3 è l'ultimo, ma io userei il 2.7.3 che magari qualche libreria aggiuntiva non è compatibile con quest'ultimo ( dico eh, non sono sicuro ). cdimauro saprà indirizzarti sicuramente meglio di me ( in quanto tempo fa è lui ad aver indirizzato me :D )

C'è pure il sito italiano ufficiale, con la guida in italiano.
Arriva però fino alla 2.7.3: http://docs.python.it/

Grazie mille!
Ho entrambe le versioni installate: 2.7 e 3.3. Allora uso la 2.7.

;)

Vincenzo1968
30-01-2013, 11:26
Io una mezza idea su come faccia senza salvarsi le posizioni esatte ce l'ho. Approfondire la questione non mi interessa. Ci sono i sorgenti. Se vuoi indagare puoi fallo da solo :Prrr:

Quindi mi debbo studiare e Python e Java. Vabbuò.

Fatti perlomeno patpattare, tie':

http://www.hwupgrade.org/public/style_emoticons/default/patpat.gif

cdimauro
30-01-2013, 11:48
E 'ndirindingheté!
Beh, è la verità. Non capisco perché non vuoi accettarla.

Questo (http://www.tinaproject.it/) è uno dei progetti a cui sto contribuendo.

Per il resto il poco tempo che ho lo impiego sulla terza versione del mio processore (di cui t'ho fornito alcuni dettagli nell'altro thread).

Se per te non sono abbastanza interessanti, non posso farci niente. Come ho già detto, è una questione di gusti.
Quindi non accetteresti nemmeno suggerimenti? Va bene.

Suggerimenti e critiche costruttive si. Sono qui per questo: per imparare. L'ho ripetuto centanaia di volte e continuerò a ripeterlo fino alla noia.

Una volta mi sono arrischiato(non in un contest) a postare un codice in C# e sono stato subissato di critiche perché era troppo "C style"...
Spero che almeno ti abbiano detto perché lo era, in modo da farti capire il problema.

Comunque è normale. Io quando scrivevo codice C# ero molto influenzato dal mio stile pythonesco.
Ho letto brevemente l'introduzione.
Sembra tuttavia che usandolo si sia limitati parecchio:
"Besides the typing restriction, programs cannot freely use the Python standard library (although about 25 common modules, such as random and re, are currently supported). Also, not all Python features, such as nested functions and variable numbers of arguments, are supported."
Sì, è un progetto abbastanza giovane, e ha diversi limiti. Ma promette molto bene.
'mbé? dove mi debbo documentare per Python? Che tutorial online debbo seguire? Che libri debbo comprare?

Il libro che ha in firma Cesare si riferisce a una versione troppo vecchia di Python; la 1.5 mi pare. O va bene lo stesso?

C'aggià fa?
No, vai sulla documentazione che c'è nel sito, come ti è stato indicato, e segui il tutorial, che è fatto benissimo. In poco riuscirai a padroneggiare il linguaggio.
Per python c'è l'ottima guida sul sito ufficiale.
http://www.python.org/doc/

Credo che Python 2.7 vada bene, il 3.3 è l'ultimo, ma io userei il 2.7.3 che magari qualche libreria aggiuntiva non è compatibile con quest'ultimo ( dico eh, non sono sicuro ). cdimauro saprà indirizzarti sicuramente meglio di me ( in quanto tempo fa è lui ad aver indirizzato me :D )

C'è pure il sito italiano ufficiale, con la guida in italiano.
Arriva però fino alla 2.7.3: http://docs.python.it/
Personalmente uso la 2.7, perché ho diverse librerie installate che non sono ancora state portate sul nuovo ramo 3.x.

Nello specifico, dovendo realizzare tutto in Python, uno vale l'altro. Ai neofiti suggerisco la 3.x. La 2.7 è mediamente più veloce nella manipolazione degli interi.
Quindi mi debbo studiare e Python e Java. Vabbuò.
Knuth ha impiegato un pomeriggio per Python, ma dubito che per Java sia la stessa cosa. :asd:

Vincenzo1968
30-01-2013, 11:57
Raga' ma un minicorso di Python non me lo potete fare qui, adesso?

Fatemi vedere come si apre un file di testo in lettura, come si leggono le righe fino alla fine del file, come si scrivone le righe lette dal primo file in un secondo file di output, e come si chiude il file. Poi uso il codice che postate come base per implementare la mia versione in Python.

Go!

cdimauro
30-01-2013, 12:14
Raga' ma un minicorso di Python non me lo potete fare qui, adesso?

Fatemi vedere come si apre un file di testo in lettura, come si leggono le righe fino alla fine del file, come si scrivone le righe lette dal primo file in un secondo file di output, e come si chiude il file. Poi uso il codice che postate come base per implementare la mia versione in Python.

Go!
with open('Saro Falsaperla.txt', 'w') as f: f.writelines(open('Agatino Pulvirenti.txt').readlines())
:cool:

Vincenzo1968
30-01-2013, 12:17
Minchia! :D

Ma un modo classico, senza caratteristiche avanzate come with as?

Abbiate pietà! :D

EDIT: ah, il programmino completo, please, con gli include(import in python?).

ARIEDIT: Possibilmente con la possibilità, da parte dell'utente, di specificare i file di input e output dalla riga di comando.

cdimauro
30-01-2013, 12:31
Minchia! :D
Lo sapevo che t'avrei impressionato: l'ho fatto apposta. :D
Ma un modo classico, senza caratteristiche avanzate come with as?

Abbiate pietà! :D
Detto fatto:
with open('Saro Falsaperla.txt', 'w') as f, open('Agatino Pulvirenti.txt') as g:
Lines = g.readlines() # Legge tutte le righe dal file, e le restituisce come lista di stringhe.
f.writelines(Lines)
La with assicura la chiusura di entrambi i file alla fine del blocco di codice, qualunque casino possa succedere.

Se vuoi una versione più C-like:
f = open('Saro Falsaperla.txt', 'w')
g = open('Agatino Pulvirenti.txt')
Lines = g.readlines() # Legge tutte le righe dal file, e le restituisce come lista di stringhe.
g.close()
f.writelines(Lines)
f.close()
EDIT: ah, il programmino completo, please, con gli include(import in python?).
Non c'è bisogno di niente: è già tutto incluso. :cool:
ARIEDIT: Possibilmente con la possibilità, da parte dell'utente, di specificare i file di input e output dalla riga di comando.
import sys
print 'Path del programma:', sys.argv[0]
print 'Numero di argomenti:', len(sys.argv) - 1
for Argument in sys.argv[1 : ]:
print Argument
In alternativa, se vuoi qualcosa di più GNU-like per l'accesso ai parametri, c'è il modulo standard optparse (che ovviamente devi importare), ma non l'ho mai usato. Però nella documentazione trovi tutto: spiegazione del modulo, di cosa fa ed esporta, e semplici esempi su come usarlo.

Vincenzo1968
30-01-2013, 12:35
Grazie mille Cesare!

Mi do subito da fare. Intanto avevo googlato un attimino per conto mio:

http://img254.imageshack.us/img254/630/c19pythonarg.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

Vincenzo1968
30-01-2013, 12:43
Ah, un ultimo favore: io nella mia versione in C dichiaro un array e lo inizializzo con i nomi dei file contenuti nella cartella "All". In Python come si fa?


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

cdimauro
30-01-2013, 12:44
Di nulla. Come vedi Python è la semplicità fatta linguaggio. :)

cdimauro
30-01-2013, 12:45
Ah, un ultimo favore: io nella mia versione in C dichiaro un array e lo inizializzo con i nomi dei file contenuti nella cartella "All". In Python come si fa?
Così:

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

Vincenzo1968
30-01-2013, 12:48
Di nuovo, grazie mille.

Mo mi debbo preparare per andare da un cliente a Trapani. Domani mattina: versione Python!

:D

Vincenzo1968
30-01-2013, 12:51
Di nulla. Come vedi Python è la semplicità fatta linguaggio. :)

Comunque vi lascio con un piccola provocazione: vedete che è come dico io: che se uno viene dal C poi basta un pomeriggio per realizzare lo stesso programmino in Python?

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

cdimauro
30-01-2013, 12:56
ROFL Uguale uguale. :asd:

P.S. Poi dai un'oacchiata al modulo random, che ti servirà sicuramente. Ci sono un sacco di funzioni.

Vincenzo1968
30-01-2013, 13:09
Anzi, che dico un pomeriggio? Pochi minuti: mezz'oretta. Massimo massimo un'ora. Il contrario non è vero: se vieni da Python vai a fare lo stesso programmino in C in mezz'ora... :D

Mezz'oretta, dico, per fare lo stesso programmino; poi, per imparare bene bene il linguaggio, magari servono giorni o settimane.

;)

Vincenzo1968
30-01-2013, 13:10
ROFL Uguale uguale. :asd:

P.S. Poi dai un'oacchiata al modulo random, che ti servirà sicuramente. Ci sono un sacco di funzioni.

Explain, explain che come torno da Trapani mi do subito da fare. :D

kwb
30-01-2013, 13:17
with open('Saro Falsaperla.txt', 'w') as f: f.writelines(open('Agatino Pulvirenti.txt').readlines())
:cool:
:rotfl: :sofico:
Minchia! :D

Ma un modo classico, senza caratteristiche avanzate come with as?

Abbiate pietà! :D

Se chiedi a cdimauro è chiaro che ti risponderà con robe incomprensibili solo per gasarsi di essere un Drago di python :asd: .
Ho degli snippet in python suggeriti da lui per dei programmini fatti per esercitarmi: li ho dovuti riempire di commenti perchè non ho idea di quello che facciano :asd:

Explain, explain che come torno da Trapani mi do subito da fare. :D
Beh, non so a cosa si riferisse cdimauro in particolare, però sul sito ufficiale, c'è tutta la documentazione della libreria, si tratta di sfogliarla e vedere cosa ti serve: http://docs.python.org/2/library/random.html#module-random

wingman87
30-01-2013, 14:45
with open('Saro Falsaperla.txt', 'w') as f: f.writelines(open('Agatino Pulvirenti.txt').readlines())
:cool:
Ma in questo modo il secondo file viene chiuso?

banryu79
30-01-2013, 15:24
Ma in questo modo il secondo file viene chiuso?
L'ha scritto sotto. Vedi post #375 (http://www.hwupgrade.it/forum/showpost.php?p=38946352&postcount=375)
EDIT: visto adesso; mi sa che nel quote di kwb il codice è riportato male...
ARI-EDIT: no lascia perdere, ho quotato io un'altro messaggio dove in effetti il codice è diverso da quello che avete indicato tu e kwb.

Vincenzo1968
30-01-2013, 15:26
Ragazzi, il seguente programmino impiega lo stesso tempo(circa 6/7 secondi) dei programmi in C e Java per creare un file di 1 GiB:


dimfileout = 1024 * 1024 * 1024
dimcurr = 0

print "\nInizio a copiare il file...\n"

fo = open('I_Promessi_Sposi.txt', 'w')
fi = file("All/i_promes.txt", 'rb')
while 1:
r = fi.read(4096)
if r == "" :
fi.seek(0)
#if r[0] == ' ' :
# print "\n Ho trovato uno spazio!\n"
fo.write(r)
dimcurr += 4096
if dimcurr >= dimfileout :
break
fo.close()
fi.close()

print "\nHo finito!\n"


Visto? Passata la paura?
Vabbe' che non elimina gli spazi vuoti superflui e le righe vuote e non mescola le righe in modo casuale, ma la differenza, alla fine, non dovrebbe essere enorme.

Quindi fatevi sotto voi che programmate in Python.

Go!

Appena torno voglio trovare almeno due o tre versioni Python. Almeno una. Almeno mezza.

kwb
30-01-2013, 15:33
Ma in questo modo il secondo file viene chiuso?

il file agatino pulvirenti.txt dovrebbe rimanere aperto al termine...
Però è anche vero che viene chiamato dentro un'altra funzione, quindi forse viene chiuso... :stordita:
Ok, aspettiamo cdimauro :asd:

Vincenzo1968
30-01-2013, 15:49
E a questo punto sarebbe carino avere anche una versione in Ruby. Se l'uomo dai grandi baffi ha qualche minuto di tempo...

:D

Vincenzo1968
30-01-2013, 16:08
Ma anche se dovesse impiegarci, mettiamo, il doppio del tempo, ci sono sempre PyPy e Cython per migliorare le prestazioni.

E, in ogni caso, fregatevene di quanto tempo ci mette.

Go go go!

Sto per tornare a casuccia, a Villabate. Dovrei impiegarci un'oretta e mezza andando piano piano, tranquillo tranquillo.

Poi il tempo della doccia e cavoli vari... Avete circa due ore e mezza.
Se becco il solito casino nella circonvallazione potrei impiegarci anche tre ore e mezza.

marco.r
30-01-2013, 16:49
Vabbe' che non elimina gli spazi vuoti superflui e le righe vuote e non mescola le righe in modo casuale, ma la differenza, alla fine, non dovrebbe essere enorme.

Il mio programma da shell, una volta che non deve eliminare spazi superflui, righe vuote e mescolare righe, diventa

#!/bin/sh
cat $1 > $2

:p

Vincenzo1968
30-01-2013, 19:04
Eccomi. Questa è la versione Ruby del programma Python precedente:


dimfileout = 1024 * 1024 * 1024
dimcurr = 0

fo = File.new("I_Promessi_Sposi.txt", "w")
fi = File.new("All/i_promes.txt", "r")

puts "\nInizio a copiare il file...\n"

while dimcurr < dimfileout
while a = fi.read(4096)
fo.write(a)
dimcurr += 4096
end
fi.seek(0, IO::SEEK_SET)
end

fo.close()
fi.close()

puts "\nFinito!\n"


Impiega circa un secondo in meno :D

Vincenzo1968
30-01-2013, 19:06
Il mio programma da shell, una volta che non deve eliminare spazi superflui, righe vuote e mescolare righe, diventa

#!/bin/sh
cat $1 > $2

:p

Cribbio! :D

Lo stai preparando il punto C?

La tua ultima versione comunque ha ancora un problemino: lascia la prima riga vuota.


#!/bin/sh
SIZE=$(echo $2 | sed 's/G/ * 1000 M/;s/M/ * 1000 K/;s/K/ * 1000/;s/$/ +\\/; $a0' | bc)
BS=1000000
COUNT=$(echo 1 + $SIZE / $BS | bc )
OUTPUT=$1
echo > $OUTPUT

cat All/*.txt | sed -e 's/\s\+/ /g' | grep -v '^\s*$' > text.dat
while $(test `stat --format '%s' $OUTPUT` -lt $SIZE )
do
shuf text.dat | dd bs=$BS iflag=fullblock count=$COUNT >> $OUTPUT
done
truncate -s $SIZE $OUTPUT

cdimauro
30-01-2013, 19:09
Il codice Python potresti sistemarlo in modo da farlo assomigliare a quello di Ruby: può darsi che si guadagni qualcosa.
Anzi, che dico un pomeriggio? Pochi minuti: mezz'oretta. Massimo massimo un'ora. Il contrario non è vero: se vieni da Python vai a fare lo stesso programmino in C in mezz'ora... :D

Mezz'oretta, dico, per fare lo stesso programmino; poi, per imparare bene bene il linguaggio, magari servono giorni o settimane.

;)
Più che altro per la libreria, perché è molto grande. Il linguaggio entro qualche giorno lo conosci già in tutte le sue caratteristiche.
Explain, explain che come torno da Trapani mi do subito da fare. :D
Te l'ha spiegato kwb. Ad esempio c'è una funzione che esegue il mescolamento di una sequenza "in-place": basta chiamarla e hai già risolto un'altra parte del tuo problema.
:rotfl: :sofico:

Se chiedi a cdimauro è chiaro che ti risponderà con robe incomprensibili solo per gasarsi di essere un Drago di python :asd: .
Beh, sì, mi diverte molto. Lo trovo estremamente espressivo come linguaggio, e dà molto spazio alla fantasia. Anche quella perversa di uno come me. :D
Ho degli snippet in python suggeriti da lui per dei programmini fatti per esercitarmi: li ho dovuti riempire di commenti perchè non ho idea di quello che facciano :asd:
Argh. Ecco, questo già non mi piace. Il codice contorto mi diverto a scriverlo per scherzare, come in questi momenti, ma lavorando seriamente cerco di renderlo leggibile e comprensibile, specialmente a chi dovesse guardarlo.

Eventualmente, se ti va, passami quei pezzi di codice, perché vorrei capire dov'è che ho sbagliato.
Beh, non so a cosa si riferisse cdimauro in particolare, però sul sito ufficiale, c'è tutta la documentazione della libreria, si tratta di sfogliarla e vedere cosa ti serve: http://docs.python.org/2/library/random.html#module-random
E' proprio quello, grazie.
Ma in questo modo il secondo file viene chiuso?
Dipende dall'implementazione di Python. CPython lo chiude subito dopo che perde il riferimento all'oggetto file (nello specifico: soltanto alla chiusura del programma), perché ha un garbage collector di tipo mark & sweep, ma PyPy, IronPython, e Jython hanno un comportamento diverso. Quindi... occhio!

Quel codice NON va usato in codice di produzione, perché è difficile sapere di preciso quando quella risorsa verrà rilasciata (in casi semplici, come questo, è banale; in altrino). Una risorsa critica come quella, che non serve più, va rilasciata quanto prima.

La soluzione corretta è, quindi, l'uso del costrutto with con doppio argomento, che ho postato dopo: questa garantisce la chiusura di entrambi i file alla fine del blocco di codice. E ciò è garantito da Python (a meno di "disastri naturali"), perché il with è equivalente semanticamente al seguente pezzo di codice:
f = open(...)
try:
blocco di codice
finally:
f.close()
Ragazzi, il seguente programmino impiega lo stesso tempo(circa 6/7 secondi) dei programmi in C e Java per creare un file di 1 GiB:


dimfileout = 1024 * 1024 * 1024
dimcurr = 0

print "\nInizio a copiare il file...\n"

fo = open('I_Promessi_Sposi.txt', 'w')
fi = file("All/i_promes.txt", 'rb')
while 1:
r = fi.read(4096)
if r == "" :
fi.seek(0)
#if r[0] == ' ' :
# print "\n Ho trovato uno spazio!\n"
fo.write(r)
dimcurr += 4096
if dimcurr >= dimfileout :
break
fo.close()
fi.close()

print "\nHo finito!\n"

Non è Pythonico. :asd:

Vabbé, c'è poco da cambiare alla fine, e sono troppo stanco e ho troppe cose da fare per sistemarlo.

Comunque occhio all'uso dei parametri 'rb' e 'w': nel primo caso hai aperto un file binario, quindi senza conversione dei newline, mentre nel secondo stati scrivendo stringhe, con l'apposita gestione dei caratteri di newline.

I risultati possono essere diversi su macchine diverse dagli Unix.
Visto? Passata la paura?
Vabbe' che non elimina gli spazi vuoti superflui e le righe vuote e non mescola le righe in modo casuale, ma la differenza, alla fine, non dovrebbe essere enorme.
Dipende tutto da come implementare l'eliminazione degli spazi vuoti, e di come gestisci le righe. Con quel pezzo di codice stati soltanto copiando byte, quindi non stringhe. A seconda di come manipoli i byte, però, ci può essere una penalizzazione nell'esecuzione, anche pesante. Python ha un bel po' di funzioni per manipolare le stringhe, che sono ovviamente scritte in C internamente, e ben ottimizzate, ma se vai fuori da queste le prestazioni possono risentirne, e non poco.
Quindi fatevi sotto voi che programmate in Python.

Go!

Appena torno voglio trovare almeno due o tre versioni Python. Almeno una. Almeno mezza.
Seeeee. Come no. Io metto a nanna il piccoli, e se riesco a ronfare prima di loro ho ancora diverse cose da fare prima di chiudere la giornata.

Comunque vediamo cosa fanno gli altri pythonisti: il forum ormai è "infestato" di gente che lavora in Python, per colpa di qualche disgraziato. :asd:
Ma anche se dovesse impiegarci, mettiamo, il doppio del tempo, ci sono sempre PyPy e Cython per migliorare le prestazioni.
Non credo, perché il programma è sostanzialmente I/O bound. Ecco perché si avvicina molto ai tempi di C e Java, e lo farà tanto più quanto aumenterai quel buffer di 4KB che usi per leggere e scrivere.
E, in ogni caso, fregatevene di quanto tempo ci mette.

Go go go!

Sto per tornare a casuccia, a Villabate. Dovrei impiegarci un'oretta e mezza andando piano piano, tranquillo tranquillo.

Poi il tempo della doccia e cavoli vari... Avete circa due ore e mezza.
Se becco il solito casino nella circonvallazione potrei impiegarci anche tre ore e mezza.
Sei hai le mani libere nel frattempo, installati Python in uno smartphone, e lavoraci. :D
Il mio programma da shell, una volta che non deve eliminare spazi superflui, righe vuote e mescolare righe, diventa

#!/bin/sh
cat $1 > $2

:p
Mi sembra che negli Unix ci sia un comando che esegue lo shuffle delle righe di testo passategli come input. Non so quanto possa reggere e che buffer abbia, ma per piccoli file dovrebbe funzionare bene.

Vincenzo1968
30-01-2013, 19:20
Post-fiume tipico di Cesare :D

Rispondo solo a questo:

"I risultati possono essere diversi su macchine diverse dagli Unix."

Ho provato sia su Windows che su Linux e il programma va bene su entrambi i sistemi. Ho verificato col programmino verifica.exe che ho scritto per il punto A.

Domani, ché sono stanco morto e debbo ancora magnà, vedo di modificare i codici Ruby/Python per farli aderire alle specifiche del punto A.

Ma se ci riesco prima di voi, dovrete indossare il sambenito per sei mesi...

Adieu e cavoli vostri(cit.) :D

Vincenzo1968
30-01-2013, 19:35
Ho sistemato i due sorgenti come suggerito da Cesare: leggo e scrivo i file in modalità binaria:

Python:

dimfileout = 1024 * 1024 * 1024
dimcurr = 0

print "\nInizio a copiare il file...\n"

fo = open('I_Promessi_Sposi.txt', 'wb')
fi = file("All/i_promes.txt", 'rb')
while 1:
r = fi.read(4096)
if r == "" :
fi.seek(0)
fo.write(r)
dimcurr += 4096
if dimcurr >= dimfileout :
break
fo.close()
fi.close()

print "\nHo finito!\n"


Ruby:

dimfileout = 1024 * 1024 * 1024
dimcurr = 0

puts "\nInizio a copiare il file...\n"

fo = File.new("I_Promessi_Sposi.txt", "wb")
fi = File.new("All/i_promes.txt", "rb")

while dimcurr < dimfileout
while a = fi.read(4096)
fo.write(a)
dimcurr += 4096
end
fi.seek(0, IO::SEEK_SET)
end

fo.close()
fi.close()

puts "\nHo Finito!\n"

cdimauro
30-01-2013, 19:58
Non ce la faccio a vederlo così il codice. Te lo sistemo prima di staccare:
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')

while dimcurr < dimfileout:
r = fi.read(4096)
while r:
fo.write(r)
dimcurr += 4096
r = fi.read(4096)

fi.seek(0)

fo.close()
fi.close()

print "Ho finito!"
Comunque la dimensione del file di output non sarà la stessa di quello del file di input, a meno che il secondo non sia un multiplo di 4096.

Dovresti usare, invece:
dimcurr += len(r)

P.S. Non usare mai i tab con Python: convertili sempre in spazi.

cdimauro
30-01-2013, 20:00
E se vuoi velocizzarlo, metti sempre il codice in una funzione:
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')

while dimcurr < dimfileout:
r = fi.read(4096)
while r:
fo.write(r)
dimcurr += 4096
r = fi.read(4096)

fi.seek(0)

fo.close()
fi.close()

print "Ho finito!"

Main()

cdimauro
30-01-2013, 20:02
Altra ottimizzazione: caching dei metodi.
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 = fi.read
Write = fo.write
while dimcurr < dimfileout:
r = Read(4096)
while r:
Write(r)
dimcurr += 4096
r = Read(4096)

fi.seek(0)

fo.close()
fi.close()

print "Ho finito!"

Main()

cdimauro
30-01-2013, 20:05
Ultima ottimizzazione: uso di funzioni parziali per quei metodi che hanno dei parametri fissi (questa piacerà a marco.r :D).

from functool 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()
Li ho scritti di getto, senza verificare se ci fossero errori. Al limite ne riparliamo domani.

kwb
30-01-2013, 20:14
Lo stai preparando il punto C?

Questo è il punto che mi interessa di più..


Argh. Ecco, questo già non mi piace. Il codice contorto mi diverto a scriverlo per scherzare, come in questi momenti, ma lavorando seriamente cerco di renderlo leggibile e comprensibile, specialmente a chi dovesse guardarlo.

Eventualmente, se ti va, passami quei pezzi di codice, perché vorrei capire dov'è che ho sbagliato.
Ma mi sono scritto i commenti, quindi no prob! :D
Il problema è che li ho trovati difficili perchè non ho ancora la dimestichezza che ha tu con il linguaggio.


Comunque vediamo cosa fanno gli altri pythonisti: il forum ormai è "infestato" di gente che lavora in Python, per colpa di qualche disgraziato. :asd: Non so quanti c'è ne siano... Ricordo che ai tempi qando ero partito con python, rispondevi solo tu :D

shinya
30-01-2013, 20:19
Ma sono io o sono VENTUNO PAGINE di thread occupati da programmi che fanno copia/incolla qui e là??
Mi sembra di essere in un film di Yasujiro Ozu... non so se avete presente...

WarDuck
30-01-2013, 21:01
Vincenzo il link nella pagina iniziale da dove scaricare i txt nn funziona...

Potete fare una prova (per capire se dipende da me)? :D

Vincenzo1968
30-01-2013, 21:43
Vincenzo il link nella pagina iniziale da dove scaricare i txt nn funziona...

Potete fare una prova (per capire se dipende da me)? :D

E' quel cacchio di sito che a quanto pare mantiene i file uploadati solo per pochi giorni. Aspetta una attimo che li metto nel mio SkyDrive(se riesco a capire come funziona. C'è qualcuno che me lo spiega in modo semplice semplice e con l'ausilio di immagini illustrative? :D ).

Vincenzo1968
30-01-2013, 21:45
Minchia Cesare,

alla fine ci siamo riusciti a spremerti un po' di codice per i contest! :D

Provo i tuoi programmi(nelle varie versioni).

Vincenzo1968
30-01-2013, 22:24
Su Windows nel portatilino ovviamente le applicazioni risultano molto più lente.

c19Python.py e c19Ruby.py sono quelli che ho scritto io. CesareXX.py sono le quattro versioni di Cesare:



C:\Contest19\Python>ptime python c19Python.py

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== python c19Python.py ===

Inizio a copiare il file...


Ho finito!


Execution time: 51.527 s

C:\Contest19\Python>ptime python Cesare01.py

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== python Cesare01.py ===

Inizio a copiare il file...
Ho finito!

Execution time: 51.715 s

C:\Contest19\Python>ptime python Cesare02.py

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== python Cesare02.py ===

Inizio a copiare il file...
Ho finito!

Execution time: 51.127 s

C:\Contest19\Python>ptime python Cesare03.py

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== python Cesare03.py ===

Inizio a copiare il file...
Ho finito!

Execution time: 52.234 s

C:\Contest19\Python>ptime python Cesare04.py

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== python Cesare04.py ===
Traceback (most recent call last):
File "Cesare04.py", line 1, in <module>
from functool import partial
ImportError: No module named functool

Execution time: 0.234 s

C:\Contest19\Python>cd..

C:\Contest19>cd Ruby

C:\Contest19\Ruby>ptime ruby c19Ruby.rb

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== ruby c19Ruby.rb ===

Inizio a copiare il file...
c19Ruby.rb:7:in `initialize': No such file or directory - All/i_promes.txt (Errn
o::ENOENT)
from c19Ruby.rb:7:in `new'
from c19Ruby.rb:7:in `<main>'

Execution time: 0.273 s

C:\Contest19\Ruby>ptime ruby c19Ruby.rb

ptime 1.0 for Win32, Freeware - http://www.pc-tools.net/
Copyright(C) 2002, Jem Berkes <jberkes@pc-tools.net>

=== ruby c19Ruby.rb ===

Inizio a copiare il file...

Ho Finito!

Execution time: 38.102 s

C:\Contest19\Ruby>


Su Windows vince nettamente Ruby :D

:yeah: :winner: :yeah:

C'è da dire, però, che la versione 4 di Cesare da errore e non sono riuscito a farla funzionare.

Vincenzo1968
30-01-2013, 22:30
Vincenzo il link nella pagina iniziale da dove scaricare i txt nn funziona...

Potete fare una prova (per capire se dipende da me)? :D

In attesa di capire come funziona SkyDrive, scaricateli da qui:

http://www.filedropper.com/c19all

;)

Vincenzo1968
30-01-2013, 22:35
Io ho deciso che d'ora in poi utilizzerò Ruby per i contest. Dice ma "rischieresti di perdere nei confronti delle versioni C"; "E chissene?".

:bimbo:

Vincenzo1968
30-01-2013, 22:50
La versione di Cesare che mi da problemi è questa:


from functool 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()


L'errore è questo:


=== python Cesare04.py ===
Traceback (most recent call last):
File "Cesare04.py", line 1, in <module>
from functool import partial
ImportError: No module named functool



http://img805.imageshack.us/img805/1356/c19rubypython.jpg

WarDuck
30-01-2013, 22:52
In attesa di capire come funziona SkyDrive, scaricateli da qui:

http://www.filedropper.com/c19all

;)

Grazie, nei prossimi giorni proverò a metter su qualcosina... probabilmente da sabato perché venerdì ho una scadenza importante :D.

VICIUS
31-01-2013, 06:16
Io ho deciso che d'ora in poi utilizzerò Ruby per i contest. Dice ma "rischieresti di perdere nei confronti delle versioni C"; "E chissene?".

:bimbo:

Si ma alla fine hai comunque preso quello tra i due che è risultato più veloce. Hai ancora la fissa per le prestazioni. :P Il mio consiglio è di provare qualcosa di completamente diverso ignorando i nano secondi.

Prova a dare una occhiata a javascript+nodejs. Oppure haskel.

cdimauro
31-01-2013, 07:48
Ma sono io o sono VENTUNO PAGINE di thread occupati da programmi che fanno copia/incolla qui e là??
Mi sembra di essere in un film di Yasujiro Ozu... non so se avete presente...
Ehm... no. Scusa l'ignoranza. :stordita: Comunque ho visto qualcosa sul wiki, e... m'interessa. :D
La versione di Cesare che mi da problemi è questa:


from functool 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()


L'errore è questo:
Nella fretta avevo dimenticato una s alla fine: quindi functools.

Comunque mi ha meravigliato Ruby, perché mediamente ha prestazioni inferiori a Python. Potresti provare PyPy, Jython, e IronPython adesso.

Vincenzo1968
31-01-2013, 09:58
Si ma alla fine hai comunque preso quello tra i due che è risultato più veloce. Hai ancora la fissa per le prestazioni. :P Il mio consiglio è di provare qualcosa di completamente diverso ignorando i nano secondi.

Prova a dare una occhiata a javascript+nodejs. Oppure haskel.

No, non c'entra il fatto che sul portatilino il programmino Ruby sia risultato più veloce. L'ho già scritto tante volte: non riesco a farmi piacere l'indentazione senza parole chiave e/o simboli. Questa, si, è una mia fissazione.
Per esempio, questo codice C è più compatto ma io non lo sopporto:


if ( x > 0 )
y = 5;
else
y = 8;


preferisco scriverlo così:


if ( x > 0 )
{
y = 5;
}
else
{
y = 8;
}

Vincenzo1968
31-01-2013, 10:05
Ehm... no. Scusa l'ignoranza. :stordita: Comunque ho visto qualcosa sul wiki, e... m'interessa. :D

Nella fretta avevo dimenticato una s alla fine: quindi functools.

Comunque mi ha meravigliato Ruby, perché mediamente ha prestazioni inferiori a Python. Potresti provare PyPy, Jython, e IronPython adesso.

Perfetto Cesare, grazie. Adesso provo tutto quanto su Linux e poi su Windows 8 nel computer buono(insomma, buono, quello "più buono" che c'ho, quello più nuovo).

PyPy, Jython, e IronPython: Minnale, ci sono anche Jython e IronPython? :D
E Cython? Da quelo che ho letto sul sito mi sembra interessante.

Comunque meglio provarli tutti quando avremo le versioni Ruby/Python pienamente funzionanti(eliminazione spazi superflui e righe vuote).
Altrimenti poi qualcuno scrive di 21 pagine di programmi che copiano file...

;)

cdimauro
31-01-2013, 10:20
Ci sono anche JRuby e IronRuby.

Comunque io preferisco questo stile (senza spazi fra le parentesi):
if (x > 0)
y = 5;
else
y = 8;
Oppure, nel caso di più istruzioni in un blocco (quindi dovendo usare per forza le graffe), questo:
if (x > 0) {
y = 5;
}
else {
y = 8;
}

Vincenzo1968
31-01-2013, 10:24
E io invece la graffa di apertura preferisco metterla come prima riga del blocco. Non so perché, è proprio una fissazione, ma è così.

:boh:

The_ouroboros
31-01-2013, 10:31
E io invece la graffa di apertura preferisco metterla come prima riga del blocco. Non so perché, è proprio una fissazione, ma è così.

:boh:

E' lo stile gnu.


f() {

}


che vedo anche spesso in java.

Vincenzo1968
31-01-2013, 10:35
Questo fatto dell'indentazione con le parantesi piazzate in diversi punti potrebbe essere oggetto del punto B.3:


Si abbiano, in input, una serie di file C non indentati. Si restituiscano in output i file indentati e con le parentesi piazzate nell'uno o nell'altro stile.


Sarebbe utile, no? Quante volte capita di scaricare del codice con un'indentazione o uno stile che non ci piacciono?
A me per esempio non piace "x=21"; preferisco "x = 21".

Qui entrerebbero in gioco le tecniche di parsing. Peggio per voi che, non appassionandovi l'argomento, non le avete studiate con cura... (scheeeerzooooo :D )

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

Vincenzo1968
31-01-2013, 10:37
E' lo stile gnu.


f() {

}


che vedo anche spesso in java.

Lo so, ma come dicevo, è una mia fissazione. Io la parentesi di inizio blocco la debbo scrivere a capo.

http://www.hwupgrade.it/forum/images_hwu/smilies/27.gif

Vincenzo1968
31-01-2013, 10:59
http://img694.imageshack.us/img694/6660/c19pythonrubylinux01.jpg
http://img266.imageshack.us/img266/9697/c19pythonrubylinux02.jpg

Ragazzi, su Linux le mie due versioni Ruby/Python battono le quattro versioni Python di Cesare. Di poco ma le battono. :D

:yeah: :winner: :yeah:

Vincenzo1968
31-01-2013, 11:38
Vedete che serve studiare l'implementazione dei DBMS? Se non avessi letto i libri sui DBMS non avrei appreso che per velocizzare l'input/output su disco bisogna utilizzare blocchi da 4 Kb(ma su certi altri sistemi di 8 Kb).

Anche se poi Repne, con la sua versione n° 1, mi ha spiegato che utilizzando blocchi di 16 MB è riuscita a eliminare le inefficienze di Windows.

Vedete? :O

:D

banryu79
31-01-2013, 12:49
Vedete che serve studiare l'implementazione dei DBMS? Se non avessi letto i libri sui DBMS non avrei appreso che per velocizzare l'input/output su disco bisogna utilizzare blocchi da 4 Kb(ma su certi altri sistemi di 8 Kb).

Anche se poi Repne, con la sua versione n° 1, mi ha spiegato che utilizzando blocchi di 16 MB è riuscita a eliminare le inefficienze di Windows.

Queste informazioni sono molto interessanti, puoi spiegare in breve perchè proprio quelle quantità? Oppure indicare una fonte dove viene spiegato?

Vincenzo1968
31-01-2013, 13:04
http://img18.imageshack.us/img18/2882/c19rubypythonwin801jpg.jpg

http://img341.imageshack.us/img341/4100/c19rubypythonwin802jpg.jpg

La macchina è questa:
http://img842.imageshack.us/img842/40/c19macchinawindows8.jpg

Vincenzo1968
31-01-2013, 13:05
Queste informazioni sono molto interessanti, puoi spiegare in breve perchè proprio quelle quantità? Oppure indicare una fonte dove viene spiegato?

Certamente. Dammi un secondo che prendo il libro e ti quoto la parte relativa ;)

cdimauro
31-01-2013, 13:10
Ragazzi, su Linux le mie due versioni Ruby/Python battono le quattro versioni Python di Cesare. Di poco ma le battono. :D

:yeah: :winner: :yeah:
Trovo strano i risultati delle mie 4 versioni. Mi sarei aspettato prestazioni migliori passando dalla prima all'ultima.

Comunque io ho riscritto il codice cercando di renderlo più "pythonico", e sfruttando quello che offre il linguaggio e la libreria, anche se sono rimasto sorpreso dal risultato del tuo pezzo più "C-esco".
Vedete che serve studiare l'implementazione dei DBMS? Se non avessi letto i libri sui DBMS non avrei appreso che per velocizzare l'input/output su disco bisogna utilizzare blocchi da 4 Kb(ma su certi altri sistemi di 8 Kb).
E su altri anche 512 byte o 1KB: dipende tutto dall'implementazione del filesystem, non dal DBMS.
Anche se poi Repne, con la sua versione n° 1, mi ha spiegato che utilizzando blocchi di 16 MB è riuscita a eliminare le inefficienze di Windows.

Vedete? :O

:D
E' normale: più si aumentano i buffer, meno chiamate al kernel ci sono per caricarvi i dati.

The_ouroboros
31-01-2013, 13:11
E su altri anche 512 byte o 1KB: dipende tutto dall'implementazione del filesystem, non dal DBMS.


Arduo argomento questo :D

Vincenzo1968
31-01-2013, 13:24
Il libro è:

http://pages.cs.wisc.edu/~dbbook/

Database Management Systems

by Raghu Ramakrishnan and Johannes Gehrke




DISK SPACE MANAGEMENT
The lowest level of software in the DBMS architecture discussed in Section 1.8, called
the disk space manager, manages space on disk. Abstractly, the disk space manager
supports the concept of a page as a unit of data, and provides commands to allocate
or deallocate a page and read or write a page. The size of a page is chosen to be the
size of a disk block and pages are stored as disk blocks so that reading or writing a
page can be done in one disk I/O.
It is often useful to allocate a sequence of pages as a contiguous sequence of blocks to
hold data that is frequently accessed in sequential order. This capability is essential
for exploiting the advantages of sequentially accessing disk blocks, which we discussed
earlier in this chapter. Such a capability, if desired, must be provided by the disk space
manager to higher-level layers of the DBMS.
Thus, the disk space manager hides details of the underlying hardware (and possibly
the operating system) and allows higher levels of the software to think of the data as
a collection of pages.


Per il momento non trovo il paragrafo dove si consiglia di usare blocchi da 4096 byte. Datemi un momentino...

;)

Vincenzo1968
31-01-2013, 13:28
Trovo strano i risultati delle mie 4 versioni. Mi sarei aspettato prestazioni migliori passando dalla prima all'ultima.

Comunque io ho riscritto il codice cercando di renderlo più "pythonico", e sfruttando quello che offre il linguaggio e la libreria, anche se sono rimasto sorpreso dal risultato del tuo pezzo più "C-esco".

E su altri anche 512 byte o 1KB: dipende tutto dall'implementazione del filesystem, non dal DBMS.

E' normale: più si aumentano i buffer, meno chiamate al kernel ci sono per caricarvi i dati.

Comunque nel computer "buono" la mia versione Python risulta più lenta rispetto alle tue di circa un secondo. La tua versione n° 2 è la migliore tra tutte le versioni Python con soli 17 secondi.

Ma Ruby non si batte con i suoi 10 secondi :D

Vincenzo1968
31-01-2013, 13:34
Sempre dal suddetto libro:


Buffer management in practice: IBM DB2 and Sybase ASE allow buffers to
be partitioned into named pools. Each database, table, or index can be bound
to one of these pools. Each pool can be configured to use either LRU or clock
replacement in ASE; DB2 uses a variant of clock replacement, with the initial clock
value based on the nature of the page (e.g., index nonleaves get a higher starting
clock value, which delays their replacement). Interestingly, a buffer pool client in
DB2 can explicitly indicate that it hates a page, making the page the next choice
for replacement. As a special case, DB2 applies MRU for the pages fetched in some
utility operations (e.g., RUNSTATS), and DB2 V6 also supports FIFO. Informix
and Oracle 7 both maintain a single global buffer pool using LRU; Microsoft SQL
Server has a single pool using clock replacement. In Oracle 8, tables can be bound
to one of two pools; one has high priority, and the system attempts to keep pages
in this pool in memory.
Beyond setting a maximum number of pins for a given transaction, there are
typically no features for controlling buffer pool usage on a per-transaction basis.
Microsoft SQL Server, however, supports a reservation of buffer pages by queries
that require large amounts of memory (e.g., queries involving sorting or hashing).


Non trovo i 4096 byte. Probabilmente l'avro letto su qualche altro libro. Datemi un attimino...

Vincenzo1968
31-01-2013, 13:40
Trovo strano i risultati delle mie 4 versioni. Mi sarei aspettato prestazioni migliori passando dalla prima all'ultima.

Comunque io ho riscritto il codice cercando di renderlo più "pythonico", e sfruttando quello che offre il linguaggio e la libreria, anche se sono rimasto sorpreso dal risultato del tuo pezzo più "C-esco".

E su altri anche 512 byte o 1KB: dipende tutto dall'implementazione del filesystem, non dal DBMS.

E' normale: più si aumentano i buffer, meno chiamate al kernel ci sono per caricarvi i dati.

Eh ma io ho provato ad aumentare le dimensioni del buffer nel mio, ma ho ottenuto solo di peggiorare i tempi.
Ci sarà qualche altra diavoleria, nella versione Repne n° 1, che spero vorrà spiegarci.

Ma dov'è finita? Perché non posta più? :cry:

Vincenzo1968
31-01-2013, 13:52
Cesare dixit: E su altri anche 512 byte o 1KB: dipende tutto dall'implementazione del filesystem, non dal DBMS.

Infatti nella sottospecie di contest sui DBMS (http://www.hwupgrade.it/forum/showpost.php?p=38740714&postcount=15) avevo chiesto le api Linux/Windows per ottenere via codice le dimensioni di una pagina restituite dal sistema operativo.

Da me, su Windows e su Linux, le api restituiscono 4096.

;)

Vincenzo1968
31-01-2013, 13:57
Queste informazioni sono molto interessanti, puoi spiegare in breve perchè proprio quelle quantità? Oppure indicare una fonte dove viene spiegato?

Dai ragazzuoli, vediamo se c'è qualcun'altro che ha il coraggio di scrivere che si tratta di 21 pagine(e, per soprammercato, scritto tutto in maiuscolo!) di programmini che copiano un file su un altro...

:D

banryu79
31-01-2013, 14:18
Ok, ho capito: Vincenzo grazie delle spiegazioni.

Vincenzo1968
31-01-2013, 14:21
Libro suddetto:


Prefetching: In IBM DB2, both sequential and list prefetch (prefetching a list
of pages) are supported. In general, the prefetch size is 32 4KB pages, but this
can be set by the user. For some sequential type database utilities (e.g., COPY,
RUNSTATS), DB2 will prefetch upto 64 4KB pages. For a smaller buffer pool
(i.e., less than 1000 buffers), the prefetch quantity is adjusted downward to 16 or
8 pages. Prefetch size can be configured by the user; for certain environments, it
may be best to prefetch 1000 pages at a time! Sybase ASE supports asynchronous
prefetching of upto 256 pages, and uses this capability to reduce latency during
indexed access to a table in a range scan. Oracle 8 uses prefetching for sequential
scan, retrieving large objects, and for certain index scans. Microsoft SQL Server
supports prefetching for sequential scan and for scans along the leaf level of a B+
tree index and the prefetch size can be adjusted as a scan progresses. SQL Server
also uses asynchronous prefetching extensively. Informix supports prefetching with
a user-defined prefetch size.

Vincenzo1968
31-01-2013, 14:26
http://ibdeveloper.blogspot.it/2008/09/what-page-size-i-should-use-in-my.html

What page size I should use in my database?

It's a common question with interesting background from developers . As I can suppose from IBSurgeon statistics, 99% of Firebird and InterBase developers use default page size: since the old ages it is 1024 bytes, and only for Firebird 2.0 it is changed to 4096 by default.
There are 4 main things related with page size: indices depth, database cache size, records per page quantity and disk cluster size.

The shortest answer to this question is to use 4k, 8k or 16k page size. That's it.


http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=%2Fcom.ibm.db2.udb.admin.doc%2Fdoc%2Fr0001954.htm

Database page size = 4096

Vincenzo1968
31-01-2013, 16:09
Si ma alla fine hai comunque preso quello tra i due che è risultato più veloce. Hai ancora la fissa per le prestazioni. :P Il mio consiglio è di provare qualcosa di completamente diverso ignorando i nano secondi.

Prova a dare una occhiata a javascript+nodejs. Oppure haskel.

Comunque si, Ruby m'ha favorevolmente impressionato anche per i tempi.
Vabbe' che una rondine non fa primavera e in altri ambiti Python potrebbe risultare più veloce. Ma si tratta di un argomento importante, almeno per me: l'IO su file.
Io al lavoro, per il 70%, di questo mi occupo: IO su file di testo e/o binari.

E non sono nanosecondi. Si tratta del doppio del tempo su Windows 8.

L'algoritmo-metodo che abbiamo utilizzato è lo stesso per entrambe le versioni Python/Ruby: lettura/scrittura di file su blocchi da 4096 byte.
Sono talmente simili i due programmi che, ad una prima occhiata, uno niubbo come me, non si accorgerebbe di qual è la versione Python e qual è la versione Ruby.

;)

Vincenzo1968
31-01-2013, 20:54
Che poi Vicius, cambiando Ruby con Java, s'è infilato in un vicolo cieco. Adesso che passo a Ruby, come farà a sfottermi per la lunghezza del codice?
E il bello è che non potrà neanche vantarsi della maggiore(forse, eventualmente) velocità d'esecuzione del suo programma rispetto al mio. Altrimenti potrei scimmiottarlo dicendo che è fissato con le prestazioni.

Io al contrario potrò tranquillamente vantarmi di avercelo molto più corto e compatto del suo(il codice dico). :O

Minchia s'è data la zappa sui piedi. Ma un colpo talmente forte da tranciarseli i piedi...

:D

Vincenzo1968
31-01-2013, 22:04
Ahhhh ecco perché:

http://stackoverflow.com/questions/5990823/why-ruby-1-9-is-faster-than-python-2-7-and-3-2

I read this bunch of links : http://pack.li/L

ruby 1.9 seems to be 2 times faster than 1.8... and faster than python 2.7 and 3.2

I made some tests, it is not only on recursion (I knew python was bad about that), put for more standard stuff also.

So here is my question : How the ruby team have done that ? 2x improvement ? Do they include an JIT compiler/optimizer or something ?


Passando dalla versione 1.8 alla 1.9 le prestazioni di Ruby sono aumentate di 2 volte.

:D

cdimauro
31-01-2013, 22:31
Dalla prima risposta:
I am a rubyist, and I think you didn't read those (quite old) articles fully. Both admit having used ... "sensationalist" headlines. And that the algorithms they use aren't optimal. So they have little value in my eyes.

The "best" place I know for comparing languages is http://shootout.alioth.debian.org . I quote "best" because as others are saying, staging language speed based on a bunch of particular implementations lacks statistical rigor.

That said, if you pitch ruby 1.9 against Python 3, you get these results

The results are: of the 10 tests used, ruby 1.9 is faster than Python in 2 tests. It's similar in 4 and it's slower in the rest (the last example is so bad I'm tempted to call it spurious)

So, according to those 10 different tests, one can only conclude that no, ruby isn't faster than Python in general. (Only in some particular cases).
Ruby 1.9 vs Python 3 (32 bit, single core) (http://benchmarksgame.alioth.debian.org/u32/benchmark.php?test=all&lang=yarv&lang2=python3)
Ruby 1.9 vs Python 3 (64 bit, quad core) (http://benchmarksgame.alioth.debian.org/u64q/benchmark.php?test=all&lang=yarv&lang2=python3)

Vincenzo1968
31-01-2013, 22:31
Vicius è spacciato:

http://img405.imageshack.us/img405/8027/jrubyinstall.jpg

http://img145.imageshack.us/img145/3818/jrubyinstalled.jpg

A quanto pare JRuby è più veloce di Ruby.

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

:bimbo:

cdimauro
31-01-2013, 22:35
La stessa cosa dovrebbe essere per Jython con CPython.

Comunque sarebbe interessante vedere anche come si comporta PyPy, e poi IronPython e IronRuby.

Come vedi, diverse implementazioni dello stesso linguaggio portano a risultati diversi.

Vincenzo1968
31-01-2013, 22:56
ehm, si Cesare, ma io mi riferivo alle prove che ho effettuato io con le nostre versioni per il punto A. E Ruby risulta più veloce, soprattutto su Windows, per quanto riguarda l'IO su file. evidentemente il passaggio dalla 1.8 alla 1.9 è stato salutare per Ruby da questo punto di vista.

Domani provo JRuby :D

L'avete voluta la bicicletta? Adesso pedalate!
M'avete messo la pulce nell'orecchio(o in testa? Come di dice?) coi linguaggi di altissimo livello? Ebbene, vi siete data la zappa sui piedi. :D

Vincenzo1968
31-01-2013, 23:04
La stessa cosa dovrebbe essere per Jython con CPython.

Comunque sarebbe interessante vedere anche come si comporta PyPy, e poi IronPython e IronRuby.

Come vedi, diverse implementazioni dello stesso linguaggio portano a risultati diversi.

Ah sicuramente! Io da domani il punto B.1 lo faccio in Ruby. La versione in C continuo a svilupparla, come dicevo prima, con le caratteristiche avanzate e poi la metto su un sito dedicato.

Sarà interessante confrontare Ruby/JRuby con Python/PyPy/ IronPython/IronRuby.

;)

banryu79
01-02-2013, 08:28
Vicius è spacciato:
A quanto pare JRuby è più veloce di Ruby.

Considera che quel programma, in forma sorgente è JRuby ma, nel momento in cui lo compili (che io sappia), sputa fuori bytecode per la JVM: a quel punto puoi anche smettere di chiamarlo JRuby credo... Il runtime è la piattaforma Java.

Al limite potresti confrontarlo con Jython (linguaggi diversi, stessa piattaforma?)

Vincenzo1968
01-02-2013, 09:58
Considera che quel programma, in forma sorgente è JRuby ma, nel momento in cui lo compili (che io sappia), sputa fuori bytecode per la JVM: a quel punto puoi anche smettere di chiamarlo JRuby credo... Il runtime è la piattaforma Java.

Al limite potresti confrontarlo con Jython (linguaggi diversi, stessa piattaforma?)

Ah quindi Vicius non potrà nemmeno sperare di battermi coi tempi di esecuzione. Bene bene... :D

Vincenzo1968
01-02-2013, 10:42
Guardate che cose meravigliose si possono fare con Ruby. Guardate come si risolve il contest 6 (http://www.hwupgrade.it/forum/showthread.php?t=1850150) con sole 13 righe di codice:

http://www.hwupgrade.it/forum/showpost.php?p=24739164&postcount=11
Questi sono i tempi per il primo file, togliendo i vari output.
Macintosh:Desktop mirco$ time ruby contest6.rb

real 0m3.078s
user 0m2.993s
sys 0m0.048s

13 righe di codice, 3 minuti per finire tutto :p

D'ora innanzi sarò io a vantarmi della brevità del codice. :D

:yeah: :winner: :yeah:

Vincenzo1968
01-02-2013, 11:14
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

;)

VICIUS
01-02-2013, 11:17
Guardate che cose meravigliose si possono fare con Ruby. Guardate come si risolve il contest 6 (http://www.hwupgrade.it/forum/showthread.php?t=1850150) con sole 13 righe di codice:

http://www.hwupgrade.it/forum/showpost.php?p=24739164&postcount=11


D'ora innanzi sarò io a vantarmi della brevità del codice. :D

:yeah: :winner: :yeah:
Il mitico contest in cui vi ho asfaltato con eval(). Che ricordi :asd:

Comunque il tuo codice non mi preoccupa. Ormai hai la mente corrotta da c, compilatori e b+tree. Dubito fortemente che avresti scritto una cosa simile. :O

Vincenzo1968
01-02-2013, 12:03
Punto B.2:

Riesco a battere, con la versione in C, il programma Linux:

http://img38.imageshack.us/img38/7573/c19b02results.jpg

10 secondi contro 27.

Anche se i numeri differiscono. Bisogna verificare come contano le parole i due programmi. Faccio la prova con un file di piccolissime dimensioni.

Minchia se serve studiare il funzionamento interno di un DBMS. Eccome se serve.

Vincenzo1968
01-02-2013, 12:04
Il mitico contest in cui vi ho asfaltato con eval(). Che ricordi :asd:

Comunque il tuo codice non mi preoccupa. Ormai hai la mente corrotta da c, compilatori e b+tree. Dubito fortemente che avresti scritto una cosa simile. :O

:asd:

Mo tocca a me asfaltarvi :D

Vincenzo1968
01-02-2013, 12:16
Mo scrivo la versione in Ruby.

Ragazzi il punto B.2 è facile facile, proprio alla portata di tutti. È un problema da esercizio di introduzione alla programmazione. E bisogna confrontarsi con un programmino come wc(wc sta per word count), non con giganti come Lucene o simili.

E dunque: go!

Vincenzo1968
01-02-2013, 12:17
La mia versione C per il punto B.2:

EDIT: modificato. Corretto piccolo bug:
ARIEDIT: corretto altro bug. Non contava correttamente il numero di caratteri:
ARIRIEDIT: Migliorato il codice:

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

Vincenzo1968
01-02-2013, 12:30
Il mitico contest in cui vi ho asfaltato con eval(). Che ricordi :asd:



La riga che dava fastidio era la 6. Più precisamente quello strano carattere a doppia S che ruby sembrava non capire essere utf8.
(-49.63 + (39.21^4^0.5 § 87.29)) - ((-93.21 * 84.57/(1 + -85.75) - 5) / (-4.3 + -64.86^(1/2))))
Ho dovuto paciugare un po' con iconv per sistemare la codifica ed ora funziona tutto.

I tempi per il secondo file sono:
Macintosh:Desktop mirco$ time ruby contest6.rb

real 0m6.174s
user 0m6.008s
sys 0m0.102s

Il codice è:
File.open('prova.txt', 'r') do |file|
file.gets # ignora la prima riga
while expression = file.gets
begin
result = eval(expression.chop!.gsub('^', '**'))
puts "#{expression} = #{result}"
rescue ZeroDivisionError
puts "#{expression} : Divisione per zero"
rescue SyntaxError
puts "#{expression} : Errore di sintassi nella espressione"
end
end
end

:D

VICIUS
01-02-2013, 12:47
La situazione purtroppo non è cambiata molto. Ancora oggi la gestione degli encoding è pessima. :mad:

Vincenzo1968
01-02-2013, 13:06
Mi sto rileggendo il contest 6. Che bei ricordi! Mi ero beccato la mia prima sospensione da parte ci Cionciuzzo(quand'era moderatore):

http://www.hwupgrade.it/forum/showpost.php?p=24772529&postcount=146

:D

Bei tempi, cribbio!

Vincenzo1968
01-02-2013, 13:09
La situazione purtroppo non è cambiata molto. Ancora oggi la gestione degli encoding è pessima. :mad:

Infatti. No ma io ho riportato il tuo post qui per mostrare la bellezza e la compettezza del codice Ruby(Ruby mon amour :D ).

Non avverti come un senso di perdita mo che sei passato a Java? Ma come fai a dormire la notte?

Fatti patpattare un attimino:

http://www.hwupgrade.org/public/style_emoticons/default/patpat.gif

Vincenzo1968
01-02-2013, 13:15
Va che roba, Vicius:

Ho visto le immagini senza output nel tuo messaggio così ho pensato bene di approfittarne e togliere del tutto l'output ora correggo subito.


Potrei di certo fattorizzare tutto in varie fasi: lettura del file, conversione in infix, valutazione e output ma il codice si allungherebbe molto e diventerebbe più contorto, la ram occupata sarebbe molta e secondo me sarebbe anche più lento.

Ultima versione:
class Fixnum
def /(operand)
self.to_f / operand.to_f
end
end

class String
def binary_operator?
true if self =~ /[+\-*\/^]/
end
def unary_operator?
true if self == '~'
end
end

start = Time.now
File.open('output.txt', 'w') do |output|
File.open('espressioni3.txt', 'r') do |file|
file.gets # ignora la prima riga
while rpn_expression = file.gets
stack = Array.new
tokens = rpn_expression.chop.split
tokens.each do |t|
if t.binary_operator?
b = stack.pop
a = stack.pop
stack.push "(#{a} #{t} #{b})"
elsif t.unary_operator?
stack.push "#{t}#{stack.pop}"
else
stack.push t
end
end
infix = stack.pop.gsub('~','-')
output.puts "#{infix} = #{eval(infix.gsub('^', '**'))}"
end
end
end
puts "Ci ho messo #{(Time.now - start).to_s} secondi"


Ma come fai? (a dormire la notte).

:D

VICIUS
01-02-2013, 13:17
Infatti. No ma io ho riportato il tuo post qui per mostrare la bellezza e la compettezza del codice Ruby(Ruby mon amour :D ).

Non avverti come un senso di perdita mo che sei passato a Java? Ma come fai a dormire la notte?

Fatti patpattare un attimino:

http://www.hwupgrade.org/public/style_emoticons/default/patpat.gif
Ho la grande fortuna di poter scegliere gli strumenti che ritengo più opportuni per poter lavorare senza imposizioni dall'alto. Java mi piace molto e se è la soluzione migliore la uso. Ruby lo uso spessissimo come linguaggio di scripting per automatizzare task ripetitivi o piccoli programmi.

Vincenzo1968
01-02-2013, 13:23
Ho la grande fortuna di poter scegliere gli strumenti che ritengo più opportuni per poter lavorare senza imposizioni dall'alto. Java mi piace molto e se è la soluzione migliore la uso. Ruby lo uso spessissimo come linguaggio di scripting per automatizzare task ripetitivi o piccoli programmi.

Vabbé allora ti patpatto:

http://www.hwupgrade.org/public/style_emoticons/default/patpat.gif

Vincenzo1968
01-02-2013, 14:21
C'era un piccolo bug nella mia versione per il punto B.2. L'ho corretto. Adesso restituisce lo stesso numero di parole di wc:

http://img687.imageshack.us/img687/3673/mywcc.jpg

Il file di prova è questo:


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.


Ma nel file da 1 GiB, il mio conta 176 milioni di parole mentre wc soltanto 173. Vai a sapere perché.

http://img823.imageshack.us/img823/7287/c19b02wcemywc.jpg

Vincenzo1968
01-02-2013, 15:20
Punto B.2, file da 5 GiB creato col programma di Repne:

http://img254.imageshack.us/img254/4741/c19b02newnew.jpg

:yeah: :winner: :yeah:

Serve studiare i DBMS. Eccome se serve! :O

:D

Vincenzo1968
01-02-2013, 17:29
Il mio è pure più accurato nel conteggio del numero di caratteri:

http://img5.imageshack.us/img5/7917/c19b02newnewnew.jpg

http://img4.imageshack.us/img4/4779/filepiccolodim.jpg

Nel file piccolo sono 279 come giustamente riportato dalla mia versione. wc riporta invece, erroneamente, 274.

:yeah: :winner: :yeah:

kwb
01-02-2013, 18:48
Ma così, una info: uno deve aver partecipato ai punti precedenti del contest per partecipare a questo o chi c'è c'è?

Vincenzo1968
01-02-2013, 18:56
Ma così, una info: uno deve aver partecipato ai punti precedenti del contest per partecipare a questo o chi c'è c'è?

No, puoi partecipare a uno qualunque dei punti. Anche senza aver svolto i precedenti.

Puoi partecipare anche con semplici pareri, suggerimenti, illustrazioni di algoritmi, etc. Non è necessario postare il codice(anche se auspicabile).

Insomma, puoi fare quello che ti pare. ;)

Vincenzo1968
01-02-2013, 19:15
http://img850.imageshack.us/img850/9619/jrubywin864.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

Vincenzo1968
01-02-2013, 19:22
http://img547.imageshack.us/img547/1709/aptgetjruby.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

https://github.com/jruby/jruby/wiki

VICIUS
01-02-2013, 19:57
Punto b in javascript. Così. Giusto per variare un po' :asd:
var fs = require('fs'),
lazy = require('lazy')

lazy(fs.createReadStream('file'))
.lines
.map(function(buff) {
var words = buff.toString().split(/\W+/)
var longestWord = ''
words.forEach(function(word) {
if (longestWord.length < word.length) {
longestWord = word
}
})
return {
bytes: buff.length,
words: words.length,
longestWord: longestWord
}
})
.foldr(function(line, x) {
return {
bytes: line.bytes + x.bytes + 1,
lines: x.lines + 1,
words: line.words + x.words,
longestWord: x.longestWord.length < line.longestWord.length ? line.longestWord : x.longestWord
}
},
{ bytes: 0, lines: 0, words: 0, longestWord: '' },
function(res) {
console.log('nel file ci sono ' + res.bytes + ' byte')
console.log('su ' + res.lines + ' righe')
console.log('che contengono ' + res.words + ' parole')
console.log('e la parola più lunga è "' + res.longestWord + '"')
})
Bisogna installare lazy tramite npm. Poi basta lanciarlo con node e lui prova ad aprire il file di nome "file". Per semplicità ho assunto che la regexp [A-Za-z0-9_]+ rappresenti una parola.

Vincenzo1968
01-02-2013, 20:28
Punto b in javascript. Così. Giusto per variare un po' :asd:
var fs = require('fs'),
lazy = require('lazy')

lazy(fs.createReadStream('file'))
.lines
.map(function(buff) {
var words = buff.toString().split(/\W+/)
var longestWord = ''
words.forEach(function(word) {
if (longestWord.length < word.length) {
longestWord = word
}
})
return {
bytes: buff.length,
words: words.length,
longestWord: longestWord
}
})
.foldr(function(line, x) {
return {
bytes: line.bytes + x.bytes + 1,
lines: x.lines + 1,
words: line.words + x.words,
longestWord: x.longestWord.length < line.longestWord.length ? line.longestWord : x.longestWord
}
},
{ bytes: 0, lines: 0, words: 0, longestWord: '' },
function(res) {
console.log('nel file ci sono ' + res.bytes + ' byte')
console.log('su ' + res.lines + ' righe')
console.log('che contengono ' + res.words + ' parole')
console.log('e la parola più lunga è "' + res.longestWord + '"')
})
Bisogna installare lazy tramite npm. Poi basta lanciarlo con node e lui prova ad aprire il file di nome "file". Per semplicità ho assunto che la regexp [A-Za-z0-9_]+ rappresenti una parola.

Punto B quale? B.1? B.2?

E come installo lazy tramite npm?

npm versione 1.1.4 va bene?

Vincenzo1968
01-02-2013, 20:30
vincenzo@Ubuntu12-10-AMD64:~$ npm --help

Usage: npm <command>

where <command> is one of:
add-user, adduser, apihelp, author, bin, bugs, c, cache,
completion, config, deprecate, docs, edit, explore, faq,
find, get, help, help-search, home, i, info, init, install,
la, link, list, ll, ln, login, ls, outdated, owner, pack,
prefix, prune, publish, r, rb, rebuild, remove, restart, rm,
root, run-script, s, se, search, set, show, shrinkwrap,
star, start, stop, submodule, tag, test, un, uninstall,
unlink, unpublish, unstar, up, update, version, view,
whoami

npm <cmd> -h quick help on <cmd>
npm -l display full usage info
npm faq commonly asked questions
npm help <term> search for help on <term>
npm help npm involved overview

Specify configs in the ini-formatted file:
/home/vincenzo/.npmrc
or on the command line via: npm <command> --key value
Config info can be viewed via: npm help config

npm@1.1.4 /usr/share/npm


:confused:

Vincenzo1968
01-02-2013, 20:38
http://img266.imageshack.us/img266/9435/lazy.jpg

http://www.hwupgrade.org/public/style_emoticons/default/coolface.png

kwb
01-02-2013, 20:39
Domande:
1. Che file bisogna utilizzare in input?
2. Posso fare più versioni ( nel senso, usare linguaggi differenti )?
3. La misurazione dei tempi, me la spiegate? Come funziona?

Vincenzo1968
01-02-2013, 20:46
Vicius, è velocissimo, ma non trova un tubo!

http://img689.imageshack.us/img689/7610/c19b01viciusjs.jpg

Vincenzo1968
01-02-2013, 20:49
Domande:
1. Che file bisogna utilizzare in input?
2. Posso fare più versioni ( nel senso, usare linguaggi differenti )?
3. La misurazione dei tempi, me la spiegate? Come funziona?

Risposte:
1. questi: http://www.filedropper.com/c19all
2. Si.
3. Per misurare i tempi, su Linux, anteponi il comando time.

Per esempio, se il tuo programma si chiama myprog.py, fai così:

time python myprog.py


Su Windows invece, devi scaricare e usare ptime.exe che trovi qui: http://www.pc-tools.net/win32/ptime/
per usarlo:

ptime python myprog.py

kwb
01-02-2013, 21:18
Ok, quindi per sto punto b2 prendo uno dei file a caso e faccio il word count?
Non dovremmo usare tutti file grossi uguali?
Oppure mi prendo il codice di qualcuno di voi e creo il file da 1gibbo?

Vincenzo1968
01-02-2013, 22:07
Ok, quindi per sto punto b2 prendo uno dei file a caso e faccio il word count?
Non dovremmo usare tutti file grossi uguali?
Oppure mi prendo il codice di qualcuno di voi e creo il file da 1gibbo?

Il tuo programma, per vedere se funziona, lo puoi provare anche su file piccoli. Poi, quando posti il codice, ci penso io a prendere i tempi sulla mia macchina. Così abbiamo i tempi di tutti quanti su una macchina unica.

Comunque, se vuoi provarli su un file grosso, puoi usare il codice di uno di noi per il punto A. Oppure puoi usare una delle quattro versioni Python che Cesare ha postato ultimamente: Creano file da 1 GiB.

Per esempio, questa:

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()


;)

kwb
02-02-2013, 00:08
Chiaro!;)

VICIUS
02-02-2013, 06:37
Vicius, è velocissimo, ma non trova un tubo!

http://img689.imageshack.us/img689/7610/c19b01viciusjs.jpg

Non dovrei risponderti. C'è scritto nel messaggio.

Di sicuro non va perché non c'è nessun file che si chiama file nella cartella in cui lo hai lanciato.

WarDuck
02-02-2013, 09:35
Eccomi qui.

Domanda banale, per generare il file grosso (punto A) bisogna usare TUTTI i files nella cartella giusto?

Vincenzo1968
02-02-2013, 10:09
Eccomi qui.

Domanda banale, per generare il file grosso (punto A) bisogna usare TUTTI i files nella cartella giusto?

Si esatto. Nella prima passata prendi una riga a caso da un file a caso e la metti nel file di output. La seconda riga sempre a caso da un file a caso e così via fino a quando non avrai copiato tutte le righe di tutti i file nel file in output.
Poi ricominci la procedura per la seconda, terza, quarta etc passata fino a quando il file in output non raggiungerà le dimensioni specificate dall'utente.

Vincenzo1968
02-02-2013, 10:19
Non dovrei risponderti. C'è scritto nel messaggio.

Di sicuro non va perché non c'è nessun file che si chiama file nella cartella in cui lo hai lanciato.

http://img809.imageshack.us/img809/815/viciusnothing.jpg

Comunque non ho capito se sono riuscito a installare 'sto lazy. Dallo screenshot di qualche post fa sembrerebbe di si ma:


vincenzo@Ubuntu12-10-AMD64:~/Contest19/Exe$ lazy --version
Comando "lazy" non trovato. Forse si intendeva:
Comando "laby" dal pacchetto "laby" (universe)
lazy: comando non trovato


Ma che è 'sto lazy? :mbe:

Vincenzo1968
02-02-2013, 10:37
Una domanda: per usare il tipo uint64_t con printf che cosa bisogna fare?

No perché avevo provato a usarlo per il punto B.2 al posto di unsigned long long

typedef struct tagFindRec
{
unsigned long long countChars;
int countRows;
int maxRowLenght;
int countWords;
int maxWordLenght;
char szLongerWord[1000];
} FindRec;


Ma non riuscivo a stampare il valore con printf.
Con unsigned long long invece posso utilizzare il formato "%llu":


printf("Il file contiene %llu caratteri.\n", myFindRec.countChars);


Così va bene e per GCC su Linux e per Visual Studio su Windows.

WarDuck
02-02-2013, 10:43
Si esatto. Nella prima passata prendi una riga a caso da un file a caso e la metti nel file di output. La seconda riga sempre a caso da un file a caso e così via fino a quando non avrai copiato tutte le righe di tutti i file nel file in output.
Poi ricominci la procedura per la seconda, terza, quarta etc passata fino a quando il file in output non raggiungerà le dimensioni specificate dall'utente.

Quindi ricapitolando:

1) bisogna usare tutti i files
2) bisogna usare almeno 1 volta tutte le righe di tutti i files

Se il vincolo 2 è vero, è inefficiente scegliere le righe a caso :p.

PS: in effetti, si possono prima permutare le linee di tutti files e andare sequenzialmente scegliendo a caso il file da cui attingere.

Vincenzo1968
02-02-2013, 10:52
Eccomi qui.

Domanda banale, per generare il file grosso (punto A) bisogna usare TUTTI i files nella cartella giusto?

Comunque, se vuoi, puoi passare direttamente al punto B. Per creare il file grosso puoi utilizzare una delle nostre soluzioni.

Se poi ti va di farlo per il piacere di farlo è tutto un altro discorso. ;)

La soluzione per il punto A che è risultata più veloce(di poco su Linux, di molto su Windows) è la Repne n° 1:


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//#include <mem.h>
#include <malloc.h>

#define N_INPUT_FILE 33
#define N_SWAP_PER_ELEMENT 8
#define N_SWAP_RAND_FILE (N_INPUT_FILE*N_SWAP_PER_ELEMENT)
#define MAX_LINE_PER_FILE 65536
#define BUFFER_MB_BLOCK 16
#define BUFFER_OUTPUT_SIZE (BUFFER_MB_BLOCK*1024*1024)

int main(argc,argv)
int argc;
char *argv[];

{
unsigned char **n,*m,*tmp_buffer_output,*buffer_output,*tmp1_buffer,*tmp2_buffer,*tmp3_buffer,*tmp4_buffer,**line_pointer[N_INPUT_FILE],*buffer_input_file[N_INPUT_FILE],*input_file_name[N_INPUT_FILE]=
{"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"};
//{"amor_fa_.txt","bertoldo.txt","candid_t.txt","convivio.txt","dell_art.txt","del_roma.txt","del_tr_t.txt","descartes_discorso_sul_metodo.txt","de_vulga.txt","dialogo_.txt","diario_d.txt","discorsi.txt","don_chis.txt","il_bugia.txt","il_corsa.txt","il_saggi.txt","i_pirati.txt","i_promes.txt","la_banca.txt","la_divin.txt","la_ric_t.txt","la_rivin.txt","la_tigre.txt","le_mecan.txt","le_opere.txt","le_tigri.txt","l_adulat.txt","l_amante.txt","l_avaro.txt","principe.txt","sidereus.txt","storia_d.txt","sulla_or.txt"};
int *o,i,j,k,l,p,n_line_size,last_char,line_file,output_file_size=1,input_file_size[N_INPUT_FILE],*line_size[N_INPUT_FILE],tmp_line_per_file[N_INPUT_FILE],line_per_file[N_INPUT_FILE];
FILE *input_file,*output_file;
time_t t;

printf("CreateTextTestFile - Build 1\n");

if((argc<2)||(argc>3))
{
printf("Use: %s <output_file_name> [optional_size_in_MBytes]",argv[0]);
return 1;
}

if(argc==3)
output_file_size=atoi(argv[2])/BUFFER_MB_BLOCK;

printf("Output file size: %d MiB\n",output_file_size*BUFFER_MB_BLOCK);

if(output_file_size<1)
{
printf("Invalid [optional_size_in_MBytes]\n");
return 1;
}

srand((unsigned)time(&t));

for(i=0;i<N_INPUT_FILE;i++)
{
if((input_file=fopen(input_file_name[i],"rb"))==NULL)
{
printf("Unable to open input file: %s\n",input_file_name[i]);
return 1;
}

if(fseek(input_file,0L,SEEK_END))
{
printf("Unable to seek input file: %s\n",input_file_name[i]);
return 1;
}

if((input_file_size[i]=ftell(input_file))==-1)
{
printf("Unable to tell input file: %s\n",input_file_name[i]);
return 1;
}

if(fseek(input_file,0L,SEEK_SET))
{
printf("Unable to seek input file: %s\n",input_file_name[i]);
return 1;
}

if((buffer_input_file[i]=malloc(input_file_size[i]))==NULL)
{
printf("Unable to allocate %d bytes %s\n",input_file_size[i]);
return 1;
}

if((line_size[i]=malloc(MAX_LINE_PER_FILE*sizeof(int)))==NULL)
{
printf("Unable to allocate %d bytes %s\n",MAX_LINE_PER_FILE*sizeof(int));
return 1;
}

if((line_pointer[i]=malloc(MAX_LINE_PER_FILE*sizeof(char *)))==NULL)
{
printf("Unable to allocate %d bytes %s\n",MAX_LINE_PER_FILE*sizeof(char *));
return 1;
}

if(fread(buffer_input_file[i],input_file_size[i],1,input_file)==0)
{
printf("Unable to read input file: %s\n",input_file_name[i]);
return 1;
}

if(fclose(input_file)!=NULL)
{
printf("Unable to close input file: %s\n",input_file_name[i]);
return 1;
}
}

for(i = 0; i < N_INPUT_FILE; i++)
{
line_file = 0;
tmp2_buffer = tmp1_buffer = buffer_input_file[i];
tmp3_buffer = tmp1_buffer + input_file_size[i];

do
{
last_char = n_line_size = 0;
tmp4_buffer = tmp2_buffer;
while ((*tmp1_buffer != 0x0A) && (*tmp1_buffer != 0x0D) && (tmp1_buffer<tmp3_buffer))
{
if( (*tmp1_buffer == 0x20) || (*tmp1_buffer == 0x09) )
{
if( last_char == 1 )
{
last_char = 0;
*tmp2_buffer = 0x20;
tmp2_buffer++;
n_line_size++;
}
}
else
{
last_char = 1;
*tmp2_buffer = *tmp1_buffer;
tmp2_buffer++;
n_line_size++;
}
tmp1_buffer++;
}

tmp1_buffer++;
if(tmp1_buffer < tmp3_buffer)
{
if((*tmp1_buffer == 0x0A) || (*tmp1_buffer == 0x0D))
tmp1_buffer++;
}

if(n_line_size)
{
*(unsigned short *)tmp2_buffer = 0x0A0D;
tmp2_buffer += 2;
line_size[i][line_file] = n_line_size+2;
line_pointer[i][line_file] = tmp4_buffer;
line_file++;
}

} while (tmp1_buffer < tmp3_buffer);

line_per_file[i] = line_file;
}

if((output_file = fopen(argv[1], "wb")) == NULL)
{
printf("Unable to create output file: %s\n", argv[1]);
return 1;
}

if((buffer_output = malloc(BUFFER_OUTPUT_SIZE)) == NULL)
{
printf("Unable to allocate %d bytes %s\n", BUFFER_OUTPUT_SIZE);
return 1;
}

for(i = 0; i <N_SWAP_RAND_FILE; i++)
{
j = rand()%N_INPUT_FILE;
k = rand()%N_INPUT_FILE;
l = line_per_file[j];
line_per_file[j] = line_per_file[k];
line_per_file[k] = l;
n = line_pointer[j];
line_pointer[j] = line_pointer[k];
line_pointer[k] = n;
o = line_size[j];
line_size[j] = line_size[k];
line_size[k] = o;
}

for(i = 0; i < N_INPUT_FILE; i++)
{

for(j = 0; j < (line_per_file[i]*N_SWAP_PER_ELEMENT); j++)
{
k = rand()%line_per_file[i];
l = rand()%line_per_file[i];
m = line_pointer[i][k];
line_pointer[i][k] = line_pointer[i][l];
line_pointer[i][l] = m;
p = line_size[i][k];
line_size[i][k] = line_size[i][l];
line_size[i][l] = p;
}

tmp_line_per_file[i] = 0;
}

tmp_buffer_output = buffer_output;
while (1)
{
for(i = 0; i < N_INPUT_FILE; i++)
{
k = line_size[i][tmp_line_per_file[i]];
if(tmp_buffer_output + k < (buffer_output + BUFFER_OUTPUT_SIZE))
{
memcpy(tmp_buffer_output, line_pointer[i][tmp_line_per_file[i]], k);

if(*tmp_buffer_output == 0x00)
{
return 1;
}

tmp_buffer_output += k;
}
else
{
j = buffer_output + BUFFER_OUTPUT_SIZE - tmp_buffer_output;
memcpy(tmp_buffer_output, line_pointer[i][tmp_line_per_file[i]], j);

if(fwrite(buffer_output,BUFFER_OUTPUT_SIZE,1,output_file) == 0)
{
printf("Unable to write output file: %s\n", argv[1]);
return 1;
}

output_file_size--;
if(output_file_size == 0)
break;

tmp_buffer_output = buffer_output;
memcpy(tmp_buffer_output, line_pointer[i][tmp_line_per_file[i]], k - j);
tmp_buffer_output += k - j;
}

tmp_line_per_file[i]++;
if(tmp_line_per_file[i] == line_per_file[i])
tmp_line_per_file[i] = 0;
}

if(output_file_size == 0)
break;
}

if(fclose(output_file) != NULL)
{
printf("Unable to close output file: %s\n",argv[1]);
return 1;
}

for(i = 0; i < N_INPUT_FILE; i++)
{
free(buffer_input_file[i]);
free(line_size[i]);
free(line_pointer[i]);
}
free(buffer_output);

return 0;
}


;)

Vincenzo1968
02-02-2013, 10:53
Quindi ricapitolando:

1) bisogna usare tutti i files
2) bisogna usare almeno 1 volta tutte le righe di tutti i files

Se il vincolo 2 è vero, è inefficiente scegliere le righe a caso :p.

PS: in effetti, si possono prima permutare le linee di tutti files e andare sequenzialmente scegliendo a caso il file da cui attingere.

Vedi post precedente. L'avevo scritto prima di leggere questo tuo ultimo.
Si, il vincolo 2 è vero.

WarDuck
02-02-2013, 10:59
Beh, vediamo se riesco a battere repne :D.

Vincenzo1968
02-02-2013, 11:04
Beh, vediamo se riesco a battere repne :D.

Praticamente lei ha spiegato che è più veloce perché utilizza blocchi da 16 MB.
Io nel mio utilizzo blocchi da 4Kb. Ho provato ad aumentare le dimensioni del blocco ma ottengo tempi uguali o addirittura peggiori. :confused:

Senti maaaaaa la domandina su uint64_t e printf che ho posto prima? ne sai qualcosa? Perché non riesco a utilizzare uint64_t con printf?

WarDuck
02-02-2013, 11:08
Praticamente lei ha spiegato che è più veloce perché utilizza blocchi da 16 MB.
Io nel mio utilizzo blocchi da 4Kb. Ho provato ad aumentare le dimensioni del blocco ma ottengo tempi uguali o addirittura peggiori. :confused:

Senti maaaaaa la domandina su uint64_t e printf che ho posto prima? ne sai qualcosa? Perché non riesco a utilizzare uint64_t con printf?

E' molto strano, uint64_t dovrebbe essere proprio unsigned long long... dopodiché dovrei rivedermi il formato, è da un po' che non uso i modificatori della printf :D.

Vincenzo1968
02-02-2013, 11:11
E' molto strano, uint64_t dovrebbe essere proprio unsigned long long... dopodiché dovrei rivedermi il formato, è da un po' che non uso i modificatori della printf :D.

Mo ti posto qualche screenshot. ;)

Comunque il tipo long long è standard giusto? Non mi debbo preoccupare per l'utilizzo del mio codice con compilatori diversi da GCC e Visual Strudio? Giusto? :confused: (se non è giusto mi metto a urlare).

:D

Vincenzo1968
02-02-2013, 11:19
Ecco intanto che succede se compilo con GCC su Linux:


vincenzo@Ubuntu12-10-AMD64:~/Contest19/Vincenzo1968$ gcc -O3 provauint64.c -o prova
provauint64.c: In function ‘main’:
provauint64.c:272:2: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 2 has type ‘uint64_t’ [-Wformat]



typedef struct tagFindRec
{
uint64_t countChars;
int countRows;
int maxRowLenght;
int countWords;
int maxWordLenght;
char szLongerWord[1000];
} FindRec;

...
...
...

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");


EDIT:
Ah no, me lo stampa correttamente, nonostante il warning:

http://img255.imageshack.us/img255/8624/uint64.jpg

Debbo provare su Windows/Visual Studio.

WarDuck
02-02-2013, 11:39
Hai incluso <stdint.h> ?

kwb
02-02-2013, 11:53
Scusate, ho provato wc con uno dei file di testo:

wc -m del_tr_t.txt
wc: del_tr_t.txt: Illegal byte sequence
152952 del_tr_t.txt


Cosa vuol dire? Me li ha contati giusti i caratteri o no? :stordita:
Se non funziona nemmeno wc non so come fare a capire se c'ho preso col programma...

Vincenzo1968
02-02-2013, 11:53
Si, l'ho incluso <stdint.h>.

Il warning nella printf si può eliminare con un casting:


printf("Il file \"%s\" contiene %llu righe.\n", argv[1], (unsigned long long)myFindRec.countRows);


Più tardi lo provo su Visual Studio.

Vincenzo1968
02-02-2013, 11:56
Scusate, ho provato wc con uno dei file di testo:

wc -m del_tr_t.txt
wc: del_tr_t.txt: Illegal byte sequence
152952 del_tr_t.txt


Cosa vuol dire? Me li ha contati giusti i caratteri o no? :stordita:
Se non funziona nemmeno wc non so come fare a capire se c'ho preso col programma...

Ci sarà qualche carattere strampalato nel file "del_tr_t.txt".
Ragazzi, non è colpa mia. Io i file li ho scaricati da liberliber.

Prova con un altro file. Magari createne uno tu di poche righe. ;)

Per esempio:

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
02-02-2013, 12:07
Da me comunque non ottengo l'errore:


AMD64:~/Contest19/Vincenzo1968/All$ time wc -m -w del_tr_t.txt
24503 151732 del_tr_t.txt

real 0m0.014s
user 0m0.012s
sys 0m0.000s

kwb
02-02-2013, 12:08
Inoltre, per il conto della lunghezza della riga, siccome ognuna è terminata da un \n, quest'ultimo va contato?

Vincenzo1968
02-02-2013, 12:21
Inoltre, per il conto della lunghezza della riga, siccome ognuna è terminata da un \n, quest'ultimo va contato?

Io l'ho contato. Forse è per questo che il mio programma fornisce un numero più alto di caratteri rispetto a wc.
Al limite fregatene del numero di caratteri. L'importante è che il programma stampi:

- Numero di righe.
- Quant'è lunga la riga più lunga.
- Numero di parole.
- Quant'è lunga la parola più lunga.
- Una delle parole più lunghe(la prima che trovi, o l'ultima, o una di mezzo).

Le ultime due features non sono presenti in wc. È una cosa nostra. ;)

EDIT:
Per esempio:

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.


Ecco l'output del mio programma:
http://img217.imageshack.us/img217/5444/c19b02outputfilepiccolo.jpg

Vincenzo1968
02-02-2013, 14:26
Mi accingo a sviluppare il punto B.1 in Ruby. Utilizzerò il cosiddetto Indice Invertito:

http://en.wikipedia.org/wiki/Inverted_index

Applications

The inverted index data structure is a central component
of a typical search engine indexing algorithm.
A goal of a search engine implementation is to optimize
the speed of the query: find the documents where word X occurs.
Once a forward index is developed, which stores lists of words
per document, it is next inverted to develop an inverted index.
Querying the forward index would require sequential iteration
through each document and to each word to verify a matching document.
The time, memory, and processing resources to perform such a query
are not always technically realistic.
Instead of listing the words per document in the forward index,
the inverted index data structure is developed which lists the
documents per word.

...

In bioinformatics, inverted indexes are very important in the
sequence assembly of short fragments of sequenced DNA.
One way to find the source of a fragment is to search for it against
a reference DNA sequence. A small number of mismatches (due to
differences between the sequenced DNA and reference DNA, or errors)
can be accounted for by dividing the fragment into smaller fragments—at
least one subfragment is likely to match the reference DNA sequence.
The matching requires constructing an inverted index of all substrings
of a certain length from the reference DNA sequence.
Since the human DNA contains more than 3 billion base pairs, and we need
to store a DNA substring for every index,and a 32-bit integer for index
itself, the storage requirement for such an inverted index would probably
be in the tens of gigabytes.


;)

Bioinformatics: vedi Contest 4 (http://www.hwupgrade.it/forum/showthread.php?t=1791293).

Vincenzo1968
02-02-2013, 14:51
Mi accingo anche ad installare Sphinx:

http://sphinxsearch.com/docs/current.html

Fortunatamente è in C++ :D

WarDuck
02-02-2013, 16:18
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