在Java中为一个数字生成多个组合列表

发布于 2024-09-28 13:29:40 字数 857 浏览 0 评论 0原文

以下是我正在解决的问题和我的代码片段。 有没有更好的方法来实现这个?我在下面使用了基本的控制结构。

将行和列存储在映射中并根据键/值对搜索映射是否更好?

建筑物入口处有一个安全键盘。它有 9 个数字 1 - 9,采用 3x3 矩阵格式。

1 2 3
4 5 6
7 8 9

安全部门已决定允许一个人出现一位数字错误,但该数字应该是水平或垂直的。示例:对于 5,允许用户输入 2、4、6、8;对于 4,允许用户输入 1、5、7。如果要输入的安全代码是 1478,并且如果用户输入 1178,则应允许用户输入。

以下是我正在处理的代码片段:

ArrayList<Integer> list = new ArrayList<Integer>();
int num = 9;
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};

for(int i =0;i< arr.length;i++){
  for(int j = 0; j <arr.length;j++){
    if(num == arr[i][j]){
      row = i;
      col = j;
      break;

    }
  }
}
for(int j1 = 0; j1< 3 ; j1++){
  if(arr[row][j1] != num){
    list.add(arr[row][j1]);
  }
}
for(int i1 = 0 ; i1 <3;i1++){
  if(arr[i1][col] != num){
    list.add(arr[i1][col]);
  }
}

The following is the problem I'm working on and my snippet of code.
Is there a better way to implement this? I have used basic control structures for this below.

Is it better to store the rows and columns in a map and searching through the map based on the key/value pairs?

There is a security keypad at the entrance of a building. It has 9 numbers 1 - 9 in a 3x3 matrix format.

1 2 3
4 5 6
7 8 9

The security has decided to allow one digit error for a person but that digit should be horizontal or vertical. Example: for 5 the user is allowed to enter 2, 4, 6, 8 or for 4 the user is allowed to enter 1, 5, 7. IF the security code to enter is 1478 and if the user enters 1178 he should be allowed.

The following is a snippet of code i was working on:

ArrayList<Integer> list = new ArrayList<Integer>();
int num = 9;
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};

