Newsgroup: it.comp.os.linux.iniziare
Titolo: come eseguire velocemente dei calcoli da testo formattato

  22925	 22918	 22833	 22791	 22798
  22835	 22827	 22850	 22829	 22866
  22856	 22923	 22927	 22864	 22864
  22923	 22857	 22888	 22850	 22815
  22859	 22886	 22873	 22886	 22894
 
Devo calcolare i totali per colonna eliminando per ogni colonna il nr 
più alto e più basso.
C'è qualche comando per farlo oppure devo fare uno script? Se devo fare 
uno script mi dareste un testo di esempio?
 
ciao e grazie


Personalmente lo farei con uno script perl
Per un esempio dovrei costruire un programma, cosa che adesso non ho 
tempo ne voglia di fare
Comunque se conosci un linguaggio di programmazione non e' difficile
Qualcosa lo puoi fare anche con openoffice, eliminando a manina i numeri 
che non servono
 
 

 che non servono
Importi con OpenOffice Calc;
Ordini le righe discendenti, quindi elimini la riga 1
Ordini poi le righe ascendenti, ed elimini ancora la riga 1
Poi fai i totali
 


scusa ma non uso openoffice, volevo imparare qualcosa di bash o del 
sistema operativo o di regexp al limite.
 
ciao e grazie


Allora vai di perl
hai la potenza della bash unita al  C e all' object oriented, tutto in 
un linguaggio solo
 
 

 un linguaggio solo
 
Scusa ma mi sai indicare un manuale in italiano molto molto essenziale,
anzi soprattutto che faccia solo esempi ovvero quasi niente teoria?
 
Perche' io ad esempio il problema di Enrico lo farei con awk, ma so che
perl e' ancora meglio.
 
 
-- 
Tanti saluti
 


http://www.perl.it/modern_perl/modern_perl.pdf
 
 
Scritto molto bene
 

 Scritto molto bene
 
Ottimo grazie!
 
-- 
Tanti saluti
 

 perl e' ancora meglio.
 
Io invece ho voluto provare proprio con awk che conosco poco e mi pare
funzioni correttamente ma come puoi vedere, nella parte finale dello
script relativa alle somme finali, sarebbe il caso di legare tutto in
un ciclo for, solo che ho provato ma non ci sono riuscito.
 
#!/bin/bash
## "sum.sh" 
## Autore: M_M
## 25/11/2014  08:52:32
 
: <<BLOCCOCOMMENTO
22925	22918	22833	22791	22798
22835	22827	22850	22829	22866
22856	22923	22927	22864	22864
22923	22857	22888	22850	22815
22859	22886	22873	22886	22894
BLOCCOCOMMENTO
 
# il nome di questo script bash:
nomescript=$(basename $0)
 
# il nome del file con una tabella di cifre su 5 righe e 5 colonne
f="tabella"
 
# Cancella i file temporanei quando lo script termina o viene interrotto
trap 'unlink ${FILE_TEMP_1}; unlink ${FILE_TEMP_2}; exit'  0   1    2        3    15
# ==>                                            Segnali:  HUP INT  (Ctrl-C) QUIT TERM
 
umask 177 # Per essere certi che i file temporanei non siano leggibili dal mondo intero
 
FILE_TEMP_1=$(mktemp)
FILE_TEMP_2=$(mktemp)
 
clear
echo "****************************************************"
echo "* Lo script '$nomescript' legge nel file '$f' e    *"
echo "* dopo aver eliminato in ogni colonna il nr piu'   *"
echo "* alto e piu' basso, calcola i totali per colonna. *"
echo "****************************************************"
echo
 
echo "La tabella originale nel file "$f":"
echo
cat $f
echo
 
sort -n $f -o $FILE_TEMP_1
echo -e "La tabella con i valori di ogni colonna\nordinati in modo crescente:"
cat $FILE_TEMP_1
echo
#echo $(awk '{print $1}' $FILE_TEMP_1)
echo
echo "la tabella ordinata senza i valori max e min:"
echo
sed '3,5!d' $FILE_TEMP_1 >> $FILE_TEMP_2
cat $FILE_TEMP_2
echo
 
echo
echo "Somma colonna 1 senza i valori max e min:"
echo $(awk '{total += $1} END {print total}' $FILE_TEMP_2)
echo
echo "Somma colonna 2 senza i valori max e min:"
echo $(awk '{total += $2} END {print total}' $FILE_TEMP_2)
echo
echo "Somma colonna 3 senza i valori max e min:"
echo $(awk '{total += $3} END {print total}' $FILE_TEMP_2)
echo
echo "Somma colonna 4 senza i valori max e min:"
echo $(awk '{total += $4} END {print total}' $FILE_TEMP_2)
echo
echo "Somma colonna 5 senza i valori max e min:"
echo $(awk '{total += $5} END {print total}' $FILE_TEMP_2)
echo
 
