Java 如何最有效地计算俄罗斯方块堆栈的高度剖面? 问题陈述

Java 如何最有效地计算俄罗斯方块堆栈的高度剖面? 问题陈述,java,performance,scala,optimization,bit-manipulation,Java,Performance,Scala,Optimization,Bit Manipulation,我们得到了一个长度height的整数数组stack。width告诉我们,在xs的每个条目中,最多设置width-最低位 计算长度宽度的数组profile,使得profile[i]==max\u i的max\u i在stack[max\u i]设置了i第位时最大 我如何才能以比下面更有效的方式实现这一点 当前解决方案 目前,我检查了各列,并分别检查每一位 下面显示了我当前在Scala中的实现。但请随意用其他语言(Java、C、C++)给出答案,因为我主要对算法部分感兴趣(针对当前CPU进行了优化)

我们得到了一个长度
height
的整数数组
stack
width
告诉我们,在
xs
的每个条目中,最多设置
width
-最低位

计算长度
宽度
的数组
profile
,使得
profile[i]==max\u i
max\u i
stack[max\u i]
设置了
i
第位时最大

我如何才能以比下面更有效的方式实现这一点

当前解决方案 目前,我检查了各列,并分别检查每一位

下面显示了我当前在Scala中的实现。但请随意用其他语言(Java、C、C++)给出答案,因为我主要对算法部分感兴趣(针对当前CPU进行了优化)

Scala代码:

def tetrisProfile(stack: Array[Int]): Array[Int] = {
  var col = 0
  val profile = new Array[Int](width)
  while(col < width){
    var row = 0
    var max = 0
    while(row < height){
      if(((stack(row) >> col) & 1) == 1)
        max = row + 1
      row += 1
    }
    profile(col) = max
    col += 1
  }
  return profile
}

我在C上编写了我的解决方案。我希望,您能够将算法移植到Java或Scala

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define WIDTH  10
#define HEIGHT 22

// Convert (1 << n) to n for n == 0-10
static char bit2ndx[11] = {-1, 0, 1, 8, 2, 4, 9, 7, 3, 6, 5};
int *tetrisProfile(int *input) {
  int row;
  // allocate memory and set everything to -1 - default rc value,
  // returned if no any result for this column
  int *rc = (int *)malloc(WIDTH * sizeof(int));
  memset(rc, ~0, WIDTH * sizeof(int));
  // create bitset for columns for check
  int testbits = (1 << WIDTH) - 1;
  // Iterate rows from up to bottom, and while exist columns for check
  for(row = HEIGHT - 1; row >= 0 && testbits != 0; row--) {
    int rowtestbits = testbits & input[row];
    while(rowtestbits != 0) {
      // extract lowest bit_1 from bitset rowtestbits
      int curbit = rowtestbits & -rowtestbits;
      rc[bit2ndx[curbit % 11]] = row;
      rowtestbits ^= curbit;
      testbits    ^= curbit;
    }
  }
  return rc;
}

int stack[HEIGHT] = {0x01, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200,
                       0,   0,   0,   0,    0,    0,    0,    0,     0,     0,
                       0,   0};


main(int argc, char **argv) {
  int i;
  int *ret = tetrisProfile(stack);
  for(i = 0; i < WIDTH; i++)
      printf("ret[%02d]=%d\n", i, ret[i]);
  free(ret);
}
#包括
#包括
#包括
#定义宽度10
#定义高度22

//皈依(1)如果董事会被转置,这会更容易。但是,仅仅为了这一点而转置它还不够容易。为什么这个标签是java?@Mikeologist我正在JVM上运行。语言不重要,所以java代码也可以。请不要建议将这个问题转移到codereview。我尝试过,他们不想要它。为了记录d、 这个问题在代码审查中被拒绝,只是因为作者坚持同时将其标记为、和。这使得Scala仅仅被视为伪代码,这对于代码审查来说是不合适的。作为一个问题,它是完全可以接受的。因此,您交换了循环,并在点击后停止每列中都有一些内容。此外,每个内部循环可能提取多个高度?我交换了循环。内部循环只迭代列:a)在此行中出现;b)在上面的行中找不到值。这样,内部循环的主体将执行小于或等于宽度倍,而不是更多。您的解决方案比旧的解决方案快4倍,这很好。你能解释一下(或提供一个链接来解释)这个
curbit%11
magic吗?上面有评论。我将尝试用另一个词来解释:变量“curbit”在相应的列中包含单个位_1。需要将钻头转换为其索引位置。最有效的解决方案-使用汇编BSF命令。但是,我认为,你的语言不允许使用汇编语言。所以,这只是一个周转表,它只包含相应位的预计算索引。也就是说,如果用数学解释,那么:N==bit2ndx[2**N];好啊另外,如果你下一个问题是“为什么是11,而不是5或10”,那么回答:2是本原根模11。所以,您需要选择分隔符,其中a)大于宽度b)2必须是分隔符的原始根。有关基本根的详细信息:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define WIDTH  10
#define HEIGHT 22

// Convert (1 << n) to n for n == 0-10
static char bit2ndx[11] = {-1, 0, 1, 8, 2, 4, 9, 7, 3, 6, 5};
int *tetrisProfile(int *input) {
  int row;
  // allocate memory and set everything to -1 - default rc value,
  // returned if no any result for this column
  int *rc = (int *)malloc(WIDTH * sizeof(int));
  memset(rc, ~0, WIDTH * sizeof(int));
  // create bitset for columns for check
  int testbits = (1 << WIDTH) - 1;
  // Iterate rows from up to bottom, and while exist columns for check
  for(row = HEIGHT - 1; row >= 0 && testbits != 0; row--) {
    int rowtestbits = testbits & input[row];
    while(rowtestbits != 0) {
      // extract lowest bit_1 from bitset rowtestbits
      int curbit = rowtestbits & -rowtestbits;
      rc[bit2ndx[curbit % 11]] = row;
      rowtestbits ^= curbit;
      testbits    ^= curbit;
    }
  }
  return rc;
}

int stack[HEIGHT] = {0x01, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200,
                       0,   0,   0,   0,    0,    0,    0,    0,     0,     0,
                       0,   0};


main(int argc, char **argv) {
  int i;
  int *ret = tetrisProfile(stack);
  for(i = 0; i < WIDTH; i++)
      printf("ret[%02d]=%d\n", i, ret[i]);
  free(ret);
}