2015-02-02 2 views
3

У меня есть следующая проблема: мне нужно создать таблицу, которая представляет собой комбинацию значений, исходящих из наборов. Мощность элементов в наборе неизвестна и может варьироваться от множества к множеству, область значений неизвестна и может также варьироваться от множества к множеству. Элементы в наборе неотрицательны, по крайней мере два элемента находятся внутри набора. Далее следует пример:Создание небулевой «таблицы истинности»

  • SET_A = {0, 1, 2}
  • SET_B = {0, 1}
  • Set_C = {0, 1}

Результат должен содержат следующие строки (порядок не является ограничивающим):

ТАБЛИЦА:

  • | 0 0 0 |
  • | 0 0 1 |
  • | 0 1 0 |
  • | 0 1 1 |
  • | 1 0 0 |
  • | 1 0 1 |
  • | 1 1 0 |
  • | 1 1 1 |
  • | 2 0 0 |
  • | 2 0 1 |
  • | 2 1 0 |
  • | 2 1 1 |

Кто-нибудь знает, какая математика стоит за этой проблемой? Я попытался рассмотреть проблемы Multiset, логические таблицы, комбинаторики. Многие из определений, которые я нашел, имеют сходство с моей проблемой, но я не могу изолировать что-либо в литературе, к которой я обращался до сих пор. Как только у меня есть ссылочное определение, я могу думать о его кодировании, но теперь я просто потерялся в рекурсивных функциях и ужасных играх с массивом. Благодарю.

EDIT: Вопрос был предложен уже: C# Permutation of an array of arraylists?

+0

Я не уверен, какие комплекты, которые вы разместили, имеют отношение к вашему столу. не могли бы вы объяснить отношения? –

+0

Таблица @GeorgeMauer содержит все комбинации всех возможных значений. – holgac

+0

Я не знаю, C# много, но в python, это прекрасный пример использования генератора/урожая. выход существует в C#; вероятно, есть способ построить нужную таблицу, используя выход. пример в python: http://pastebin.com/zveXyd0S – holgac

ответ

2

Редактировать: Извините, пришлось запустить прошлым вечером. Для произвольной размерности вы, вероятно, : придется использовать рекурсию. Вероятно, есть способ обойтись без него, но с рекурсией наиболее просто. Нижеследующее непроверено, но должно быть правильно.

IEnumerable<int[]> getRows(int[][] possibleColumnValues, int[] rowPrefix) { 
    if(possibleColumnValues.Any()) { //can't return early when using yield 
     var remainingColumns = possibleColumnValues.Skip(1).ToArray(); 
     foreach(var val in possibleColumnValues.First()) { 
      var rowSoFar = rowPrefix.Concat(new[]{val}).ToArray(); 
      yield return getRows(remainingColumns rowSoFar); 
     } 
    } 
} 

Использование:

getRows(new [][] { 
       new [] {0,1,2}, 
       new [] {0,1}, 
       new [] {0,1}, 
    }, new int[0]); 
+0

Ничего себе, хорошо, но это возможно, чтобы расширить эту функциональность до набора массивов ? (от pos1 до posN создается динамически), у меня есть динамический набор массивов, я не знаю, сколько они придут. Я пробовал это: http://pastebin.com/jV6pfMdh – Andrea

+0

@ user3200743 Извините, мне пришлось кончить прошлым вечером. проверьте мое редактирование. Я думаю, что это намного проще, чем принятый ответ. –

+0

Я ЛЮБЛЮ ЭТО;) Я нашел еще одно доступное рекурсивное решение, но я, вероятно, выберу твое. 6 строк кода, мне это нравится. Хорошего дня. – Andrea

2

Что вам смотреть на это комбинаторика. Также не имеет значения, что является доменом элементов в наборе. Пока вы можете перечислить их, проблема будет такой же, как для чисел от 0 до установленной мощности.

Чтобы перечислить все параметры, укажите вектор индексов и после каждого итерационного приращения первый индекс. Если он переполняется, установите значение 0 и увеличит второй индекс и т. Д.

+0

Комбинаторика - довольно большая ветвь, и я теряюсь в диком лесу определений. Относительно вашего решения, что вы имеете в виду под индексом? Является ли это индексом элемента в наборе (если вы думаете о представлении массива) или что-то еще (возможно, в отношении самой таблицы) – Andrea

0

Задача состоит в том, чтобы напечатать перестановки.Вы, кажется, копаете глубже, чем это. Это не имеет ничего общего с природой элементов.

+0

Поскольку я не знаю числа наборов и количества элементов в них. Мне трудно реализовать (я не могу легко определить правила построения таблицы, когда эти два ограничения больше не выполняются). Я беру первый набор, затем я пытаюсь построить перестановку с учетом второго набора, а затем третьего, но как я могу остановиться? Я попробовал рекурсивный подход к функциям, но что было бы условием завершения? (или, может быть, я устал и мне нужен сон;)) – Andrea

+0

@ user3200743 см. мое решение. Условие для завершения - больше нет столбцов для обработки –

0

Следующие данные не указаны для эффективности (ни в пространстве, ни в скорости). Идея состоит в том, чтобы просто получить базовый алгоритм. Я оставлю вам больше пространства и времени для вас.

Основная идея состоит в том, чтобы признать, что все комбинации списков n - это всего лишь комбинации из n-1 списков с каждым элементом первого списка. В этот момент это довольно прямая рекурсивная функция.

public static IEnumerable<int[]> Permute(params IEnumerable<int>[] sets) 
{ 
    if(sets.Length == 0) yield break; 
    if(sets.Length == 1) 
    { 
     foreach(var element in sets[0]) yield return new[] { element }; 
     yield break; 
    } 

    var first = sets.First(); 

    var rest = Permute(sets.Skip(1).ToArray()); 

    var elements = first.ToArray(); 

    foreach(var permutation in rest) 
    { 
     foreach(var element in elements) 
     { 
      var result = new int[permutation.Length + 1]; 
      result[0] = element; 
      Array.Copy(permutation, 0, result, 1, permutation.Length); 
      yield return result; 
     } 
    } 
} 
+0

=) это работает, и я счастлив, желаю вам отличного дня! – Andrea