#sum=`(sed 's/^/x+=/' $FILE_TEMP1; echo x) | bc`
 
echo
echo "Premere il tasto [Invio] per chiudere."
read dummy
 
 
 

 un ciclo for, solo che ho provato ma non ci sono riuscito.
 
Lo script che hai fatto e' interessante e lo guardero' in seguito. Pero'
per il problema di Enrico per prima cosa e' da sapere se:
1) le colonne sono in numero determinato, in questo caso 5 ?
2) se ogni colonna ha o no un numero fisso e dato di righe.
 
La 2 poco importa, pero' puo' essere comoda; la 1 serve giusto per
fissare l'indice del ciclo for. Io a mente pensavo:
 
for j in...; do
awk '{print $j}' origine | sort > /tmp/COLONNE/$j
 
(Tra parentesi: mi sa che awk puo' darlo gia' ordinato senza bisogno
d'invocare sort).
Poi awk (o anche sed mi pare) so che puo' cancellare la prima e l'ultima
riga. Quindi per la somma di ogni $j devi aver scritto gia' tu il
comando awk (fa anche seni, esponenziali...).
Probabilmente non c'e' neppure bisogno di parcheggiare le colonne nei
file, si puo' fare in un colpo solo ridirezionando con le pipe.
 
P.S. No... vedo ora che hai messo bc per la somma, e sed per tagliare le
righe, va be' poi con calma lo guardo.
 
-- 
Tanti saluti
 


grazie delle risposte, ora devo con calma capire cosa fa lo script, per 
rispondere alla domanda nr 2, qui  5 colonne di 5 risultati lunghi 5 
cifre sempre.
 
di nuovo grazie e buon linux!
 


piu che awk direi un miscuglio tra awk e shell
 

 di nuovo grazie e buon linux!
 
Grazie e altrettanto!
 
-- 
Tanti saluti
 

 piu che awk direi un miscuglio tra awk e shell
 
Interessante questo che dici, cioe' si puo' usare awk anche senza shell?
 
-- 
Tanti saluti
 


 
dipende da quello che si vuole fare
awk non è general purpose come perl,c,c++,java,ecc..
 

 awk '{print $j}' origine | sort > /tmp/COLONNE/$j
 
E` proprio quello che in bash non riesco a fare.
Se uso '$j' e` come se scrivessi
awk '{print 1}' origine
mentre funziona con
awk '{print $1}' origine
 
Cmq lo script precedente aveva degli errori; forse questo e` un po'
meglio ma sempre senza il ciclo for :-(
 
 
#!/bin/bash
## "sum.sh" 
## Autore: M_M
## 25/11/2014  12:52:32
 
: <<BLOCCOCOMMENTO
  22925	 22918	 22833	 22791	 22798
  22835	 22827	 22850	 22829	 22866
  22856	 22923	 22927	 22864	 22864
  22923	 22857	 22888	 22850	 22815
  22859	 22886	 22873	 22886	 22894
BLOCCOCOMMENTO
 
# il nome del file con una tabella di cifre su 5 righe e 5 colonne
f="tabella"
 
# il nome di questo script bash:
nomescript=$(basename $0)
 
BOLD=$(tput bold)
PLAIN=$(tput sgr0)
 
# Cancella i file temporanei quando lo script termina o viene interrotto
trap 'unlink ${FILE_TEMP_1}; unlink ${FILE_TEMP_2}; exit'  0   1    2        3    15
# ==>                                            Segnali:  HUP INT  (Ctrl-C) QUIT TERM
 
umask 177 # Per essere certi che i file temporanei non siano leggibili dal mondo intero
 
FILE_TEMP_1=$(mktemp)
FILE_TEMP_2=$(mktemp)
 
function somma () {
    sort -n $FILE_TEMP_1 -o $FILE_TEMP_2
    echo
    echo "Colonna $1 con valori ordinati in modo crescente:"
    cat $FILE_TEMP_2
    echo
    > $FILE_TEMP_1
    echo "Colonna $1 senza i valori max e min:"
    echo
    sed '3,5!d' $FILE_TEMP_2 >> $FILE_TEMP_1
    cat $FILE_TEMP_1
    echo
    echo "${BOLD}Somma colonna $1 senza i valori max e min:${PLAIN}"
    echo
    echo $(awk '{total += $1} END {print total}' $FILE_TEMP_1)
    echo
}
 
function digitanumcolonna () {
    echo
    echo -n "Digitare il numero della colonna [ 0 per uscire ]: "
    read opzione_n
    case "$opzione_n" in
 
	"1") > $FILE_TEMP_1
	     awk '{print $1}' $f >> $FILE_TEMP_1
	     somma 1
	     ;;
 
	"2") > $FILE_TEMP_1
	     awk '{print $2}' $f >> $FILE_TEMP_1
	     somma 2 
	     ;;
 
	"3") > $FILE_TEMP_1
	     awk '{print $3}' $f >> $FILE_TEMP_1
	     somma 3
	     ;;
 
	"4") > $FILE_TEMP_1
	     awk '{print $4}' $f >> $FILE_TEMP_1
	     somma 4
	     ;;
 
	"5") > $FILE_TEMP_1
	     awk '{print $5}' $f >> $FILE_TEMP_1
	     somma 5
	     ;;
 
	"0") exit 0
	     ;;
 
	  *) echo
	     echo "${BOLD}Errore: Opzione non valida.${PLAIN}"
	     ;;
    esac
}
 
clear
echo "****************************************************"
echo "* Lo script '$nomescript' legge nel file '$f' e    *"
echo "* dopo aver eliminato in ogni colonna il nr piu'   *"
echo "* alto e piu' basso, calcola i totali per colonna. *"
echo "****************************************************"
echo
 
 
 
while [ 1 ]   # Ciclo infinito.
do
    echo
    echo "La tabella originale nel file "$f":"
    echo
    cat $f
    echo
    echo -n "Vuoi calcolare la somma di una colonna? [Y/n] "
    read a
    if [[ "$a" == "Y" || "$a" == "y" || "$a" = "" ]]; then
	digitanumcolonna
    else
	exit 0
    fi  
done
 

 meglio ma sempre senza il ciclo for :-(
 
Poi me lo guardo, mi ci vuole tempo perche' devo ancora assimilare il
metodo dell'assegnazione di variabili che usi. Inoltre devo assumere
come modello-skel di script i commenti e cose varie che usi metterci.
 
-- 
Tanti saluti
 

 meglio ma sempre senza il ciclo for :-(
 
Forse devi cambiarlo, mettendoci il ciclo for (*), percio' allora
aspetto un po' a guardarlo.
 
------
(*) Puoi generalizzarlo a $1 colonne cosi':
 
========
#!/bin/bash
 
for j in $(seq $1); do
awk "{print \$$j}" origine | sort > /tmp/COLONNE/$j
done
======
 
-- 
Tanti saluti
 


non ho seguito il thread, ma mi pare che nessuno abbia menzionato 
python che ti permetterebbe di risolvere il problema con con poche 
righe di codice molto meglio degli altri linguaggi suggeriti
 
BTW i dati sono in un file?
 
-- 
bye
!(!1|1)
 

 BTW i dati sono in un file?
 
Si'.
 
-- 
Tanti saluti
 

 Scusa una domanda-lampo: sta guardando perl, non credo che phyton possa
 
sto, non sta.
 
-- 
Tanti saluti
 


Tecnicamente, per questo tipo di problemi,
cose come "octave", cioe` m script, sono
la soluzione.
 
a=[22925     22918     22833     22791     22798
   22835     22827     22850     22829     22866
   22856     22923     22927     22864     22864
   22923     22857     22888     22850     22815
   22859     22886     22873     22886     22894];
b=sort(a);
c=sum(b(2:end-1,:));
 
Che poi, si puo` accorciare (solo "octave") con:
 
a=[...]
c=sum(sort(a)(2:end-1,:));
 
Tra l'altro questo scala bene con matrici larghe.
 
Poi, ovviamente, puo` sembrare di spostare un
mucchietto di sabbia con il buldozer...
Non e` che gli altri linguaggi di programmazione,
pero`, siano meglio in questo senso.
 
bye,
 
-- 
 
piergiorgio


anche in perl si fa una cosa simile
piu o meno con lo stesso numero di righe di octave (che comunque non 
conosco)
 

 done
 
Ahaaah! proteggevo il $ di awk ma le virgolette invece di apici non le
mettevo ...
 
Sarebbe bello mettere tutto in una nuova tabella ma ora sono stufo ..
 
 
#!/bin/bash
## "sum.sh" 
## Autore: M_M
## 25/11/2014  20:37:00
: <<BLOCCOCOMMENTO
  22925	 22918	 22833	 22791	 22798
  22835	 22827	 22850	 22829	 22866
  22856	 22923	 22927	 22864	 22864
  22923	 22857	 22888	 22850	 22815
  22859	 22886	 22873	 22886	 22894
BLOCCOCOMMENTO
# il nome del file con una tabella di cifre su 5 righe e 5 colonne
file_tabella="tabella.txt"
# il nome di questo script bash:
nomescript=$(basename $0)
BOLD=$(tput bold)
PLAIN=$(tput sgr0)
# Cancella i file temporanei quando lo script termina o viene interrotto
trap 'unlink ${FILE_TEMP_1}; unlink ${FILE_TEMP_2}; exit'  0   1    2        3    15
# ==>                                            Segnali:  HUP INT  (Ctrl-C) QUIT TERM
umask 177 # Per essere certi che i file temporanei non siano leggibili dal mondo intero
FILE_TEMP_1=$(mktemp)
FILE_TEMP_2=$(mktemp)
clear;
echo
echo "****************************************************"
echo "* Lo script '$nomescript' legge nel file '$file_tabella'"
echo "* e dopo aver eliminato in ogni colonna il nr piu'"
echo "* alto e piu' basso, calcola i totali per colonna."
echo "****************************************************"
echo
echo
echo "La tabella originale nel file "$file_tabella":"
echo
cat $file_tabella
for j in 1 2 3 4 5
do
    awk "{print \$$j}" $file_tabella | sort -n $1 >> $FILE_TEMP_1 ### Thank you Yoda!!!
    echo; echo "......................................................."; echo;
    echo "Colonna $j con valori ordinati in modo crescente:"
    cat $FILE_TEMP_1
    echo
    echo "Colonna $j senza i valori max e min:"
    echo
    sed '3,5!d' $FILE_TEMP_1 >> $FILE_TEMP_2
    cat $FILE_TEMP_2
    echo
    echo
    echo "${BOLD}Somma colonna $j senza i valori max e min:${PLAIN}"
    echo
    echo $(awk '{total += $1} END {print total}' $FILE_TEMP_2)
    > $FILE_TEMP_1
    > $FILE_TEMP_2
done
echo; echo "......................................................."; echo;
echo 
echo "${BOLD}Premere il tasto [Invio] per chiudere.${PLAIN}"
read dummy
 


Si, ma fammi vedere il programma in perl...
 
bye,
 
-- 
 
piergiorgio

Addi' 25 nov 2014, Piergiorgio Sartor scrive:

Si', se ci hai tempo sarebbe proprio interessante, se no tra qualche
giono ci provo io... o forse tra qualche mese.
;^)
 
-- 
Tanti saluti
 


e' simile:
my @a=(<valori>);
sum(sort(@a));
 
poi sum va costruita
 
 

 ... che conosco poco ...
 
Mettiamo i puntini sulle i, tu non conosci affatto AWK, al massimo 
sai vagamente che esiste una cosa chiamata AWK
 
cat somme.awk
 
#! /bin/gawk -f 
 
NR==1  {for (i=1;i<=NF;i++) 
          max[i] = $i
       }
NR==2  {for (i=1;i<=NF;i++) 
          if ($i <= max[i])
            min[i] = $i
          else  {
            min[i] = max[i]
            max[i] = $i 
          } 
       }
NR>=3  { for (i=1;i<=NF;i++)  
          if ($i < min[i] ) {
            somma[i] += min[i]
            min[i] = $i
          }
          else 
            if ($i <= max[i] )
              somma[i] += $i
            else {
              somma[i] += max[i]
              max[i] = $i
            }
       }   
END    {print "minimi"
        for (i in min) printf "%d ", min[i]
	printf "\n"
        print "massimi"
        for (i in max) printf "%d ", max[i]
	printf "\n"
        print "somme"
        for (i in somma) printf "%d ", somma[i]
	printf "\n"
       }
 
 
PS se una cosa del genere dovesse passare in produzione
io toglierei le inestazioni, che hanno solo un valore di debug,
Quindi:
 
