Автоматически суммировать числовые столбцы и печатать итоги - PullRequest
8 голосов
/ 18 ноября 2010

Учитывая вывод git ... --stat:

 3 files changed, 72 insertions(+), 21 deletions(-)
 3 files changed, 27 insertions(+), 4 deletions(-)
 4 files changed, 164 insertions(+), 0 deletions(-)
 9 files changed, 395 insertions(+), 0 deletions(-)
 1 files changed, 3 insertions(+), 2 deletions(-)
 1 files changed, 1 insertions(+), 1 deletions(-)
 2 files changed, 57 insertions(+), 0 deletions(-)
 10 files changed, 189 insertions(+), 230 deletions(-)
 3 files changed, 111 insertions(+), 0 deletions(-)
 8 files changed, 61 insertions(+), 80 deletions(-)

Я хотел получить сумму числовых столбцов, но сохранить форматирование строки. В целях общности я создал скрипт awk, который автоматически суммирует любые числовые столбцы и выдает итоговую строку:

{
    for (i = 1; i <= NF; ++i) {
        if ($i + 0 != 0) {
            numeric[i] = 1;
            total[i] += $i;
        }
    }
}
END {
    # re-use non-numeric columns of last line
    for (i = 1; i <= NF; ++i) {
        if (numeric[i])
            $i = total[i]
    }
    print
}

Выход:

 44 files changed, 1080 insertions(+), 338 deletions(-)

Awkимеет несколько функций, которые упрощают задачу, таких как автоматическое преобразование строк-> чисел, все массивы как ассоциативные массивы, а также возможность перезаписывать автоматически разделенные позиционные параметры и затем печатать эквивалентные строки.

Есть ли лучший языкза этот взлом?

Ответы [ 11 ]

5 голосов
/ 20 ноября 2010

Perl - 47 символов

Вдохновлено решением awk от ChristopheD. Используется с ключом командной строки -an. 43 символа + 4 символа для переключателя командной строки:

