Awk 如何循环数组的所有子集?

Awk 如何循环数组的所有子集?,awk,Awk,给定一个数组 a[1]=10,a[2]=20,a[3]=30 任何人都有一个遍历所有子集的迭代器。例如: function show(lst) { print ""; for(i in lst ) print(i,lst[i]) } e、 g 十, 二十 三十 四十 10,20 10,30 20,30 10,20,30使用二进制计数器技巧 $ awk 'BEGIN{n=split("10 20 30",a);

给定一个数组

  a[1]=10,a[2]=20,a[3]=30  
任何人都有一个遍历所有子集的迭代器。例如:

   function show(lst) { print ""; for(i in lst ) print(i,lst[i]) }
e、 g

十,

二十

三十

四十

10,20

10,30

20,30


10,20,30

使用二进制计数器技巧

$ awk 'BEGIN{n=split("10 20 30",a); 
             for(i=0;i<2^n;i++) 
               {printf "{"; 
                for(j=0;j<n;j++) printf "%s", and(i,2^j)?" "a[j+1]:""; 
                print " }"}}'
{ }
{ 10 }
{ 20 }
{ 10 20 }
{ 30 }
{ 10 30 }
{ 20 30 }
{ 10 20 30 }
重用来自的get_combs函数


这里的代码与@karakfa相同,但存储到一个数组中

# subs.awk
function push(a,x) { a[length(a)+1] = x }

function subs(a,b,  n,i,j) {
   n = length(a)
   for(i=1;i<2^n;i++) {
      b[i]["\\"]
      delete b[i]["\\"]
      for(j=0;j<n;j++) 
        if(and(i,2^j))
           push(b[i], a[j+1]) }}

function demo(  a,b,i,j) {
  split("a b c d",a," ") 
  subs(a,b)
  for(i in b) {
    for(j in b[i]) printf(" " b[i][j])
     print ""}}

BEGIN { demo() }
有什么好办法吗

保持@karakfa方法的简单性。。。 ... 同时还添加了@EdMorton的代码是如何生成从最小到最大的东西的? 我试图改变@karakfa的内部循环,但没有成功

我 我不喜欢的是添加一个排序的后处理器 尺寸见下文

但是有人有更优雅的方法吗

 # subs.awk
function push(a,x) { a[length(a)+1] = x }

function subs(a,b,  m,n,i,j) {
   n = length(a)
   for(i=1;i<=2^n ;i++) {
     b[i][0]
     delete b[i][0]
     for(j=0;j<n;j++) 
       if(and(i,2^j))
          push(b[i], a[j+1]); }}
 
function sizeSort(_,a,__,b,  l1,l2) {
  l1=length(a)
  l2=length(b)
  return l1==l2 ? 0 : (l1<l2 ? -1 : 1) }

function demo(  a,b,i,j,n) {
  split("10 20 30 40",a," ") 
  subs(a,b)
  n=asort(b,c,"sizeSort")
  for(i=1;i<=n;i++) printl(c[i]) }

function printl(a,   i){
  for(i in a) printf(" " a[i])
  print "" }

BEGIN { demo() }

根据你的不同语言和所选择的语言,对于同一个主题有几个答案。寻找算法组合。见f.exhttps://math.stackexchange.com/questions/89419/algorithm-wanted-enumerate-all-subsets-of-a-set-in-order-of-increasing-sums 顺便说一句,你的40有点不合适?你的正确:40是错的。抢手货同样的问题也被发布在usenet上,在那里有人指出所要的实际上是一个电源组,并且在上有一个解决方案。非常好的解决方案!我对@karakfa的优秀解决方案进行了一个很小的扩展,如下所示。当然,任何一个都可以,来真正加速这个过程,预计算和测试。缓存大小为n=1、n=2、n=3等的所有解决方案的索引,这将使所有子集的后续推理只需快速查找表
$ awk -f subsets.awk
10
20
30
10 20
10 30
20 30
10 20 30
# subs.awk
function push(a,x) { a[length(a)+1] = x }

function subs(a,b,  n,i,j) {
   n = length(a)
   for(i=1;i<2^n;i++) {
      b[i]["\\"]
      delete b[i]["\\"]
      for(j=0;j<n;j++) 
        if(and(i,2^j))
           push(b[i], a[j+1]) }}

function demo(  a,b,i,j) {
  split("a b c d",a," ") 
  subs(a,b)
  for(i in b) {
    for(j in b[i]) printf(" " b[i][j])
     print ""}}

BEGIN { demo() }
gawk -f subs.awk 
a
b
a b
c
a c
b c
a b c
d
a d
b d
a b d 
c d
a c d
b c d 
a b c d
 # subs.awk
function push(a,x) { a[length(a)+1] = x }

function subs(a,b,  m,n,i,j) {
   n = length(a)
   for(i=1;i<=2^n ;i++) {
     b[i][0]
     delete b[i][0]
     for(j=0;j<n;j++) 
       if(and(i,2^j))
          push(b[i], a[j+1]); }}
 
function sizeSort(_,a,__,b,  l1,l2) {
  l1=length(a)
  l2=length(b)
  return l1==l2 ? 0 : (l1<l2 ? -1 : 1) }

function demo(  a,b,i,j,n) {
  split("10 20 30 40",a," ") 
  subs(a,b)
  n=asort(b,c,"sizeSort")
  for(i=1;i<=n;i++) printl(c[i]) }

function printl(a,   i){
  for(i in a) printf(" " a[i])
  print "" }

BEGIN { demo() }
% gawk -f subs.awk 

 20
 30
 10
 40
 20 30
 10 20
 10 40
 20 40
 30 40
 10 30
 10 20 30
 10 30 40
 20 30 40
 10 20 40
 10 20 30 40