....
END    { for (i in somma) printf "%d ", somma[i] ; printf "\n"  }
 
 
 

 la soluzione.
 
Tecnicamente MATLAB, R, Mathematica, octave, sono
strumenti più adatti in generale ma in questo caso particolare
NON È DETTO CHE LO SIANO, anzi non lo sono.
Ovviamente non sta al gruppo sindacare su questo ma all'autore
dell'OP che non ha detto cosa deve farci con questi dati, se 
non mi sbaglio.
E ancora, se Octave o MATLAB fossero adatti agli scopi del 
nostro sicuramente quegli non avrebbe postato affatto.
 
PS non siamo ridicoli, un thread così lungo su uno script che 
si può fare in dieci minuti a prescindere dal linguaggio adottato.
 
 

 poi sum va costruita
 
Cosa vuol dire che "sum va costruita"?
 
bye,
 
-- 
 
piergiorgio

 si può fare in dieci minuti a prescindere dal linguaggio adottato.
 
In dieci minuti?
 
In 30 secondi, semmai... :-)
 
bye,
 
-- 
 
piergiorgio


a volte una discussione apparentemente inutile è utile per chi non ne sa 
quanto te, non dico che capiti sempre ma le idee degli altri sono sempre 
buone a capire quello che stai facendo meglio soprattutto se non hai 
infarinatura sull'argomento.
Per esempio tu dai per scontato che uno sappia cosa siano, MATLAB R o 
Mathematica, ma io non so proprio di chestai parlando, tieni conto che 
questo forum è iniziare e ogni argomento nuovo su linux è un inizio.
 
ciao e grazie (a tutti) :)

 In 30 secondi, semmai...:-)
 
30 secondi? ma va sono così veloce che quando ho finito, ho qualche anno 
in meno di te. :)
 
ciao e buon linux!

 ho nolto tempo per questi linguaggi.
 
sono essenzialmente preferenze personali, ma python ha un enorme 
numero di librerie e permette di creare facilmente anche programmi 
gnome o qt/kde
 
comunque se cerchi con google "perl vs python" puoi trovare pareri 
molto più esaurienti del mio visto che da anni ormai programmo solo 
occasionalmente
 
-- 
bye
!(!1|1)
 

 ciao e buon linux!
 
 
-- 
 
piergiorgio

 unirmi a enoquick.
 
Per me e` solo cio` che copiando qua e la` riesco a fare in Bash :-/
 
Per risolvere il problema postato dall'opener piu` breve di cosi` non
riesco a farla:
 
#!/bin/bash
## "sumcol.sh" 
## Autore: M_M
## 26/11/2014  20:36:03
 
<<BLOCCOCOMMENTO
22925	22918	22833	22791	22798
22835	22827	22850	22829	22866
22856	22923	22927	22864	22864
22923	22857	22888	22850	22815
22859	22886	22873	22886	22894
BLOCCOCOMMENTO
 
file_tabella="tabella.txt"
for j in 1 2 3 4 5; do
sort -n $file_tabella | sed '2,4!d' | awk "{total += \$$j} END {print total}"
done
exit 0
 

 questo forum è iniziare e ogni argomento nuovo su linux è un inizio.
 
Mi hai frainteso. Anzi stai capovolgendo il mio pensiero. Nel post 
precedente io intendevo dire che tu non sicuramente non conoscevi 
questi pacchetti e che sicuramente non li avevi a disposizione perché
sono alquanto specialistici e quini non sono normalmente installati
e tranne Octave non sono liberi e sono abbastanza costosi. Quindi
suggerire questi pacchetti è una cosa abbastanza stupida e inutile.
Vabbè anche colpa mia che non sono stato troppo chiaro.
 

 
 
 
-- 
 
piergiorgio

 Vabbè anche colpa mia che non sono stato troppo chiaro.
 
Non solo non sei chiaro, ma non hai neanche
riflettuto troppo sulla questione in generale.
 
Era ben scritto, nel mio post, che usare Octave e`
come usare un buldozer per spianare un mucchietto
di sabbia.
 
D'altro canto, nessuno si e` sognato che con quel
tool sono esattamente 2 linee di codice.
Incluso il load() della matrice da un file di testo.
 
