Zrobiłem szybki test porównawczy na istniejące odpowiedzi, które
- używaj tylko standardowych narzędzi (przepraszam za rzeczy takie jak
lua
lubrocket
),
- są prawdziwymi liniowcami,
- są w stanie dodać ogromne ilości liczb (100 milionów), oraz
- są szybkie (zignorowałem te, które trwały dłużej niż minutę).
Zawsze dodawałem liczby od 1 do 100 milionów, które były możliwe do wykonania na mojej maszynie w mniej niż minutę dla kilku rozwiązań.
Oto wyniki:
Pyton
:; seq 100000000 | python -c 'import sys; print sum(map(int, sys.stdin))'
5000000050000000
# 30s
:; seq 100000000 | python -c 'import sys; print sum(int(s) for s in sys.stdin)'
5000000050000000
# 38s
:; seq 100000000 | python3 -c 'import sys; print(sum(int(s) for s in sys.stdin))'
5000000050000000
# 27s
:; seq 100000000 | python3 -c 'import sys; print(sum(map(int, sys.stdin)))'
5000000050000000
# 22s
:; seq 100000000 | pypy -c 'import sys; print(sum(map(int, sys.stdin)))'
5000000050000000
# 11s
:; seq 100000000 | pypy -c 'import sys; print(sum(int(s) for s in sys.stdin))'
5000000050000000
# 11s
Awk
:; seq 100000000 | awk '{s+=$1} END {print s}'
5000000050000000
# 22s
Wklej i Bc
Na mojej maszynie zabrakło pamięci. To działało dla połowy wielkości wejściowej (50 milionów liczb):
:; seq 50000000 | paste -s -d+ - | bc
1250000025000000
# 17s
:; seq 50000001 100000000 | paste -s -d+ - | bc
3750000025000000
# 18s
Sądzę więc, że zajęłoby to około 35 sekund dla 100 milionów liczb.
Perl
:; seq 100000000 | perl -lne '$x += $_; END { print $x; }'
5000000050000000
# 15s
:; seq 100000000 | perl -e 'map {$x += $_} <> and print $x'
5000000050000000
# 48s
Rubin
:; seq 100000000 | ruby -e "puts ARGF.map(&:to_i).inject(&:+)"
5000000050000000
# 30s
do
Dla porównania, skompilowałem wersję C i przetestowałem ją również, aby zorientować się, o ile wolniejsze są rozwiązania oparte na narzędziach.
#include <stdio.h>
int main(int argc, char** argv) {
long sum = 0;
long i = 0;
while(scanf("%ld", &i) == 1) {
sum = sum + i;
}
printf("%ld\n", sum);
return 0;
}
:; seq 100000000 | ./a.out
5000000050000000
# 8s
Wniosek
C jest oczywiście najszybszy z 8s, ale rozwiązanie Pypy dodaje tylko niewielki narzut około 30% do 11s . Ale, szczerze mówiąc, Pypy nie jest dokładnie standardem. Większość ludzi ma zainstalowany tylko CPython, który jest znacznie wolniejszy (22 s), dokładnie tak szybko, jak popularne rozwiązanie Awk.
Najszybszym rozwiązaniem opartym na standardowych narzędziach jest Perl (15s).