Найти все наборы длины n комбинаций из m массивов

У меня были проблемы с реализациями, описанными выше, так как мой скрипт управляется из символического каталога или, по крайней мере, поэтому я думаю, что вышеупомянутые решения не сработали для меня. В соответствии с ответом @ ennuikiller я завернул свой Rscript в bash. Я устанавливаю переменную пути с помощью pwd -P, которая разрешает символические структуры каталогов. Затем передайте путь в Rscript.

Bash.sh

#!/bin/bash

# set path variable
path=`pwd -P`

#Run Rscript with path argument
Rscript foo.R $path

foo.R

args <- commandArgs(trailingOnly=TRUE)
setwd(args[1])
source(other.R)
0
задан mplungjan 18 January 2019 в 13:50
поделиться

1 ответ

Вы в основном хотите найти каждую перестановку каждого массива и объединить их. Это может быть сделано рекурсивно:

function permutate(arr) {
    // every array of length one is already permutated
    if (arr.length == 1) return [ arr ];
    let permutations = [];
    for (let i = 0; i < arr.length; i++) {
        // Remove the current element and permutate the rest
        let sub = permutate(arr.splice(i, 1));
        // Insert current element into every permutation
        sub = sub.map(x => [arr[i], ...x]);
        // Add permutations to list
        permutations.push(...sub);
    }
    return permutations;
}

Следующая функция объединения:

function combine(arrays, current = [], i = 0) {
    if (i == arrays.length)
        return [ current ];

    let values = [];

    for (let j = 0; j < arrays[i].length; j++) {
        let temp = current.slice();
        temp.push(arrays[i][j]);
        values.push(...combine(arrays, temp, i + 1));
    }

    return values;
}

// If you get a call stack size exceeded (stackoverflow) error, you can replace
// this using nested for loops. For instance for 5 arrays with 5 elements each:
let sets = [];
for (let i = 0; i < permutations[0].length; i++) {
  for (let j = 0; j < permutations[1].length; j++) {
    for (let k = 0; k < permutations[2].length; k++) {
      for (let l = 0; l < permutations[3].length; l++) {
        for (let m = 0; m < permutations[4].length; m++) {
            let set = [];
            for (let n = 0; n < 5; n++) {
                set.push([ permutations[0][i][n], permutations[1][j][n], permutations[2][k][n], permutations[3][l][n], permutations[4][m][n] ]);
            }
            sets.push(set);
        }
      }
    }
  }
}

Сначала переставляя каждый массив (что приводит к 24 различным перестановкам для каждого), затем объединяя их ( что составляет 24 ^ 4 = 331776 комбинаций), вы получите все, что вам нужно для построения массивов. Просто переберите каждую комбинацию и поместите элементы с одинаковыми индексами в один и тот же набор:

let permutations = [ array1, array2, array3, array4 ].map(arr => permutate(arr));

let sets = combine(permutations);
let out = [];
for (let i = 0; i < sets.length; i++) {
    let set = [];
    for (let j = 0; j < 4; j++) {
        set.push([ sets[i][0][j], sets[i][1][j], sets[i][2][j], sets[i][3][j] ]);
    }
    out.push(set);
}

Рабочий пример:

array1 = ['a', 'b', 'c', 'd'];
array2 = ['e', 'f', 'g', 'h'];
array3 = ['i', 'j', 'k', 'l'];
array4 = ['m', 'n', 'o', 'p'];

function permutate(arr) {
  if (arr.length == 1) return [ arr ];
  let permutations = [];
  for (let i = 0; i < arr.length; i++) {
    let temp = arr.slice();
    temp.splice(i, 1);
    let sub = permutate(temp);
    sub = sub.map(x => [arr[i], ...x]);
    permutations.push(...sub);
  }
  return permutations;
}

function combine(arrays, current = [], i = 0) {
	if (i == arrays.length)
		return [ current ];
	
	let values = [];
	
	for (let j = 0; j < arrays[i].length; j++) {
		let temp = current.slice();
		temp.push(arrays[i][j]);
		values.push(...combine(arrays, temp, i + 1));
	}
	
	return values;
}

let permutations = [ array1, array2, array3, array4 ].map(arr => permutate(arr));
console.log(permutations);

let sets = combine(permutations);
let out = [];
for (let i = 0; i < sets.length; i++) {
	let set = [];
	for (let j = 0; j < 4; j++) {
		set.push([ sets[i][0][j], sets[i][1][j], sets[i][2][j], sets[i][3][j] ]);
	}
	out.push(set);
}
console.log(out);
[114 ]

0
ответ дан Bálint 18 January 2019 в 13:50
поделиться
Другие вопросы по тегам:

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