Il che dovrebbe dimostrare come una classe di problemi
che coinvolge matrici abbia qualche SW piu` decente
di perl o python per poter essere trattata.
 
Nota, inoltre, che esiste una libreria C++, "eigen",
che implementa metodi come quelli di Matlab/Octave,
consentendo di portare codice m generico in C++,
quasi 1 a 1.
 
Insomma, era chiaro che non si trattava di risolvere
un puzzle, ma di fornire spunti all'OP.
 
bye,
 
-- 
 
piergiorgio

 regexp al limite" (dopo prima risposta).
 
Certo in risposta ad un altro buontempone che gli aveva proposto 
OpenOffice; per fortuna in questo caso Enrico si è accorto da solo 
che usare OpenOffice era una cazzata. Almeno spero.
 

 di sabbia.
 
Ed era scritto pure che Python e PERL non erano meglio.
Cazzata per cazzata ....
 

On 2014-11-26 22:26, mallin.shetland wrote:
[...]
 
Senza offesa, ma secondo me tu stai ragionando
con i paraocchi.
 
bye,
 
-- 
 
piergiorgio

 Ed era scritto pure che Python e PERL non erano meglio.
 
Infatti non sono meglio per quel problema.
E ti sfido a dimostrare il contrario.
 
bye,
 
-- 
 
piergiorgio


sono io il buontempone
 

 è quello dove si suggeriva di usare perl.
sempre il sottoscritto
 
il buontempone di openoffice
 

 E ti sfido a dimostrare il contrario.
 
tutto dipende da qual'è il problema
 
se gli elenchi di numeri sono in un file e se l'elaborazione dei dati 
è una cosa di routine, devi considerare che è necessario uno script 
che legga dal file, controllando:
- la presenza di parametri
- l'esistenza del file
- l'accessibilità al file
- che il formato dei dati del file sia compatibile
- che mostri un minimo di righe di istruzioni d'uso con --help o -h
ecc...
 
python rispetto agli altri linguaggi IMHO è l'unico che permette di 
scrivere in modo semplice uno script facilmente leggibile e quindi 
facilmente estensibile anche a distanza di anni dalla prima stesura e 
da una persona diversa dall'autore originale
 
e cosa più essenziale è abbastanza semplice da permettere di 
realizzare uno script dopo che si è dedicata qualche ora alla lettura 
del tutorial e a qualche test (se si ha già qualche esperienza di 
programmazione)
 
-- 
bye
!(!1|1)
 

 In realtŕ sono poco adatti all'uso cazzeggio.
 
R e' gratis.
Se non ti piace octave (gratis), c'e' anche scilab (gratis pure lui).
 
Ciao Jack
-- 
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?

 se vuoi la funzione sum te la scrivo in una sola riga
 
Una sola *vera* riga, senza concatenazione... :-)
 
bye,
 
-- 
 
piergiorgio

 e a qualche test (se si ha già qualche esperienza di programmazione)
 
C'e` un altro punto, che pare passare un po' inosservato.
 
Le soluzioni (perl ed octave) che ho visto usano sum(sort()).
 
Il che e` pratico, ma sotto ottimale.
 
Dato che la complessita` media di sort() e O(n*log(n))
(a parte rank sort, ma non mi pare questo sia il caso),
il metodo sum(sort()) ha una complessita` O(n*(1+log(n))).
Cioe` sum() e` O(n) e sort() e O(n*log(n)).
 
Ora, si puo` fare meglio:
 
sum()-min()-max()
 
Questo ha complessita` O(3*n) ed e` quindi meglio per
log(n) > 2.
Con gli interi risulta uguale al metodo sum(sort()).
Con i float forse si forse no.
 
Questo miglioramento suggerisce, pero`, un'altra idea.
 
E` possibile attraversare la lista una volta e trovare
sum(), min() e max() contemporaneamente, riducendo la
complessita` a O(n).
 
Pseudo code (per una sola colonna):
 
sum_elem=elem(1)
min_elem=elem(1)
max_elem=elem(1)
 
for i=2 to num_elem
  sum_elem=sum_elem+elem(i)
  min_elem=min(min_elem,elem(i)
  max_elem=max(max_elem,elem(i)
endfor
 
result=sum_elem-min_elem-max_elem
 
Ora, in qualunque linguaggio compilato questo dovrebbe
essere piu` veloce di due chiamate a libreria sum(sort()).
E dovrebbe anche essere piu` veloce in qualunque linguaggio
interpretato che non abbia sort(), forse.
 
In octave, per una lista di 1000 elementi, sum(sort()) e`
*100* volte piu` veloce dello script esplicito di cui sopra.
 
Morale della favola: la ragione per cui python o perl potrebbero
essere meglio (da verificare) e` che la forma esplicita puo`
presentare vantaggi rispetto alla forma compatta, cosa che
con octave non si verifica sicuramente.
 
bye,
 
-- 
 
piergiorgio

 elimina il primo ed ultimo elemento (min e max).
 
Ma scusa una cosa strana:
- se chiedo "elimina il primo e l'ultimo", allora sempre tutto OK;
- invece min max, con due massimi (numeri uguali), che fa? me li toglie
tutt'e due?
 
-- 
Tanti saluti
 

 ritorna l' ultima valutazione quindi $s
 
Questa non vale, e` una concatenazione... :-)
 
Sarebbe:
 
sub sum {
  my $s=0;
  $s += $_ for(@_);
}
 
Sono 4 righe...
 
Altrimenti qualunque programma in molti linguaggi
si potrebbe scrivere con una unica linea. :-)
 
In generale, ci scriveresti il programma perl
*completo* che fa quanto chiesto dall'OP?
 
Dall'assegnazione della matrice, fino al print
del risultato...
 
