Рекурсия массива

У меня есть присвоение, которое я не могу выяснить, любые указатели будут очень цениться, оно идет как так:

Существует серия лампочек, представленных как массив истинных/ложных, существует переключатель для каждой лампочки путем нажатия на нее для любой лампочки, Вы переключаете ее, а также 2 смежных (1 от левого и еще 1 от права; если в напряжении лампа нажатого переключателя - только 1 смежный переключенный, конечно).

То, что необходимо для выполнения, является методом, который принимает массив серии превращенных лампочек включения - выключения и другого представляющего другое состояние, предположительно, 1-го массива после того, как некоторые переключатели были нажаты..! Таким образом, рекурсия должна использоваться, чтобы узнать, существует ли комбинация щелчков переключателя, которые преобразуют массив 1 для выстраивания 2.

Вот подпись метода:

public static boolean disco(boolean[] init, boolean[] target)

Возвратит true, если массив init может быть преобразован для предназначения, ложь иначе. Метод должен быть статическим и не использовать циклы и любые другие статические и глобальные переменные, только локальные.

Пример:

boolean[] init = {true, false, true, false, true, false};
boolean[] target = {false, true, false, true, false, true};

Поскольку выше 2 массивов, дискотека (init, цель) возвратит true, потому что переключение 1-х и 4-х ламп уступило бы, целевое состояние (помните смежные лампы, переключаемые также).

6
задан Bill the Lizard 19 September 2012 в 01:56
поделиться

4 ответа

новая версия

public static boolean disco(boolean[] init, boolean[] target)  
{  
  return recurse(init,boolean,0);  
}  

public static boolean recurse(boolean[] init, boolean[] target, int min)  
{  
  if (min == init.length)  
    if (init == target)  
      return true;  
    else  
      return false;  
  boolean[] temp = "init with a change at min";  
  boolean a = recurse(init, target, min+1);  
  boolean b =   recurse(temp, target, min+1);  
  return a||b;
}  

новая новая версия

Я разбил ее на три случая:

Случай 1 : длина% 3 = 0
Заменив первую и вторую лампочки, вы можете повлиять на изменение только третьей лампы. Тогда при изменении на 4 и 5 будет изменен только 6-й. Мы видим, что мы можем заменить любую лампочку с индексом кратным 3.
Работая в обратном направлении (начиная с конца), мы можем сделать то же самое, но на этот раз это показывает нам, что мы можем менять лампочки с индексами (i + 1), кратными 3.
Комбинируя их, мы видим, что если мы хотим изменить индекс 0,1 mod 3, мы можем. Но затем, чтобы изменить 2, нам просто нужно изменить соседнюю пару 0,1, а затем изменить среднюю. Так что во всех случаях они разрешимы.

Случай 2 : длина% 3 = 1
Точно так же, как и в первом случае, но мы можем повлиять на отдельные изменения на 0,2 mod 3 и, таким образом, сжать случаи 1 mod 3.

Случай 3 : длина% 3 = 2
Работа вперед и назад дает только случаи 0 по модулю 3. Единственные оставшиеся шаги, которые у нас есть, вносят два изменения в лампочки (так как мы можем игнорировать любые изменения в положениях 0). Изменение 1 или 2 изменит положение, окруженное двумя нулями, тогда как изменение 0 поменяет местами четность в соседних блоках 1,2, которые имеют 0 между ними (проще, если вы его нарисуете).Но что я показал до сих пор, так это то, что все 0 можно исправить, и в любых соседних 1,2 вы можете исправить оба, если они ошибочны, не меняя ничего другого. Если один из них неверен, вы распространяете изменение на соседнюю пару 1,2. При необходимости это изменение можно переместить. Это означает, что любое четное количество ошибок в 1,2 позиции может быть исправлено, а нечетное - нет. Все ошибки в позиции 0 могут быть исправлены.

public static boolean disco(boolean[] init, boolean[] target)  
{  
  if (init.length%3 == 0 || init.length%3 == 1)
    return true;
  return recurse(init,target,0, true);
}

public static boolean recurse(boolean[] init, boolean[] target, int index, boolean even)
{
  if (index = init.length)
    return even;
  if (init[index] != target[index] && index%3 != 0)
    even = !even;
  return recurse(init, target, index+1, even);
}
7
ответ дан 8 December 2019 в 17:19
поделиться

Вот словами , как бы я это сделал:

Если осталось не более трех лампочек, довольно легко проверить, могут ли они быть переключился так, что это правильно.

Если лампочек больше трех, выполните следующие действия:

Убедитесь, что первая лампочка правильная. Если это так, продолжайте рекурсивно с подмассивом, начиная со второй лампочки.

Если первая лампочка не подходит, включите вторую лампочку (переключение первой лампы не сработает, потому что предыдущие лампы переключаются обратно). Теперь первая лампочка правильная. Продолжайте с подмассивом, начиная со второй лампочки.

4
ответ дан 8 December 2019 в 17:19
поделиться

Спасибо всем за помощь, вот что у меня получилось:

public static boolean disco(boolean[] init, boolean[] target)
{
    if (java.util.Arrays.equals(init, target)) {
        return true;
    } else {
        return disco(init, target, 0);
    }
}

private static boolean disco(boolean[] init, boolean[] target, int i)
{
    if (i > init.length-1) {
        return false;
    }

    disco(init, target, i+1);
    boolean t = false;

    if (init[i] != target[i]) {
        switchBulb(init, target, i);
    }

    if (java.util.Arrays.equals(init, target)) {
        t = true;
    }

    return t;
}

private static void switchBulb(boolean[] init, boolean[] target, int i)
{
    if ( (i > 1) && (init[i-1] != target[i-1]) && (init[i-2] != target[i-2]) ) {
        // If there's a series of 3 opposite-to-target bulbs, switch the middle one & from both sides
        init[i-1] = !init[i-1];
        init[i] = !init[i];
        init[i-2] = !init[i-2];
    } else if (i > 0 && i < init.length-1) {
        // There's only 1 bulb or 2 adjacent bulbs that are opposite of target.
        if (i == 1 && (init[0] != target[0]) ) {
            // First 2 bulbs are opposite of target's, so switch the 1st one.
            init[i-1] = !init[i-1];
            init[i] = !init[i];
        } else if ( (i == init.length-2) && (init[i+1] != target[i+1]) ) {
            init[i+1] = !init[i+1];
            init[i] = !init[i];
        } else {
            init[i] = !init[i];
            init[i-1] = !init[i-1];
            init[i+1] = !init[i+1];
        }
    } else {
        // First bulb or last bulb.
        init[i] = !init[i];
        if (i == 0) {
            init[i+1] = !init[i+1];
        } else {
            init[i-1] = !init[i-1];
        }
    }
}

Я чувствую, что мое использование рекурсии здесь минимально, могло бы быть намного чище, если бы рекурсия использовалась правильно. Any thoughts? Я говорю о функции switchBulb, ее можно заменить более сложной логикой рекурсии, или я ошибаюсь?

Например, если просто перебирать лампочки по одной и сравнивать с целевым массивом, то не обязательно получится правильно для ВСЕХ комбинаций лампочек (см. пример), так как же имитировать случайное переключение лампочек с помощью рекурсии? Или есть какая-то закономерность? Должна быть, если нет, то как она узнает, когда остановиться?

Кажется, я нашел решение, напишу позже, если кому-то интересно...

1
ответ дан 8 December 2019 в 17:19
поделиться

Подсказка: Пусть a1, a2, ..., ak, ..., an - входные данные, а b1, b2, ..., bk, ..., bn - желаемый выход.

Вы можете рекурсивно проверить левую и правую стороны, а затем объединить результат. Самое сложное - объединить результат.

Начнем с левой стороны.

  1. Проверьте a1, a2, ..., ak, true на b1, b2, ..., bk, true.
    1. если true, то проверяем a1, a2, ..., ak на b1, b2, ..., bk.
      1. если true, то решение от a1, a2, ..., ak до b1, b2, ..., bk не может включать переключение k-го переключателя
      2. если false, то решение от a1, a2, ..., ak до b1, b2, ..., !bk должно включать переключение k-го переключателя
    2. если false, то тест a1, a2,...,ak до b1, b2,...,bk
      1. если true, то решение от a1,a2, ..., ak до b1, b2,..., bk должно включать переключение k-го переключателя
      2. если false, то решение от a1,a2,...,ak до b1, b2,..., bk не может включать переключение k-го переключателя

После двух тестов в левой части, вы можете провести аналогичные тесты в правой части. Вы сможете объединить значения тестов, так как будете знать, был ли переключен k-й переключатель или нет.

2
ответ дан 8 December 2019 в 17:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: