Newsgroup: it.comp.programmare
Titolo: Contatore caratteri

Tre giorni fa ho dovuto scrivere qualche riga di codice per contare i
caratteri contenuti in un file (tutti, anche i newline) e stampare a video
il risultato. Mi sono incuriosito...
Mi piacerebbe vedere qualche versione nei vari linguaggi, giusto per
vedere con quale linguaggio si riesce ad implementare il contatore con il
minor numero di istruzioni. 
Potete spendere 1 minuto per scrivere qualche riga, nel linguaggio che
preferite?
Con due sole istruzioni si potra` fare?
Ciao,
-- 
Marco

 il risultato. Mi sono incuriosito...
Dimenticavo...
Questa e` la mia versione in Python:
count = 0
for line in open('myfile').readlines() : count += len(line) 
print 'Numero caratteri:', count
Ciao,
-- 
Marco

 Ciao,
Saluti,
David
-- 
         Linux Registered User #334216
Get FireFox! >> 
http://snipurl.com/gofoxygo/
 <<
Blog         >>  
http://www.hanskalabs.net/
  <<
Staff        >> 
http://www.debianizzati.org/
 <<

 print 'Numero caratteri:', count
Mi scuso con tutti i pythonisti per la mia ignoranza :-$
print len(open('myfile').read())
Anche con python in una riga.
-- 
Marco

Marco ha scritto:

Una riga anche in shell:
wc -c <nomefile>
Sulla falsariga del phyton e altri linguaggi simili, si potrebbe 
scrivere in una sola riga anche in C, tuttavia, quando un programma 
compilato si prende la briga di aprire un file, e' buona programmazione 
testare sempre il valore di ritorno della open() e, se questa fallisce, 
non procedere oltre.
Nel caso di cui sopra, in phyton, se il file 'myfile' non esistesse, la 
open() non tornerebbe alcun oggetto di tipo file, e il successivo metodo 
  read() produrrebbe risultati inaspettati, come ogni volta che si ha a 
che fare con puntatori non inizializzati correttamente.
Ad ogni modo, senza voler necessariamente aprire il file e leggerlo 
tutto per contare i caratteri, esiste sempre l'alternativa di chiedere 
l'informazione di lunghezza del file al filesystem con la funzione 
stat() che il file neanche lo apre, ma restituisce una bella struttura 
che contiene tutte le informazioni relative al file, tra cui la lunghezza.
Ogni linguaggio degno di questo nome ha una implementazione della stat()

 Ogni linguaggio degno di questo nome ha una implementazione della stat()
Si anche Python, os.stat()
-- 
Lawrence, 
oluyede.org
 - 
neropercaso.it
"It is difficult to get a man to understand 
something when his salary depends on not
understanding it" - Upton Sinclair

 <?= strlen(file_get_contents($argv[1])) ?>
