Вот быстрый 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
добавил к нему.
Надеюсь это поможет!