Генерация нескольких списков комбинаций для числа в Java - PullRequest
2 голосов
/ 21 октября 2010

Вот проблема, над которой я работаю, и мой фрагмент кода.Есть ли лучший способ реализовать это?Для этого я использовал базовые структуры управления.

Лучше ли хранить строки и столбцы на карте и осуществлять поиск по карте на основе пар ключ / значение?

На входе в здание установлена ​​охранная клавиатура.Он имеет 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]);
  }
}

Ответы [ 5 ]

1 голос
/ 21 октября 2010

Есть много способов решить эту проблему, но я думаю, что это может быть решено с помощью HashMaps и HashSets более эффективно, чем выполнение нескольких итераций.

На вашем месте я бы сначала построил модель данных, используя хэш-карту и хэш-набор.Это потому, что хэш-карта и хэш-набор имеют быстрый поиск (без итераций)

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);
}
0 голосов
/ 21 октября 2010

Для конкретной клавиатуры в вашем вопросе мы можем использовать основание 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)
}

Более общим и надежным решением будет создание карты, на которой вы можете указать, какие другие ключи вы принимаете.

Пример: разрешение A, Z, P, M, N для A: поместить новую запись '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 ;
}
0 голосов
/ 21 октября 2010

Или это ...

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.

0 голосов
/ 21 октября 2010

Здесь есть много разных приемлемых решений.Я предполагаю, что проще построить матрицу 10x10 для проверки ошибок (например, errorMatrix).Первый индекс тогда будет означать исходную цифру, второй индекс - цифру, набранную пользователем, а значение arr [i] [j] - количество ошибок для этой пары цифр.Инициализируйте его следующим образом:
errorMatrix [i] [i] = 0 // без ошибок
errorMatrix [i] [j] = 1, где i и j - соседние по горизонтали или вертикали цифры
errorMatrix [i] [j] = 2, в других случаях.

Тогда для каждой пары цифр вы получите количество ошибок в O (1).Вы заявили, что примете только одну ошибку, поэтому для непарных пар будет достаточно значения 2, и вы можете просто суммировать номера ошибок и сравнить их с единицей.

Итак, как это построить.Переберите все пары цифр и найдите значение ошибки.Вы должны лучше реализовать функцию CheckError, которая будет вычислять ее для пары цифр a и b

  1. , если a = b, тогда errorMatrix равен 0;
  2. Цифры aи b являются вертикальными соседями, если abs (ab) = 3. Итак, abs (ab) == 3 set errorMatrix [a] [b] = 1;
  3. Цифры a иb являются горизонтальными соседями, если

    a.(a-1) / 3 == (b-1) / 3 - здесь мы проверяем, что эти цифры находятся на одной строке.
    b.abs (ab) == 1 - здесь мы проверяем, что цифры находятся в соседних ячейках.
    Если (a) и (b), то значение ошибки равно 1;

  4. В других случаях значение ошибки равно 2.

Мне кажется, что эта спецификация верна.Однако вам необходимо протестировать его перед использованием

Так что, если вы хотите обрабатывать изменения раскладки клавиатуры, вам просто нужно переписать метод CheckError.

Надеюсь, это поможет.

0 голосов
/ 21 октября 2010

Я бы хотел иметь функцию, аналогичную 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));

Теперь мы начинаем нуждаться в каком-то реальном веществе. И я думаю, что оставлю остальное как упражнение для читателя. Да, я не учел хитрости, но это стратегия (дизайн, основанный на тестировании), который ведет вас более непосредственно к решениям, чем просто пытается написать код. Пока вы проходите все тесты, вы постепенно продвигаетесь к завершенному решению. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...