Facciamo una cosa, visto che ho appurato che sicuramente puo` essere fatto
con una sola istruzione. Consideriamo il programmino scritto nel
linguaggio x che conta il numero di caratteri di cui esso stesso e`
composto (cosi` non ci sono ambiguita`). 
Per intenderci, in python (da shell):
marco@ubuttu:~$ vi f
marco@ubuttu:~$ cat f
print len(open('f').read())
marco@ubuttu:~$ python f
28
Invito i pythonisti a trovare una soluzione piu` breve ed i non pythonisti
a proporre la loro.
Ciao,
-- 
Marco

 a proporre la loro.
Comincia a piacermi sta sfida :D
neo@matrix:~/test$ nano conta.php
neo@matrix:~/test$ cat conta.php
<?=strlen(file_get_contents($argv[0]))."\n"?>
neo@matrix:~/test$ php -f conta.php
46
neo@matrix:~/test$ mv conta.php pippo.php
neo@matrix:~/test$ php -f pippo.php
46
neo@matrix:~/test$
Anche se cambia nome, legge sempre se stesso. :)
È proprio il minimo che riesco a fare...
In python, la mia "soluzione generale" è:
neo@matrix:~/test$ nano pyth
neo@matrix:~/test$ python pyth
47
neo@matrix:~/test$ cat pyth
import sys
print len(open(sys.argv[0]).read())
neo@matrix:~/test$
ovviamente si perde molto per quell'"import sys"...
In BASH:
neo@matrix:~/test$ nano shell
neo@matrix:~/test$ cat shell
cat $0|wc -c
neo@matrix:~/test$ bash shell
13
neo@matrix:~/test$
Ovviamente si potrebbe usare il più breve "wc -c $0", ma il risultato
non sarebbe "9", sarebbe "9 bash"... dato che vogliamo solo il numero,
il codice è quello. (O, in alternativa, wc -c $0|awk '{print $1}'... ma
è molto più lungo :D)


 a proporre la loro.
Non ho capito se state facendo una gara per sta cosa :-D
rhymes@groove ~ % python -c "import sys; print len(sys.stdin.read())" <
file.txt
587


 587
No, non era questo... :)
Dev'essere un codice che conta i caratteri del codice stesso... :P


 Anche se cambia nome, legge sempre se stesso. :)
Allora, vediamo se questa va bene. Il nome del file deve essere immesso
dall'utente, quindi credo che come generalita` possa andare, visto che
puoi usare il nome che ti pare per il programma ed il codice non cambia:
marco@ubuttu:~$ cat myfile
print len(open(raw_input()).read())
marco@ubuttu:~$ python myfile
myfile
36
Puo` andare? :-P
-- 
Marco

 Non ho capito se state facendo una gara per sta cosa :-D
No, inizialmente volevo vedere diversi modi di fare un compitino semplice
semplice in diversi linguaggi. 
Ora pero` sta diventando interessante, e si accettano sfide (tra linguaggi) :-) 
Pero` mi piacerebbe anche vedere l'implementazione in C e java (anche se
non anno speranza :-)), giusto per curiosita`. Se qualcuno puo`.
Ciao,
-- 
Marco

 Dev'essere un codice che conta i caratteri del codice stesso... :P
Vabbé allora è già stato fatto in una sola linea un paio di post fa.


 non anno speranza :-))
Ma perchè questa corsa a chi ce l'ha più corto vi appassiona tanto? Spero
che non vi salti in mente di considerare la bontà di un linguaggio da
quanto possa essere compatto il suo codice sorgente. La compatezza non è ne
segno di velocità dell'eseguibile ne indice di leggibilità. Per esempio,
parlando in generale, un codice C o pascal di 15 righe potrebbe essere 50
volte più veloce del corrispondente codice python di una riga.

 Puo` andare? :-P
No :D
Comunque ecco una mia versione in C... probabilmente sarà da migliorare
(MOLTO probabilmente :P):
neo@matrix:~/test$ nano csrc.c
neo@matrix:~/test$ gcc -o c csrc.c
neo@matrix:~/test$ ./c csrc.c
172
neo@matrix:~/test$
#include<stdio.h>
int main(int argc,char *argv[]){FILE *f;int n=0;int
c;f=fopen(argv[1],"r");while(1){if((c=fgetc(f))==EOF)break;++n;}printf("%d\n",n);fclose(f);return;}
Ovviamente, 174 caratteri togliendo tutte le indentazioni, gli spazi
inutili, le parentesi inutili, ... :) (la leggibilità... bleah :D)
Inoltre, questo legge _qualunque_ file passato da riga di comando (mi
contraddico con quanto detto sopra) perché, ovviamente... mica può
leggere il compilato :P...
Cheers,
David
P.S.: sarebbe bello pubblicare il tutto su una bella paginetta sul web... :)


 di una riga.
D'accordissimo su questo.
La sfida è, almeno per me, raggiungere uno stesso scopo con il minor
numero di righe di codice possibile. Finora, questa è la classifica
(secondo i dati che ho, eh):
1) PHP: 46
2) Python: 47
3) C: 172
(per il python ho usato la versione "generale"... dove l'utente non deve
inserire nulla... per il C, vedi ragionamento sull'altra "biforcazione"
del thread, non può leggere sè stesso perché è compilato)


 3) C: 172
Correggo:
1) Bash: 13
...