Sono curioso di vederlo in perl...
 
Grazie,


 tutt'e due?
 
Non ho capito, fammi un esempio.
 
bye,
 
-- 
 
piergiorgio


110
110
103
102
101
 
Pero' ho detto una cavolata perche' fara' di certo 526 - 101 - 110, mica
cancella tutti pattern 110.
 
-- 
Tanti saluti
 

 Se ho un po di tempo mi ci metto
 
Magari, perche` mi interesserebbe.
 
Thanks,
 
bye,
 
-- 
 
piergiorgio

 che 
è semplice come python ma molto più veloce
-- 
bye
!(!1|1)
 

 cosa significa NR==1 o anche ==2 o anche >=3 ?
 
Ad intuito direi che NR sta per Number Row cioe` il numero di riga.
Se da terminale provi ad es. a dare
awk 'NR==3{print $0}' nomefile.txt
vedi che ti stampa la terza riga di quel file.
 
 

 C'e` invece di default mawk.
 
Si' ma infatti io avevo da subito aggiunto gawk a mawk.
 
-- 
Tanti saluti
 

 cosa significa NR==1 o anche ==2 o anche >=3 ?
 
``NR'' sta per "total Number of input Records"
 
Un po' di teoria: AWK è orientato alla linea, esegue una sequenza
di comandi per ogni record di input (che per default è una linea).
Il formato di ogni comando è:
 
<schema> {<azione>}
 
dove <schema> è una espressione booleana <azione> è una 
sequenza di istruzioni eseguita se <schema> ha valore vero
Se manca lo schema viene eseguita l'azione per ogni record 
di input, se manca l'azione viene eseguita l'azione di default 
{ print }
 
Detto questo ti sarà chiaro cosa fa ``NR==1 { print Prima riga }''
 


 
#!/usr/bin/perl
use strict;
use warnings;
 
my @m=();
 
while(<STDIN>)  {
	my @row=split(/\s+/,$_);
	for my $i(0..@row -1) {
		my $n=$row[$i];
		next unless $n=~/^\d+$/;
		$m[$i]=[] unless defined $m[$i];
		push @{$m[$i]},$n;
	}
}
 
my @tot=();
 
for my $col(@m) {
	my @a = sort { $a <=> $b } @$col;
	my $sum=0;
	if (@a > 2) {
		$sum += $_ for(@a[1..@a-2]);
	}
	push @tot,$sum;
}
 
print join(' ',@tot),"\n";
exit 0;
 
 
Da eseguire con  ./
sum.pl
 < filename
 
 
Poi se vuoi qualche delucidazione su qualche passaggio puoi chiedere
 
 
 
 

 perdere tempo con bash e con algoritmi O(log n!)
 
Grazie a tutti quanti, con una menzione per quelli che mi hanno risposto 
in questo subthread, senza fare polemiche ma dandomi uno strumento con 
esempi e spiegazioni chiare. :)
 
ciao e grazie!

 Poi se vuoi qualche delucidazione su qualche passaggio puoi chiedere
 
Se vale anche per me, chiedero' -- ma dovrebbe esserci tutto in quel
manuale che m'hai indicato. TNX per lo script.
 
-- 
Tanti saluti
 


#!/usr/bin/perl
use strict;
use warnings;
 
my @s=();
my @min=();
my @max=();
 
while(<STDIN>)  {
	my @row=split(/\s+/,$_);
	for my $i(0..@row -1) {
		my $n=$row[$i];
		next unless $n=~/^\d+$/;
		if (defined $s[$i]) {
			$s[$i]+=$n;
		}
		else {
			$s[$i]=$n;
		}
		if (defined $min[$i]) {
			$min[$i]=$n if $n < $min[$i];
		}
		else {
			$min[$i]=$n;
		}
		if (defined $max[$i]) {
			$max[$i]=$n if $n > $max[$i];
		}
		else {
			$max[$i]=$n;
		}
	}
}
 
for my $i(0..@s -1) {
	print $s[$i] - $min[$i] - $max[$i]," ";
}
print "\n";
exit 0;
 
 
Questa è una versione ancora piu efficiente
Non usa matrici nè sort
 

 Non usa matrici nè sort
 
Questa sembra quasi italiano, come fanno a dire che perl e' difficile?!
Grazie :-)
 
-- 
Tanti saluti
 

 ciao e grazie
Certo che dover fare fatica a trovare le risposte pertinenti perchè ci 
sono persone che devono dimostrare di essere più intelligenti è 
veramente deprimente.
Come rendere inutilizzabile un thread spammandolo di litigi che a sto 
punto potrebbero essere pure finti.
 