$i-=@a=map{($b[$i++]+=$_)||$_}@F}{print"@a"

Я могу получить 45 (переключатель 41 + -ap) с небольшим количеством обмана:

$i=0;$_="<kbd>Ctrl-M</kbd>@{[map{($b[$i++]+=$_)||$_}@F]}"

Старое 66-символьное решение на основе хеш-функции:

@a=(),s#(\d+)(\D+)#$b{$a[@a]=$2}+=$1#gefor<>;print map$b{$_}.$_,@a
2 голосов
/ 23 ноября 2010

AWK - 63 символа

(в скрипте bash $ 1 - это имя файла, предоставляемое в качестве аргумента командной строки):

awk -F' ' '{x+=$1;y+=$4;z+=$6}END{print x,$2,$3,y,$5,z,$7}' $1

Конечно, можно также передать входные данные (будетсохраните еще 3 символа, когда это разрешено).

2 голосов
/ 18 ноября 2010

Рубин - 87

puts ' '+[*$<].map(&:split).inject{|i,j|[0,3,5].map{|k|i[k]=i[k].to_i+j[k].to_i};i}*' '
2 голосов
/ 18 ноября 2010

Python - 101 символ

import sys
print" ".join(`sum(map(int,x))`if"A">x[0]else x[0]for x in zip(*map(str.split,sys.stdin)))'

Использование уменьшения больше на 126 символов

import sys
print" ".join(reduce(lambda X,Y:[str(int(x)+int(y))if"A">x[0]else x for x,y in zip(X,Y)],map(str.split,sys.stdin)))
1 голос
/ 01 июня 2011

PHP 152 130 символов

Ввод:

$i = "
3 files changed, 72 insertions(+), 21 deletions(-) 
3 files changed, 27 insertions(+), 4 deletions(-) 
4 files changed, 164 insertions(+), 0 deletions(-) 
9 files changed, 395 insertions(+), 0 deletions(-) 
1 files changed, 3 insertions(+), 2 deletions(-) 
1 files changed, 1 insertions(+), 1 deletions(-) 
2 files changed, 57 insertions(+), 0 deletions(-) 
10 files changed, 189 insertions(+), 230 deletions(-) 
3 files changed, 111 insertions(+), 0 deletions(-) 
8 files changed, 61 insertions(+), 80 deletions(-)";

Код:

$a = explode(" ", $i);

foreach($a as $k => $v){
    if($k % 7 == 0)
        $x += $v;

    if(3-$k % 7 == 0)
        $y += $v;

    if(5-$k % 7 == 0)
        $z += $v;   

}

echo "$x $a[1] $a[2] $y $a[4] $z $a[6]";

Выход:

44 files changed, 1080 insertions(+), 338 deletions(-)

Примечание: explode () потребует наличия пробела перед новой строкой.

1 голос
/ 21 ноября 2010

JavaScript (Rhino) - 183 154 139 байт

Гольф:

x=[n=0,0,0];s=[];readFile('/dev/stdin').replace(/(\d+)(\D+)/g,function(a,b,c){x[n]+=+b;s[n++]=c;n%=3});print(x[0]+s[0]+x[1]+s[1]+x[2]+s[2])

Доступный для считывания:

x=[n=0,0,0];
s=[];

readFile('/dev/stdin').replace(/(\d+)(\D+)/g,function(a,b,c){
    x[n]+=+b;
    s[n++]=c;
    n%=3
});

print(x[0]+s[0]+x[1]+s[1]+x[2]+s[2]);
1 голос
/ 18 ноября 2010

За счет увеличения длины вашего кода я переместил основной синтаксический анализ в предложение BEGIN, поэтому основное предложение обрабатывает только числовые поля.Для немного большего входного файла я смог измерить значительное улучшение скорости.

BEGIN {
    getline
    for (i = 1; i <= NF; ++i) {
        # need to test for 0, too, in this version
        if ($i == 0 || $i + 0 != 0) {
            numeric[i] = 1;
            total[i] = $i;
        }
    }
}
{
    for (i in numeric) total[i] += $i
}
END {
    # re-use non-numeric columns of last line
    for (i = 1; i <= NF; ++i) {
        if (numeric[i])
            $i = total[i]
    }
    print
}

Я сделал тестовый файл, используя ваши данные и выполнив paste file file file ... и cat file file file ..., так что результат имел 147поля и записи 1960 года.Моя версия заняла около четверти твоей.По исходным данным разница не поддалась измерению.

1 голос
/ 18 ноября 2010

Эта проблема не сложная и не сложная ... хотя и "симпатичная".

Вот решение на Python:

import sys
r = []
for s in sys.stdin:
    r = map(lambda x,y:(x or 0)+int(y) if y.isdigit() else y, r, s.split())
print ' '.join(map(str, r))

Что оно делает ... оно сохраняетподсчитайте в r при переходе от строки к строке.Разбивает строку, затем для каждого элемента списка, если это число, добавляет его в счет или сохраняет его как строку.В конце они все переопределяются в строку и объединяются с пробелами между ними для печати. ​​

Альтернативная, более «алгебраическая» реализация, если нам не нужно читать все входные данные сразу:

import sys

def totalize(l):
    try:    r = str(sum(map(int,l)))
    except: r = l[-1]
    return r

print ' '.join(map(totalize, zip(*map(str.split, sys.stdin))))

Что делает этот?totalize() берет список строк и пытается вычислить сумму чисел;если это не удается, он просто возвращает последний.zip() снабжается матрицей, представляющей собой список строк, каждая из которых является списком элементов столбца в строке - zip транспонирует матрицу, чтобы она превратилась в список элементов столбца, а затем totalize вызывается для каждого столбца ирезультаты объединяются, как и раньше.

0 голосов
/ 03 декабря 2010

PHP, 176 166 164 159 158 153

for($a=-1;$a<count($l=explode("
",$i));$r=explode(" ",$l[++$a]))for($b=-1;$b<count($r);$c[++$b]=is_numeric($r[$b])?$c[$b]+$r[$b]:$r[$b]);echo join(" ",$c);

Однако для этого потребуется полный ввод в $ i ... Вариант с $ i , замененным $ _ POST ["i"] поэтому он будет отправлен в текстовой области ... Имеет 162 символов:

for($a=-1;$a<count($l=explode("
",$_POST["i"]));$r=explode(" ",$l[$a++]))for($b=0;$b<count($r);$c[$b]=is_numeric($r[$b])?$c[$b]+$r[$b]:$r[$b])$b++;echo join(" ",$c);

Это версия с

НЕ ЖЕСТКИХ КОЛОНН

0 голосов
/ 29 ноября 2010

Lua, 140 байт

Я знаю, что Lua не лучший язык для игры в гольф, но, по сравнению с размером времени выполнения, я думаю, он неплохо справляется.

f,i,d,s=0,0,0,io.read"*a"for g,a,j,b,e,c in s:gmatch("(%d+)(.-)(%d+)(.-)(%d+)(.-)")do f,i,d=f+g,i+j,d+e end print(table.concat{f,a,i,b,d,c})
...