最近在逛论坛shell 板块, 发现有一些类似全排列的问题
比如:
8楼 版主提到的问题
点击(此处)折叠或打开
-
x abcd
-
y 0,1
-
z a,b,c
-
-
变成:
-
x abcd y 0 z a
-
x abcd y 0 z b
-
x abcd y 0 z c
-
x abcd y 1 z a
-
x abcd y 1 z b
-
x abcd y 1 z c
-
===================
-
规则:y (0/1) z (a/b/C)有6种情况
当然, 如果给的文本只有这3行, 这并没有啥, 如给改成:
-
给一文本, 每行按","分隔,然后按照各行取一个域先后排列,罗列出所有排列组合:
-
$cat file
-
a
-
b,c
-
=> 排列为
-
a b
-
a c
-
-
$cat file2
-
a,b
-
1,2,3
-
m
-
=> 排列为
-
a 1 m
-
a 2 m
-
a 3 m
-
b 1 m
-
b 2 m
-
b 3 m
这里和上面的例子类似, 只是明确了文本行数不定
-
我的思路就是每处理一行时, 就存储该行及该行之前的行的情况, 最后在打印出来
-
比如
-
a,b
-
1,2,3
-
m
-
-
处理第一行的时候, 保留a[1,1]=a 和 a[1,2]b
-
处理第二行的时候, 就保留a[2,1]=a 1, a[2,2]=a 2, a[2,3]=a 3, a[2,4]=b 1, a[2,5]=b 2, a[2,6]=b 3
-
...
-
可以发现a[NR,n]是关于a[NR-1,m]的
-
代码:
-
awk -F, -vn=1 '{l=split($0,b,",");for(i=1;i<=l;++i)for(k=1;k<=n;++k)a[NR,++m]=a[NR-1,k]b[i] OFS;n=m;m=0}END{for(i=1;i<=n;++i){print a[NR,i]}}'
所以最上面的例子的代码可以很快得出:
-
awk -vn=1 '{l=split($2,b,",");for(i=1;i<=l;++i)for(k=1;k<=n;++k)a[NR,++m]=a[NR-1,k]$1 FS b[i] FS;n=m;m=0}END{for(i=1;i<=n;++i){print a[NR,i]}}'
这写是通过各行的域来顺序排列的,当然也有按列的顺序来的
又比如,
-
大意就是:
-
文本有2行,分别代表两个向量, 给出一个步长
-
比如:
-
$cat file
-
0 0.75
-
0.25 0
-
-
给出步长为0.25
-
则要求得到:
-
0 0
-
0 0.25
-
0 0.5
-
0 0.75
-
0.25 0
-
0.25 0.25
-
0.25 0.5
-
0.25 0.75
-
-
即每列从该列最小值按给定步长递增到不超过最大值,然后给出所有符合条件的组合情况,总共有2*4=8种情况
-
同样, 假如文本是
-
$cat file2
-
1 2 1
-
3 2 2
-
-
配合给的步长为1,则要得出:
-
1 2 1
-
1 2 2
-
2 2 1
-
2 2 2
-
3 2 1
-
3 2 2
-
-
总共有3*1*2=6种情况,当然,有可能会有重复的
这里按列来全排列的情况与按行的情况类似, 我的思路是先得到每列的最大最小值, 然后得到各列符合条件的元素, 最后来做排列
-
awk -vv=0.25 '{for(i=1;i<=NF;++i){max[i]=max[i]!=""?(max[i]>$i?max[i]:$i):$i;min[i]=min[i]!=""?(min[i]<$i?min[i]:$i):$i}}END{for(i=1;i<=NF;++i){for(k=min[i];k<=max[i];k+=v)a[i,++n]=k;b[i]=n;n=0}t=1;for(i=1;i<=NF;++i){for(k=1;k<=b[i];++k)for(j=1;j<=t;++j){c[i,++n]=c[i-1,j]a[i,k] FS}t=n;n=0}for(i=1;i<=t;++i)print c[NF,i]}
阅读(2028) | 评论(0) | 转发(0) |