ciao e buon linux

 punto potrebbero essere pure finti.
 
Sono stupito da quanto scrivi :-O a cosa ti riferisci?
 
Io questi litigi non li ho proprio letti, anzi mi paiono tutte
discussioni interessantissime. Quando prima hai ringraziato
mallin.shetland hai capito cosa stava dicendo con la frase "Invece la
cosa di cui più mi meraviglio è che tutti conosconoC e tutti sanno di
AWK e quindi tutti dovrebbero arrabattarsi a fare un programmino
semplice semplice (come trovare il massimo o il minimo in tempo lineare)
ma preferiscono perdere tempo con bash e con algoritmi O(log n!)" ?
 
La tua richiesta di aiuto ha IMHO di per se introdotto il tema
"Algoritmi e strutture dati".
A pag. 11 di questo PDF
http://www.disp.uniroma2.it/users/grandoni/slide%20ASDonline/cap04stampa.pdf
 
c'e` questa domanda: "O( n2 ) è quanto di peggio si possa fare: tutti i
confronti possibili! Possiamo fare di meglio ?"
IMHO quello che a te sembra un litigio in realta` e` una discussione per
dare la risposta a quella domanda o a qualcosa di simile.
 
 
 
 
 


Quali litigi ?
Dovresti esserne fiero invece, senza volerlo hai aperto alcuni dibattiti 
che qui non nascevano da tempo
E devo dire che piu o meno tutti si sono comportati civilmente
 


La ragione per cui viene cancellato il min e il max riguarda il 
controllo della prestazione di un programma, in certi casi il sistema 
rallenta determinati lavori perchè ce ne sono altri più importanti che 
girano contemporaneamente. Tagliando il tempo + basso e + alto ti metti 
al sicuro da anomalie non prodotte dal programma in se che gira.
Quindi se ci fossero due 101 togliendone uno si ridurrebbe il possibile 
intervento del sistema sul funzionamento, ma l'altro dovrebbe restare.
Questo è ciò che servirebbe a me, poi la vostra speculazione teorica può 
andare oltre.
 
ciao e grazie


si vede che il troll sono io. :)
 
ciao e buon linux

 dare la risposta a quella domanda o a qualcosa di simile.
 
Potrebbe, e in realtà il thread ha preso questo andamento. 
in realtà l'OP chiedeva l'indicazione di uno strumento o di un algoritmo 
con relativo  esempio ed hanno proposto solo un algoritmo che non andava
bene. E non andava bene non perché usava sort in maniera inefficiente ma
perché usava AWK alla cazzo di cane.
E far notare questo non serve  dimostrare che qualcuno è più bravo di
qualcun altro ma are una risposta sensata all'OP.
 

 E devo dire che piu o meno tutti si sono comportati civilmente
 
E non posso fare a meno di approvare ed unirmi ad enoquick.
Ancora una volta. Non ci fare l'abitudine però.

 ciao e grazie
 
Mi aggiungo anch'io al coro
(gawk o una versione di awk che supporti asort)
 
----------------------------------------
{
	print $0;
	ele[NR] = NF;
	while (NF > 0)
	{
		dati[NF, NR] = $NF;
		NF--;
	}
}
 
 
END {
	for (i = 1; i <= NR; i++)
	{
		for (j = 1; j <= ele[i]; j++)
			a[j] = dati[i, j];
		asort(a, b, "@val_num_asc");
# per eliminare min e max
# j = 2 ; j < ele[i]
# per aver la somma
# finale [(ele[i] + 1] += b[j]
		for (j = 1; j<= ele[i]; j++)
			finale[j, i] = b[j]
	}
	for (i = 1; i <= NR; i++)
	{
		for (j = 1; j <= ele[i]; j++)
			printf("%s\t", finale[i, j]);
		print "";
	}
    }
----------------------------------------

 nr più alto e più basso.
 
% cat tog.py
rows = []
for l in  open('tog.dat').readlines():
    rows.append([int(n) for n in l.strip().split()])
print [sum(sorted(t)[1:-1]) for t in zip(*rows)]
% python tog.py
[68638, 68661, 68611, 68543, 68545]
% 
-- 
compro mobili vecchi - vendo mobili antichi

 si vede che il troll sono io. :)
 
Un pochino si.
 
Potevi fare una domanda piu` chiusa, invece
di generalizzare al punto che qualunque
risposta sarebbe andata bene.
 
Detto altrimenti, spiega qual'e` il problema,
non come implementare una soluzione.
Magari esiste qualcosa di gia` disponibile...
 
bye,
 
-- 
 
piergiorgio