David Paleino ha scritto:

Nuova implementazione in C:


 ...
Partito il post per sbaglio, sorry. (grr, l'alt+invio di thunderbird)
Dicevo... nuova implementazione in C:
#include<stdio.h>
main(int argc,char *argv[]){FILE
*f=fopen(argv[1],"r");fseek(f,0,SEEK_END);printf("%d\n",ftell(f));}
(dimenticate il return, il tipo di main, e la chiusura del file. LOL).
neo@matrix:~/test/count$ ./c2 csrc2.c
119
neo@matrix:~/test/count$
Cheers,
David
(chi fa meglio? :D)


 1) Bash: 13
Correggo: python 33! :-)
marco@ubuttu:~$ cat myfile
print len(open(__file__).read())
marco@ubuttu:~$ python myfile
33
Ciao,
-- 
Marco

 volte più veloce del corrispondente codice python di una riga.
Potrebbe, certo. Specialmente senza Psyco ;-)
Ciao,
-- 
Marco

 Ciao,
Saluti,


 David
P.S.: sembra che partecipi solo io ormai... :'(


 (chi fa meglio? :D)
Usando open() e lseek() invece di fopen e fseek, si puo' risparmiare la
ftell() visto che la lseek() ritorna essa stessa la nuova posizione del
file.
Inoltre al posto di SEEK_END si puo' tranquillamente scrivere 2 e quindi
evitare di includere l'header.
(Che schifo...)
Potrebbe uscire una cosa del genere (non ho qui il compilatore e non
posso testare)
main(int c,char *v){int f=open(v[1],0);printf("%d\n",lseek(f,0,2));}
68 caratteri, con beneficio di verifica.
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 68 caratteri, con beneficio di verifica.
neo@matrix:~/test/count$ gcc -o c3 csrc3.c
csrc3.c: In function ‘main’:
csrc3.c:1: warning: incompatible implicit declaration of built-in
function ‘printf’
neo@matrix:~/test/count$ ./c3 csrc3.c
71
neo@matrix:~/test/count$
Una nuova implementazione in Java (98):
class A{public static void main(String[]a){System.out.println(new
java.io.File(a[0]).length());}}
Nuova classifica: (*lol*)
1) Bash: 13
2) Python: 33
3) PHP: 38
4) C: 71
5) Java: 98


 71
Si, perche' sei andato a capo dopo l'ultima graffa.
Non serve andare a capo!


 Non serve andare a capo!
Lo so... è nano che mi aggiunge un \n alla fine del file. :@
(la classifica non cambia comunque... ;) )
Cheers,
David


Marco wrote:
Nuova versione python (sulla scia di lseek :-)):
marco@ubuttu:~$ cat myfile
print open(__file__,'a').tell()
marco@ubuttu:~$ python myfile
32
Classifica aggiornata:
1) BASH (13 caratteri):
cat $0|wc -c
2) Python (32 caratteri):
print open(__file__,'a').tell()
3) PHP (38 caratteri):
<?$a=stat($argv[0]);echo $a[7]."\n"?>
4) C (69 caratteri):
main(int c,char **v){int f=open(v[1],0);printf("%d\n",lseek(f,0,2));}
5) Java (98 caratteri):
class A{public static void main(String[]a){System.out.println(new
java.io.File(a[0]).length());}}
Ciao,
-- 
Marco

 Ciao,
Saluti,
David
P.S.: m'è piaciuta questa "gara"... ;)


Io Proporrei una soluzione del genere:
#include <cstdio>
main(){printf("38");}
mi conta esattamente il numero dei caratteri ed è indipendente dal
nome del programma. Che ne dite?  :-)
David Paleino ha scritto:


 nome del programma. Che ne dite?  :-)
Che conta male (in verita` non conta ma stampa e basta) :-D
Ci sono 40 caratteri ;-)
Ciao,
-- 
Marco

Marco ha scritto:

*LOL* (ad entrambi :D)


evitare di includere l'header.
L'header tocca includerlo per il prototipo delle funzioni.  Inoltre un
codice che non specifichi "int" come valore di ritorno di main() non č
piů legale.

 (la classifica non cambia comunque... ;) )
Per amor di precisione, ci sono linguaggi che pretendono un fine linea 
alla fine della linea, altri, come il C che invece non lo pretendono.
Considerando i minimi termini che stiamo raggiungendo, un newline in 
piu' o in meno e' piu' dell'1% del codice, quindi parecchio rilevante.

 piů legale.
A dire il vero, la necessita' dell'header stava nella definizione delle 
costanti, che se non sono definite il compilatore da' errore.
La mancanza di prototipi e di definizioni del valore di ritorno, 
producono solo dei warning.
Non oso passare quel codice al lint, altrimenti mi sputerebbe in faccia 
in ascii art.

 piu' o in meno e' piu' dell'1% del codice, quindi parecchio rilevante.
Eheh è vero! :)


 in ascii art.
Cosa disegnerebbe esattamente? Che forma ha uno "sputo"? :D
Cheers,
David


producono solo dei warning.
No. La definizione del valore di ritorno è un *obbligo* in C.
Studia l'ultimo standard ISO/IEC.

 di alcuno standard ;)
17 caratteri:
int main(){x();}
x e` una funzione non standard che stampa la lunghezza del file.
        Mauro

         Mauro


 smiley, andrebbero interpretati...).
Anche la mia soluzione era ironica, non voglio creare flame.
Pero` se si vuole un gioco che sia "giocabile", ci vogliono delle
regole precise.  
Di solito in questi giochi i programmi devono essere validi e
rispettare le regole del linguaggio, e non possono usare
funzioni/librerie/moduli esterni.  Non basta fare qualcosa che in
condizioni particolari puo` essere compilato da alcuni compilatori.
Se quando fa comodo si decide di ignorare le regole del linguaggio o
di usare funzioni esterne, allora il limite non dipende piu` dal
linguaggio, ma si possono creare programmi corti a piacere a seconda
di quanto ci si spinge oltre.
        Mauro

         Mauro
MTC,


"funziona" e "è il più corto possibile". :)
"Funziona" per un programma C significa che è compilabile sulla tua e
sulla mia piattaforma, non solo sulla tua o solo sulla mia, altrimenti
funziona sol sulla tua o solo sulla mia, indi, in generale, non
funziona. "Funziona", quindi, significa rispettare lo standard.
Non c'è, come vedi, alcun flame, solo dovute precisazioni ;-)
Anche perché altrimenti è correttissimo quanto afferma Mauro.
Vedendola in termini matematici: per ogni problema X da te citato,
sulla piattaforma Y ci sarà sempre la funzione non standard z() che
risolverà il problema X alla perfezione ;-).

 risolverà il problema X alla perfezione ;-).
Ok.
Torniamo alla questione originaria... avete altre implementazioni? :)
Cheers,


i386", cosě siamo tutti a posto :-D
No, non dico questo. Dico l'esatto contrario: non ha senso specificare
una determinata piattaforma, visto che esiste lo standard.

 Torniamo alla questione originaria... avete altre implementazioni? :)
Due succinte implementazioni in C++ standard che utilizzano la libreria 
degli stream. Il seguente programma stampa la lunghezza in byte del file 
passato come parametro:
#include <iostream>
#include <fstream>
int 
main(int,char**v){std::cout<<std::ifstream(v[1],std::ios::binary).seekg(0,std::ios::end).tellg();}
Il seguente programma si limita a ritornare la lunghezza al programma 
chiamante (era stato chiesto di calcolare, non di stampare):
#include <fstream>
int main(int,char**v){return 
std::ifstream(v[1],std::ios::binary).seekg(0,std::ios::end).tellg();}
Dopo averlo eseguito, da CMD, si può digitare: echo %errorlevel%
-- 
     Carlo Milanesi
 
http://digilander.libero.it/carlmila

 chiamante (era stato chiesto di calcolare, non di stampare): 
Si, hai ragione, nella seconda specifica mi son dimenticato di indicare
che il risultato deve essere stampato a video. 
Era indicato nel post in alto alla gerarchia :-P
Ciao,
-- 
Marco