【问题标题】:Algorithm to determine dimensions of matrix given a string rep给定字符串代表确定矩阵维数的算法
【发布时间】:2021-10-12 21:53:51
【问题描述】:

给定一个描述超矩阵的字符串,例如

"[[[1,2],[4,5],[6,7]]"  which is a 3,2 matrix

 "[[1,2,3],[4,5,6]]"    which is a 2,3 matrix

 "[ [[1,2],[3,4],[4,6]], [[7,8],[9,10],[11,12]] ]" which is a 2,3,2 matrix

有没有找到矩阵维度的好方法?例如,我正在寻找一种算法,它会为第三个矩阵报告 2,3,2。我可以保证每个维度都有不变的元素,即没有丢失的数字。可以假设字符串可以被标记为整数、逗号和左右方括号。我对可能使用的方法更感兴趣,我认为它可能是递归的。我玩弄了建造一棵树的想法,但我不确定这最终会有所帮助。显然,我可以使用 numpy 并查看形状非常轻松地使用 python 做到这一点,但我正在寻求可能的算法的建议。

【问题讨论】:

  • (1) 遍历字符串并维护一个名为 depth 的变量,初始化为 0,在每个 '[' 处增加 1,在每个 ']' 处减少 1。 (2) 在遍历字符串时,计算每个深度的逗号数。保留一个计数器列表,以便每个深度都有一个计数器。只要变量depth 首次再次小于该深度,就停止计算给定深度的逗号。
  • 哇,谢谢你的快速回答,我先研究一下。
  • 检查一串括号是否正确平衡是一个标准问题;见Wikipedia: Dyck language。了解如何使用递归或迭代来解析带括号的字符串非常有用。您不仅需要它来确定矩阵的维度,还需要解析算术表达式,例如 3*(4-(5+6))
  • 我可以解析表达式,但我有一个生成维度的心理障碍。

标签: algorithm matrix


【解决方案1】:
  • 遍历字符串并维护一个名为 depth 的变量,初始化为 0,每 '[' 加 1,每 ']' 减 1。
  • 在遍历字符串时,计算每个深度的逗号数。保留一个计数器列表或字典,以便每个深度都有一个计数器。
  • 当变量深度第一次再次小于该深度时,停止计算给定深度的逗号。
def get_dims(mat):
  depth = 0
  capped_depth = len(mat)
  dims = {}
  for c in mat:
    if c == '[':
      depth += 1
    elif c == ']':
      if depth <= capped_depth:
        dims[depth] = dims.get(depth, 0) + 1
      depth -= 1
      capped_depth = min(depth, capped_depth)
    elif c == ',' and depth <= capped_depth:
      dims[depth] = dims.get(depth, 0) + 1
  return [v for k,v in sorted(dims.items())]

get_dims("[ [[1,2],[3,4],[4,6]], [[7,8],[9,10],[11,12]] ]")
# [2, 3, 2]

get_dims("[[1,2,3],[4,5,6]]")
# [2, 3]

get_dims("[[1,2],[4,5],[6,7]]")
# [3, 2]

get_dims('[[[]]]')
# [1, 1, 1]

get_dims('[[[,]]]')
# [1, 1, 2]

请注意,此代码假定字符串描述了一个格式良好的矩阵。但是您可以轻松修改代码以验证字符串是否格式正确。

  • 当且仅当depth 在 for 循环期间始终为正数,并且在 for 循环后恰好变为 0 时,方括号才正确嵌套。
  • 我编写的代码使用第一个列表在每个深度的长度来计算相应的维度。如果每个给定深度的所有列表都具有相同的长度,则矩阵将是良构的。

【讨论】:

  • 我希望我能将两者都标记为正确。
【解决方案2】:

这是一个 C 版本:

void printMatrixDimensions(const char *inString) {
    int depth = 0;
    int dimensions = 0;
    int *counts = NULL;
    for (const char *inString_ptr = inString; inString_ptr[0] != '\0'; inString_ptr++) {
        char c = inString_ptr[0];
        char upOrDown = 0;
        
        if (c==' ' || c=='\t' || c=='\r' || c=='\n') continue; // skip whitespace
        if (c == '[') { upOrDown = 1; } // determine if we're going down in depth
        else if (c == ']') { upOrDown = -1; } // or coming up
        depth += upOrDown;
        
        if (upOrDown == 1) { // if we're going deeper,
            if (depth > dimensions) { // expand our depths stack if needed
                dimensions = depth;
                counts = realloc(counts, sizeof(int) * dimensions);
            }
            counts[depth - 1] = 0; // initialize the new depth with a count of 0
        }
        
        if (!(c=='[' || c==']')) { // if a character other than []
            if (c==',') { // if a comma, then we have at least 2 members
                if (counts[depth - 1] == 0) counts[depth - 1] = 2;
                else counts[depth - 1] += 1;
            } else { // if a non-comma char is there, that counts for a member
                if (counts[depth - 1] == 0) counts[depth - 1] = 1;
            }
        }
    }
    
    printf("Matrix dimensions:\n");
    for (int i = 0; i < dimensions; i++) {
        printf("%i ", counts[i]);
    }
    printf("\n");
    
    
    if (counts != NULL) free(counts);

}

【讨论】:

  • 我一直在运行 C 代码,想知道是否应该在 for 循环的每次迭代中增加深度。例如 [1,2],产生 0 1 2 1 而 [[1,2],[3,4]] 产生 0 0 2 0 1 2 1。我将检查代码以查看发生了什么。 [更新] 我的错误,我错误地初始化了 upOrDown。工作正常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-22
  • 2022-12-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多