Перестановочные столбцы без повторов - PullRequest
4 голосов
/ 24 января 2012

Кто-нибудь может дать мне какой-нибудь кусок кода или алгоритма или что-то еще для решения следующей проблемы?У меня есть несколько файлов, каждый с разным количеством столбцов, например:

$> cat file-1   
1 2
$> cat file-2
1 2 3
$> cat file-3
1 2 3 4

Я хотел бы вычесть абсолютные значения столбцов и разделить на сумму всех в строке для каждого другого столбца только один раз (комбинация без повторяющихся пар столбцов):

in file-1 case I need to get:

0.3333                    # because |1-2/(1+2)|

in file-2 case I need to get:

0.1666 0.1666 0.3333      # because |1-2/(1+2+3)| and |2-3/(1+2+3)| and |1-3/(1+2+3)|

in file-3 case I need to get:

0.1 0.2 0.3 0.1 0.2 0.1   # because |1-2/(1+2+3+4)| and |1-3/(1+2+3+4)| and |1-4/(1+2+3+4)| and |2-3/(1+2+3+4)| and |2-4/(1+2+3+4)| and |3-4/(1+2+3+4)|

Ответы [ 3 ]

3 голосов
/ 24 января 2012

Это должно сработать, хотя я предполагаю, что вы допустили небольшую ошибку в своих входных данных. Исходя из вашего третьего паттерна, следующие данные должны быть -

Вместо:

in file-2 case I need to get:

0.1666 0.1666 0.3333      # because |1-2/(1+2+3)| and |2-3/(1+2+3)| and |1-3/(1+2+3)|

Должно быть:

in file-2 case I need to get:

0.1666 0.3333 0.1666     # because |1-2/(1+2+3)| and |1-3/(1+2+3)| and |2-3/(1+2+3)|

Вот awk один вкладыш:

awk '
NF{
    a=0;
    for(i=1;i<=NF;i++)
    a+=$i;
    for(j=1;j<=NF;j++)
    {
        for(k=j;k<NF;k++)
        printf("%s ",-($j-$(k+1))/a)
        }
    print "";
    next;
    }1' file

Короткая версия:

awk '
NF{for (i=1;i<=NF;i++) a+=$i; 
for (j=1;j<=NF;j++){for (k=j;k<NF;k++) printf("%2.4f ",-($j-$(k+1))/a)}
print "";a=0;next;}1' file

Входной файл:

[jaypal:~/Temp] cat file
1 2

1 2 3

1 2 3 4

Тест:

[jaypal:~/Temp] awk '
NF{
    a=0;
    for(i=1;i<=NF;i++)
    a+=$i;
    for(j=1;j<=NF;j++)
    {
        for(k=j;k<NF;k++)
        printf("%s ",-($j-$(k+1))/a)
        }
    print "";
    next;
    }1' file
0.333333 

0.166667 0.333333 0.166667 

0.1 0.2 0.3 0.1 0.2 0.1 

Тест из более короткой версии:

[jaypal:~/Temp] awk '
NF{for (i=1;i<=NF;i++) a+=$i; 
for (j=1;j<=NF;j++){for (k=j;k<NF;k++) printf("%2.4f ",-($j-$(k+1))/a)}
print "";a=0;next;}1' file 
0.3333 

0.1667 0.3333 0.1667 

0.1000 0.2000 0.3000 0.1000 0.2000 0.1000
1 голос
/ 24 января 2012

@ Джайпал, просто бей меня! Вот что у меня было:

awk '{for (x=1;x<=NF;x++) sum += $x; for (i=1;i<=NF;i++) for (j=2;j<=NF;j++) if (i < j) printf ("%.1f ",-($i-$j)/sum)} END {print ""}' file.txt

Выход:

0.1 0.2 0.3 0.1 0.2 0.1

печатает с точностью до одного знака после запятой.

@ Jaypal, есть ли быстрый способ напечатать абсолютное значение? Возможно, как: abs(value)?

EDIT:

@ Jaypal, да, я тоже пытался искать и не мог найти что-то простое :-( Кажется, if ($i < 0) $i = -$i - это путь. Я думаю, вы могли бы использовать sed, чтобы убрать любые знаки минус:

awk '{for (x=1;x<=NF;x++) sum += $x; for (i=1;i<=NF;i++) for (j=2;j<=NF;j++) if (i < j) printf ("%.1f ", ($i-$j)/sum)} {print ""}' file.txt | sed "s%-%%g"

Ура!

0 голосов
/ 24 января 2012

Поскольку это выглядит как домашнее задание, я буду действовать соответственно.

Чтобы найти общее количество чисел в файле, вы можете использовать

cat filename | wc -w

Найдите первый номер по:

cat filename | cut -d " " -f 1

Чтобы найти сумму в файле:

cat filename | tr " " "+" | bc

Теперь, когда у вас есть total_nos, используйте что-то вроде:

for i in {seq 1 1 $total_nos}
do
    #Find the numerator by first_number - $i
    #Use the sum you got from above to get the desired value.
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...