for(int i =0;i< arr.length;i++){
  for(int j = 0; j <arr.length;j++){
    if(num == arr[i][j]){
      row = i;
      col = j;
      break;

    }
  }
}
for(int j1 = 0; j1< 3 ; j1++){
  if(arr[row][j1] != num){
    list.add(arr[row][j1]);
  }
}
for(int i1 = 0 ; i1 <3;i1++){
  if(arr[i1][col] != num){
    list.add(arr[i1][col]);
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

心房敞 2024-10-05 13:29:40

有很多方法可以解决这个问题,但我认为使用 HashMap 和 HashSet 可以比多次迭代更有效地解决。

如果我是你,我会首先使用哈希图和哈希集构建数据模型。这是因为哈希图和哈希集具有快速查找(无迭代)

HashMap<Integer,HashSet<Integer>> values = new HashMap<Integer, HashSet<Integer>>();

//now put in the accepted values for one
HashSet<Integer> oneValues = new HashSet<Integer>();
oneValues.put(1);
oneValues.put(2);
oneValues.put(4);
values.put(1, oneValues);

//put in 2 values
......

然后当您解析输入时,如果您想查看代码是否接受输入的值,只需执行类似的操作

private boolean isAccepted(int input, int combinationValue)
{
  // check to see if the inputed value in the accepted values set
  return values.get(combinationValue).contains(input);
}

There are many ways to solve this, but I think it can be solved with HashMaps and HashSets more efficiently than doing several iterations.

If I were you, I would build the data model first using a hash map and a hash set. This is because hash map and hash set have fast lookup, (no iterations)

HashMap<Integer,HashSet<Integer>> values = new HashMap<Integer, HashSet<Integer>>();

//now put in the accepted values for one
HashSet<Integer> oneValues = new HashSet<Integer>();
oneValues.put(1);
oneValues.put(2);
oneValues.put(4);
values.put(1, oneValues);

//put in 2 values
......

Then when you parse your input, if you want to see if an inputed value is accepted for what the code is, just do something like

private boolean isAccepted(int input, int combinationValue)
{
  // check to see if the inputed value in the accepted values set
  return values.get(combinationValue).contains(input);
}
凉城凉梦凉人心 2024-10-05 13:29:40

我倾向于想要一个类似于 isCloseTo(int a, int b) 的函数所以,比如说,如果我调用 isCloseTo(5, 5) 它将返回 true 。如果我调用 isCloseTo(2, 5) 它也应该返回 true。但如果我调用 isCloseTo(1, 3) 它将返回 false。

所以我会编写这样的测试:

assertTrue(isCloseTo(5, 5));

好的,这真的很容易通过:

public boolean isCloseTo(int a, int b) {return true;}

然后,也许

assertFalse(isCloseTo(1, 3) );

上面的实现失败了,所以我需要更改它

public boolean isCloseTo(int a, int b) {return a == b;}

这仍然是一个不完整的实现,所以我们需要另一个测试

assertTrue(isCloseTo(1, 2));

现在我们开始需要一些真正的实质内容。我想我会把剩下的作为练习留给读者。是的,我已经省略了棘手的部分,但这是一种策略(测试驱动设计),它可以让您更直接地找到解决方案,而不仅仅是尝试编写代码。只要您保持所有测试都通过,您就可以朝着完整的解决方案稳步前进。祝你好运!

I would tend to want a function along the lines of isCloseTo(int a, int b) So, say, if I called isCloseTo(5, 5) it would return true. If I called isCloseTo(2, 5) it should return true, too. But if I called isCloseTo(1, 3) it would return false.

So I'd write tests like that:

assertTrue(isCloseTo(5, 5));

OK, that's really easy to get to pass:

public boolean isCloseTo(int a, int b) {return true;}

Then, maybe

assertFalse(isCloseTo(1, 3));

which fails with the above implementation, so I'd need to change it

public boolean isCloseTo(int a, int b) {return a == b;}

That's still an incomplete implementation, so we need another test

assertTrue(isCloseTo(1, 2));

Now we start to need some real substance. And I think I'll leave the rest as an exercise for the reader. Yes, I've left the tricky bits out, but this is a strategy (test-driven design) that leads you more directly to solutions than just trying to write the code. As long as you keep all the test passing, you make steady progress toward a complete solution. Good luck!

红颜悴 2024-10-05 13:29:40

这里有许多不同的可接受的解决方案。我想构造 10x10 整数矩阵来检查错误会更容易(例如 errorMatrix)。第一个索引表示原始数字,第二个索引表示用户输入的数字,arr[i][j] 的值是该数字对的错误数量。以这种方式初始化它:
errorMatrix[i][i] = 0 //没有错误
errorMatrix[i][j] = 1,其中 i 和 j 是水平或垂直相邻的数字
在其他情况下,errorMatrix[i][j] = 2。

那么对于每个数字对,您将得到 O(1) 的错误数量。您声明您只接受一个错误,因此对于不匹配的对,值 2 就足够了,您只需将错误数相加并将其与 1 进行比较即可。

那么,如何构建这个。迭代所有数字对并找出误差值。你应该更好地实现函数 CheckError 来计算数字对 a 和 b

  1. 如果 a=b,则 errorMatrix 为 0;
  2. 数字 a 和 b 是垂直的
    如果 abs(ab) = 3,则为邻居。所以,是
    abs(ab)==3 设置 errorMatrix[a][b] =
    1;
  3. 数字a和b是水平的
    邻居如果

    a. (a-1)/3==(b-1)/3 - 在这里我们检查这些数字是否在同一行。
    b. abs(ab)==1 - 在这里我们检查数字是否在相邻单元格中。
    如果(a)和(b)则误差值为1;

  4. 在其他情况下错误值为 2。

在我看来这个规范是正确的。不过使用前需要先测试一下

因此,如果您想处理键盘布局的更改,您只需重写 CheckError 方法即可。

希望它有所帮助。

There are many different acceptable solutions here. I suppose it's easier to construct 10x10 matrix of integer to check for the errors (for example errorMatrix). First index then will mean original digit, second index - digit typed by user, and value of arr[i][j] is a number of errors for this digit pair. Initialize it that way:

errorMatrix[i][i] = 0 //no error

errorMatrix[i][j] = 1, where i and j are horizontally or vertically neighboring digits

errorMatrix[i][j] = 2, in other cases.


Then for every digit pair you will get number of errors in O(1). You stated that you will accept only one error, so the value of 2 for unmatched pairs will be enough and you can just sum up the error numbers and compare it to one.



So, how to construct this. Iterate through all of the digit pairs and find the value of error. You should better implement function CheckError that will calculate it for digit pair a and b

  1. if a=b, then errorMatrix is 0;
  2. The digits a and b are vertical
    neighbors if abs(a-b) = 3. So, is
    abs(a-b)==3 set errorMatrix[a][b] =
    1;
  3. The digits a and b are horizontal
    neighbors if

    a. (a-1)/3==(b-1)/3 - here we check that this digits are on the same line.

    b. abs(a-b)==1 - here we check that digits are in the neighboring cells.

    If (a) and (b) then error value is 1;

  4. In other cases error value is 2.

It seems to me that this spec is right. However, you need to test it before using


So, if you then want to handle the changes of the keypad layout you just have to rewrite CheckError method.

Hope it helps.

王权女流氓 2024-10-05 13:29:40

或者这个...

boolean matchDigit(int p, int d) {
   return (p==d) 
       || (p==d-3) 
       || (p==d+3) 
       || (d%3!=1 && p==d-1) 
       || (d%3!=0 && p==d+1);
} 

假设我们已经确保 p 和 d 在 1 到 9 之间。

Or this...

boolean matchDigit(int p, int d) {
   return (p==d) 
       || (p==d-3) 
       || (p==d+3) 
       || (d%3!=1 && p==d-1) 
       || (d%3!=0 && p==d+1);
} 

this assumes we've already assured that p and d are between 1 and 9.

北方的韩爷 2024-10-05 13:29:40

对于您问题中的特定键盘,我们可以使用基数 3 来解决此问题并计算数字/按键之间的距离。

1 { 1 / 3, 1 % 3 } = {0, 1}
2 { 2 / 3, 2 % 3 } = {0, 2}
...
5 { 5 / 3, 5 % 3 } = {1, 2}
...
8 { 8 / 3, 8 % 3 } = {2, 2}

public boolean isValidCode(int code, int expexted) {
    while(code > 0)
    {
        if (!isValidDigit(code % 10, expected % 10))
            return false ;
        code /= 10 ;
        expected /= 10 ;
    }

    return (code == expected) ;
}

public boolean isValidDigit(int a, int b) {
    int dx = (a - b) / 3 ;
    int dy = (a - b) % 3 ;
    return ((Math.abs(dx) + Math.abs(dy)) == 1)
}

一个更通用和更强大的解决方案是创建一个 Map,您可以在其中设置您接受的其他键。

示例:A 允许使用 A、Z、P、M、N:在映射中放置一个新条目 'A'="AZPMN",检查字符是否相同或类型字符是否在例外字符串中。


private Map acceptedChars = new HashMap() ;

public void loadAcceptedCharacters() {
    acceptedChars.put('A', "AZPMN") ;
}

public boolean isValidKeyword(String word, String expected)
{
    if (word == null || word.matches("\\s*"))
        return false ;

    if (word.length() != expected.length())
        return false ;

    for(int idx = 0; idx < word.length(); idx++)
    {
        if (!isValidDigit(word.chatAt(idx), expected.charAt(idx)))
            return false ;
    }

    return true ;
}

public boolean isValidDigit(char chr, char expected) {
    String accepted ;
    if (chr != expected)
    {
        accepted = acceptedChars.get(chr) ;
        if (accepted == null)
            return false ;
        if (accepted.indexOf(chr) < 0) 
            return false ;
    }
    return true ;
}

For the specific keyboard in your question we can use a base 3 to solve this problem and to calculate the distances between digits/keys.

1 { 1 / 3, 1 % 3 } = {0, 1}
2 { 2 / 3, 2 % 3 } = {0, 2}
...
5 { 5 / 3, 5 % 3 } = {1, 2}
...
8 { 8 / 3, 8 % 3 } = {2, 2}

public boolean isValidCode(int code, int expexted) {
    while(code > 0)
    {
        if (!isValidDigit(code % 10, expected % 10))
            return false ;
        code /= 10 ;
        expected /= 10 ;
    }

    return (code == expected) ;
}

public boolean isValidDigit(int a, int b) {
    int dx = (a - b) / 3 ;
    int dy = (a - b) % 3 ;
    return ((Math.abs(dx) + Math.abs(dy)) == 1)
}

A more generic and robust solution will be to create a Map where you can set what other keys you accept.

Sample: allowing A, Z, P, M, N for A: place a new entry 'A'="AZPMN" in the map, validation checkd if the character is the same or if the type character is in the exceptions string.


private Map acceptedChars = new HashMap() ;

public void loadAcceptedCharacters() {
    acceptedChars.put('A', "AZPMN") ;
}

public boolean isValidKeyword(String word, String expected)
{
    if (word == null || word.matches("\\s*"))
        return false ;

    if (word.length() != expected.length())
        return false ;

    for(int idx = 0; idx < word.length(); idx++)
    {
        if (!isValidDigit(word.chatAt(idx), expected.charAt(idx)))
            return false ;
    }

    return true ;
}

public boolean isValidDigit(char chr, char expected) {
    String accepted ;
    if (chr != expected)
    {
        accepted = acceptedChars.get(chr) ;
        if (accepted == null)
            return false ;
        if (accepted.indexOf(chr) < 0) 
            return false ;
    }
    return true ;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文