2016-12-31 4 views
1

Я построил этот образец кода в Swift Playgrounds как доказательство концепции для части более крупного проекта, над которым я работаю. Что мне нужно сделать, это передать ряд опций (представленных optionsArray или testArray), где каждый int - количество доступных опций. Эти варианты в конечном итоге будут встроены в 300 миллионов отдельных PDF-файлов и файлов HTML. В настоящее время этот код работает, и выдает огромный список возможностей, которые я хочу.Лучший подход к рекурсии?

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

Вещи, которые я уже знаю: он не может обрабатывать значение 0, выходящее из массива. Массив является константой, поэтому это не произойдет случайно. То, как код в строке будет обрабатывать вещи, 0 - это бессмысленное значение для использования. Каждый элемент представляет количество доступных опций, поэтому 2 по существу является логическим, 1 будет false. Поэтому, если мне нужны элементы-заполнители для будущего расширения, они будут иметь значение 1 и отображаться как 0 в выводе.

Кроме того, конечный продукт будет не просто штриховым текстом на консоль в качестве вывода, он напишет файл в функции permutationEnding() на основе массива currentOptions.

let optionsArray: [Int] = [7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,2,2,2,2,2,2,2,2] 
let testArray: [Int] = [7,2,3,2] 
var currentOptions: [Int] = [] 
var outputString: String = "" 
func buildPermutations(array: Array<Int>) { 
    currentOptions.removeAll() 
    permutationRecursion(array: array, index: 0) 
} 
func permutationRecursion(array: Array<Int>, index: Int) { 
    for i in 1 ... array[index] { 
     currentOptions.append(Int(i-1)) 
     if array.count > (index + 1) { 
      permutationRecursion(array: array, index: index + 1) 
     } else { 
      permutationEnding() 
     } 
     currentOptions.removeLast() 
    } 
} 
func permutationEnding() { 
    for i in 1 ... currentOptions.count { // Output Elements 
     outputString += String(currentOptions[i-1]) 
    } 
    outputString += "\n" // Goes after output elements closing bracket. 
} 
// buildPermutations(array: optionsArray) 
buildPermutations(array: testArray) 
print(outputString) 

Мысли?

+0

Что именно вы пытаетесь сделать? Создайте список перестановок с помощью некоторых предопределенных опций? –

+0

По существу, да. У меня есть корпоративное приложение, которое позволяет людям проходить процесс собеседования, а некоторые из ответов, которые они дают, дают больше информации, которая будет помещена в PDF-файл, который динамически генерируется для них. Из-за характера работы, в которой я работаю, риск аудита для запуска пользовательского кода (PHP и т. Д.) На сервере является репрессивным, а варианты создания PDF на стороне клиента, которые используют JavaScript, в лучшем случае недостаточны. Меня попросили найти решение, которое не использует ни для веб-версии, аналогичной приложению. –

+0

Итак, мне нужно будет перекачивать HTML-шаблоны в эту вещь (как и в случае с существующим приложением), и выставлять * все * возможности как готовые PDF-файлы. В конце концов, мне также нужно будет построить все дерево решений как HTML, поэтому оно работает так, как это делает приложение. Выходы этого типа будут чем-то вроде 50101010011 ... и т. Д., Когда это будет сделано.Это смешно, но это позволяет нам иметь все варианты без использования технологии серверной стороны. Регуляторы могут сделать жизнь странной. –

ответ

0

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

Я получил это до четырех или пяти линий.

let n = testArray.count // for readability 
let products = ([Int](1...n)).map({testArray[$0..<n].reduce(1, *)}) 

// products is the cross product of element i + 1 to element n of the array for all i in the array 

let zipped = zip(testArray, products) 

for i in 0..<testArray.reduce(1, *) { // this reduce is the cross product of the whole array 

    let treePath = zipped.map(){ String(i/$0.1 % $0.0) }.joined() 
    outputString += treePath + "\n" 
} 

Еще одно редактирование: я думаю, что это может быть быстрее с некоторыми причудливыми матричными операциями, такими как NumPy. Интересно, может ли рамка Accelerate сделать для вас какую-то магию, но я не работал с ней.

редактировать: Мне было интересно, так что я засек с этим тест-массив

let testArray: [Int] = [7,2,2,2,2,2,2,3,2] 

рекурсивная функция в этом вопросе был: 132.56 сек

почтового индекса карта здесь был: 14,44 s

И он выглядит экспоненциальным, так как я добавляю элементы в тестовый массив.

+0

Это красота! Мне нужно немного поработать, чтобы понять, как это делается. Я также посмотрю на NumPy и посмотрю, что там можно найти. Спасибо за понимание и другое представление о том, как подойти к проблеме. –

+0

NumPy - это библиотека Python, которая очень быстро выполняет операции над целой матрицей/серией. Я читал, что структура ускорения может делать подобные вещи в ObjC/Swift. Из любопытства, это для компьютеризации руководящих принципов клинической практики/медицинской истории? –

+0

Это не так. Это для высоко настраиваемых учетных записей и вспомогательных услуг в финансовом учреждении. Процесс собеседования и его результирующие ответы (массив) по существу образуют дорожную карту для требований к учетной записи и рекомендуемых продуктов/услуг, связанных с ней. –

Смежные вопросы