Вот быстрый 100% скрипт bash, который сделает эту работу:
a=()
while read _ n; do
[[ -n $n ]] && ((++a[n]))
done < datafile.txt
c=0
for i in ${!a[@]}; do
echo "$((c+=a[i])) $i"
done
Если вам нужен скрипт, который вы можете вызвать из командной строки:
#!/bin/bash
a=()
while read _ n; do
[[ -n $n ]] && ((++a[n]))
done < "$1"
c=0
for i in ${!a[@]}; do
echo "$((c+=a[i])) $i"
done
Или, если вы предпочитаете однострочку, чтобы произвести впечатление на вашу бабушку:
a=(); while read _ n; do [[ -n $n ]] && ((++a[n])); done < datafile.txt; c=0; for i in ${!a[@]}; do echo "$((c+=a[i])) $i"; done
Он работает примерно за 2-3 секунды на двухъядерном процессоре Pentium с частотой 2,6 ГГц в файле с 100000 строк.
редактировать
Пояснения:
Первый цикл:
- Мы инициализируем
a как пустой массив: a=()
- Читаем файл
datafile.txt построчно. В каждой строке два поля, только второе добавляется в имена переменных n
- Если
n не пусто (это тест [[ -n $n ]] мы увеличиваем значение n ключа массива a ; это то, что делает строка ((++a[n])) . ((...)) является арифметическим контекстом bash.
- После прочтения всех файлов у нас есть массив
a , а k поле - это ровно количество автономных систем, степень которых равна k .
Тогда второй цикл:
- Перед циклом переменная
c устанавливается в 0.
for i in ${!a[@]}; do будет перебирать все ключи массива a .
$((c+=a[i])) добавит значение a[i] к c и расширится до этого значения. Это значение echo со значением ключа, который i добавил к нему.
Надеюсь это поможет!