将循环重构为函数

时间:2009-04-06 10:03:02

标签: java function for-loop

我有这段java代码:

int maxDigit = 4;
for(int a = 0; a <= maxDigit; a++)
{
  for(int b = 0; b <= maxDigit; b++)
  {
    if(b != a){
      for(int c = 0; c <= maxDigit; c++)
      {
        if(c != a && c != b)
        {
          for(int d = 0; d <= maxDigit; d++)
          {
            if(d != a && d != b && d != c)
            {
              for(int e = 0; e <= maxDigit; e++)
              {
                if(e != a && e != b && e != c && e != d)
                {
                  String temp = a + "" + b + "" + c + "" + d + "" + e;
                  System.out.println(temp);
                  permutations.add(Integer.parseInt(temp));
                }
              }
            }
          }
        }
      }
    }
  }
}

如何将这段代码转换为函数?

目的是生成数字0到9的排列,这里的代码在0到4之间。看起来很容易将它放在函数中,但我无法立即找到它。

5 个答案:

答案 0 :(得分:2)

这是获取all permutations of a string的典型问题的变体。

您的教授希望您做的归纳是这个问题非常适合使用递归的解决方案。

字符串s的排列的基本算法如下:

  1. 选择s中的第一项。
  2. 获取s中其他项目的所有排列(所选项目除外)。
  3. 将所选项目添加到步骤2中的每个排列。
  4. 重复s的下一个字符。
  5. 这是使用Functional Java库的有效解决方案。

    导入这些......

    import fj.F;
    import fj.P2;
    import fj.P1;
    import fj.data.Stream;
    import static fj.data.Stream.nil;
    import static fj.data.Stream.cons;
    import static fj.data.Stream.range;
    import static fj.data.Enumerator.charEnumerator;
    import static fj.data.Show.streamShow;
    import static fj.data.Show.charShow;
    import static fj.P2.map2_;
    

    查找排列的递归函数:

    public Stream<Stream<Character>> permutations(final Stream<Character> s) {
      return selections(s).bind(
        new F<P2<Character, Stream<Character>>, Stream<Stream<Character>>>() {
          public Stream<Stream<Character>>()
            f(final P2<Character, Stream<Character>> ys) {
              return permutations(ys._2()).bind(cons(ys._1()));
            }
          });
    }
    

    依次选择每个元素的递归函数:

    public Stream<P2<Character, Stream<Character>>>
    selections(final Stream<Character> s) {
      if (xs.isEmpty())
        return nil();
      else {
        final char x = xs.head();
        final Stream<Character> xs = s.tail()._1();
        return cons(P.p(x, xs),
          new P1<Stream<P2<Character, Stream<Character>>>>() {
            public Stream<P2<Character, Stream<Character>>> _1() { 
              return selections(xs).map(map2_().f(cons(x))));
            }
          });
      }
    }
    

    然后,获取字符'0'到'9'的所有排列:

    Show<Stream<Character>> s = streamShow(charShow);
    for (Stream<Character> ps : permutations(range(charEnumerator, '0', '9'))) {
      System.out.println(s.showS(ps));
    }
    

    编辑:这实际上是comonads的一个很好的用例。使用Functional Java的最新主干,您可以使用Zipper comonad执行此操作,如下所示:

    public static Stream<Stream<Character>> perms(Stream<Character> s) {
      Stream<Stream<Character>> r = single(Stream.<Character>nil());
      for (final Zipper<Character> z : fromStream(s))
        r = join(z.cobind(
          new F<Zipper<Character>, Stream<Stream<Character>>>() {
            public Stream<Stream<Character>> f(final Zipper<Character> zp) {
              return perms(zp.lefts().reverse().append(zp.rights())).map(compose(
                Stream.<Character>cons().f(zp.focus()),
                  P.<Stream<Character>>p1()));
            }
          }).toStream());
      return r;
    }
    

答案 1 :(得分:1)

填补空洞:

int[] indexes = { 0, 0, 0, 0, 0 };
addPermutations(maxDigit, indexes, 0, permutations);


void addPermutations(int max, int[] indexes, int currentIndex, List<Integer> permutations) {
    if (currentIndex == indexes.length) {
        // terminal case
        String temp = ...;
        System.out.println(temp);
        permutations.add(Integer.parseInt(temp));
    } else {
        // recursive case
        for (int i = 0; i <= max; i++) {
            if (... != i) {
                indexes[currentIndex] = i;
                addPermutations(max, indexes, currentIndex+1, permutations);
            }
        }
    }
}

答案 2 :(得分:0)

已经存在一个非常相似的问题:

How to increment a java String through all the possibilities?

答案 3 :(得分:0)

没有代码,但算法应如下所示。

假设您想要从0到7的所有5位数的排列。为此:

  • 计算基数为7的值的j =十进制值为100000(1 + 5个零)
  • 循环for i = 0; i < j; ++i,将每个i转换为base-7系统,可选择在前缀为零。

答案 4 :(得分:0)

您可以使用N-ary树,每个点有4个分支,递归导航树并跨越已经看到该节点数字的分支?