Искусство Объема Программирования 4: Гроздь 3 имеет тонну их, которые могли бы соответствовать Вашей конкретной ситуации лучше, чем, как я описываю.
проблемой, с которой Вы столкнетесь, является, конечно, память и довольно быстро, у Вас будут проблемы 20 элементами в Вашем наборе - 20 глоток> C3 = 1140. И если Вы хотите выполнить итерации по набору, лучше использовать измененный алгоритм кода Грея, таким образом, Вы не держите всех их в памяти. Они генерируют следующую комбинацию от предыдущего и избегают повторений. Существуют многие из них для различного использования. Мы хотим максимизировать различия между последовательными комбинациями? минимизировать? и так далее.
Некоторые исходные бумаги, описывающие коды Грея:
Вот некоторые другие бумаги, затрагивающие тему:
Phillip J Преследование, ' Алгоритм 382: Комбинации M из Объектов N ' (1970)
алгоритм в C...
можно также сослаться на комбинацию ее индексом (в лексикографическом порядке). Понимание, что индекс должен быть некоторым количеством изменения справа налево на основе индекса, мы можем создать что-то, что должно восстановить комбинацию.
Так, у нас есть набор {1,2,3,4,5,6}..., и мы хотим три элемента. Скажем, {1,2,3} мы можем сказать, что различие между элементами один и в порядке и минимально. {1,2,4} имеет одно изменение и лексикографически номер 2. Таким образом, количество 'изменений' в последнем месте составляет одно изменение в лексикографическом упорядочивании. Второе место, с одним изменением {1,3,4} имеет одно изменение, но составляет больше изменения, так как это во-вторых (пропорционально числу элементов в исходном наборе).
метод, который я описал, является разрушением, как это кажется от набора до индекса, мы должны сделать реверс †“, который намного более хитер. Это - то, как Застежки решают проблему. Я записал [приблизительно 1 116] C для вычисления их с незначительными изменениями †“, я использовал индекс наборов, а не диапазона числа для представления набора, таким образом, мы всегда работаем от 0... n.Примечание:
существует иначе : его понятие легче схватить и программировать, но это без оптимизации Застежек. К счастью, это также не производит дублирующиеся комбинации:
набор , который максимизирует , где .
Для примера: 27 = C(6,4) + C(5,3) + C(2,2) + C(1,1)
. Так, 27-я лексикографическая комбинация четырех вещей: {1,2,5,6}, те - индексы любого набора, на который Вы хотите посмотреть. Пример ниже (OCaml), требует choose
функция, оставленная читателю:
(* this will find the [x] combination of a [set] list when taking [k] elements *)
let combination_maccaffery set k x =
(* maximize function -- maximize a that is aCb *)
(* return largest c where c < i and choose(c,i) <= z *)
let rec maximize a b x =
if (choose a b ) <= x then a else maximize (a-1) b x
in
let rec iterate n x i = match i with
| 0 -> []
| i ->
let max = maximize n i x in
max :: iterate n (x - (choose max i)) (i-1)
in
if x < 0 then failwith "errors" else
let idxs = iterate (List.length set) x k in
List.map (List.nth set) (List.sort (-) idxs)
следующие два алгоритма предоставлены для дидактических целей. Они реализуют итератор и (более общее) папка полные комбинации. Они максимально быстро, имея сложность O ( n глоток> C k). Потребление памяти связывается k
.
Мы запустим с итератора, который назовет пользователя предоставленным функции для каждой комбинации
let iter_combs n k f =
let rec iter v s j =
if j = k then f v
else for i = s to n - 1 do iter (i::v) (i+1) (j+1) done in
iter [] 0 0
А, более общая версия назовет пользователя предоставленным функции наряду с переменной состояния, начинающей с начального состояния. Так как мы должны передать состояние между различными состояниями, мы не будем использовать для цикла, но вместо этого, использовать рекурсию,
let fold_combs n k f x =
let rec loop i s c x =
if i < n then
loop (i+1) s c @@
let c = i::c and s = s + 1 and i = i + 1 in
if s < k then loop i s c x else f c x
else x in
loop 0 0 [] x
Мы закончили тем, что использовали службу для обработки долго выполняющихся запросов. Служба принимает рабочую нагрузку в качестве делегата, а затем передает ее BackgroundWorker, одновременно открывая наше представление «Пожалуйста, подождите».
Это работает хорошо, поскольку позволяет нам контролировать длительные процессы во всех наших ViewModels в одном и том же способом, с довольно простым интерфейсом.
Вы можете получать события, поступающие из ViewModel, обновлять View, когда вам нужна задержка, но тогда вам нужно иметь этот код во всех ваших ViewModel, а не в одном классе, который может быть поддерживать более легко.
РЕДАКТИРОВАТЬ Служба - это просто класс, зарегистрированный в вашем контейнере IOC, и может использоваться вашими ViewModels.
public interface IProcessingService
{
void Process(Action<BackgroundWorker> action);
void Process(Action<BackgroundWorker> action,
Action<RunWorkerCompletedEventArgs> finish);
}
Используя это, ваша ViewModel может реализовать что-то вроде этого.
Вы можете использовать прототип посредника, который создал Джош Смит, чтобы иметь слабосвязанную систему обмена сообщениями от виртуальной машины к виртуальной машине. VM может отправить сообщение о том, что она «занята», с помощью представление, подписывающееся на это сообщение «IsBusy».
Затем представление может отображать правильный диалог, пока не будет получено сообщение «IsNotBusy».
Другой вариант - передать ViewModel в конструкторе некоторый интерфейс, например IDialogProvider, который имеет методы чтобы показать диалог. Реализация этого поставщика будет зависеть от представления, но, по крайней мере, модель представления знает только об интерфейсе, а не о конкретной реализации.
public interface IDialogProvider
{
void ShowErrorMessage(string message);
}