Кажется, вы пытаетесь найти оптимальное решение, удваивая список источников, а затем перемешивая числа, многократно разбивая и объединяя массив.
Я думаю, что эта проблема поддается рекурсивному подходу. Создайте целевой массив с 2 * len(list)
пустыми слотами. (Независимо от того, является ли слот пустым или нет, его нужно пометить специальным значением, например -1
.) Затем рекурсивно попытаться вписать элементы исходного массива в целевой массив.
Давайте рассмотрим ваш пример{0, 1, 3}. Создайте целевой массив:
. . . . . .
Попробуйте все возможные зелья для 0. Первое -
0 0 . . . .
Теперь попробуйте соответствовать 1. Есть две возможности
0 0 . . . .
0 0 1 . 1 .
но это не будет соответствовать следующему элементу, 3. Вернитесь на один шаг назад:
0 0 . . . .
0 0 . 1 . 1
Здесь 3 тоже не вписываются. Мы исчерпали наш поиск этой позиции нулей, поэтому давайте возьмем следующую жизнеспособную позицию нулей:
. 0 0 . . .
Есть только один способ разместить одну:
. 0 0 . . .
. 0 0 1 . 1
Сейчасдавайте попробуем подобрать 3 и, бинго!, оно подходит:
. 0 0 . . .
. 0 0 1 . 1
3 0 0 1 3 1
Теперь вы можете остановить поиск или попытаться найти другие решения. В этом случае есть только одно решение, а именно отражение этого, но есть 300 способов разместить числа от 1 до 8, например, враг.
Этот подход в значительной степени грубая сила, но вНа практике, существует не так много правильных способов заполнения массива, поэтому неправильные пути обнаруживаются рано. Возможно, размещение первых чисел сначала даст лучшую производительность. Вы можете поиграть с этим и измерить его.
Вот программа, которая делает это. (Вероятно, это больше похоже на C, чем на Go. Не берите в голову.)
package main
import "fmt"
func fit_r(res[] int, a[] int, i int) int {
n := len(a);
if i == n {
fmt.Printf("%v\n", res);
return 1;
} else {
count := 0;
m := a[i];
for j := 0; j < 2*n - 1 - m; j++ {
if res[j] == -1 && res[j + 1 + m] == -1 {
// place values
res[j] = m;
res[j + 1 + m] = m;
// test further values
count += fit_r(res, a, i + 1);
// clean up and remove values again
res[j] = -1;
res[j + 1 + m] = -1;
}
}
return count;
}
}
func fit(a[] int) int {
res := make([] int, 2 * len(a));
for i := range res {
res[i] = -1;
}
return fit_r(res, a, 0);
}
func main() {
list := [] int {0, 1, 2, 3};
n := fit(list);
fmt.Println(n, "solutions");
}