Вывод списка массивов [Решено]
Цитата: BlendLog от 13.09.2022, 14:34Всем привет! Имеется такая задача, в которой нужно вывести список массивов, состоящий из 4 элементов, каждый элемент которого может принимать некоторое число от 1 до 8. При этом числа в массиве не должны повторяться между собой.
[spoiler title="Пример"]1 2 3 4 1 2 3 5 1 2 3 6 1 2 3 7 1 2 3 8 1 2 4 3 1 2 4 5 1 2 4 6 1 2 4 7 1 2 4 8 1 2 5 3 1 2 5 4 1 2 5 6 1 2 5 7 1 2 5 8 ...int[] main_arr = { 1, 1, 1, 0 }; async void add() { await Task.Run(() => { double countdown = Math.Pow(NumBase, power); while ((int)countdown != 0) { for (int i = main_arr.Length - 1; i >= 0; i--) { if (main_arr[i] == 8) { main_arr[i] = 1; } else { main_arr[i] += 1; break; } } if (!isRepeat(main_arr)) { print(main_arr); } countdown--; } }); } void print(int[] array) { for (int i = 0; i < array.Length; i++) { richTextBox1.Text += $"{array[i]} "; } richTextBox1.Text += "\n"; }[/spoiler]
Второе условие задачи, нужно чтобы сумма двух первых и двух последних чисел совпадала. Если совпадает, то выводим массив.
[spoiler title="Пример кода"]bool isEqual(int[] array) { int left_sum = 0; int right_sum = 0; for (int i = 0; i < array.Length / 2; i++) { left_sum += array[i]; } for (int i = array.Length / 2; i < array.Length; i++) { right_sum += array[i]; } return left_sum == right_sum; } ... if (!isRepeat(main_arr)) { if (isEqual(main_arr)) { print(main_arr); } }[/spoiler]
Вроде бы всё работает, но не пойму как убрать повторения массивов?1 7 3 5 1 7 5 3 //у обоих массивов сумма левой и правой части одинаковаКак сделать такой вывод массива без учёта перестановок? Пробовал добавлять массивы в
List<int[]>,каждый раз сортировать новый массив и делать посимвольное сравнение из этого общего списка, но программа тогда останавливается и ничего не выводит вовсе.
Всем привет! Имеется такая задача, в которой нужно вывести список массивов, состоящий из 4 элементов, каждый элемент которого может принимать некоторое число от 1 до 8. При этом числа в массиве не должны повторяться между собой.
1 2 3 4 1 2 3 5 1 2 3 6 1 2 3 7 1 2 3 8 1 2 4 3 1 2 4 5 1 2 4 6 1 2 4 7 1 2 4 8 1 2 5 3 1 2 5 4 1 2 5 6 1 2 5 7 1 2 5 8 ...
int[] main_arr = { 1, 1, 1, 0 };
async void add()
{
await Task.Run(() =>
{
double countdown = Math.Pow(NumBase, power);
while ((int)countdown != 0)
{
for (int i = main_arr.Length - 1; i >= 0; i--)
{
if (main_arr[i] == 8)
{
main_arr[i] = 1;
}
else
{
main_arr[i] += 1;
break;
}
}
if (!isRepeat(main_arr))
{
print(main_arr);
}
countdown--;
}
});
}
void print(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
richTextBox1.Text += $"{array[i]} ";
}
richTextBox1.Text += "\n";
}
Второе условие задачи, нужно чтобы сумма двух первых и двух последних чисел совпадала. Если совпадает, то выводим массив.
bool isEqual(int[] array)
{
int left_sum = 0;
int right_sum = 0;
for (int i = 0; i < array.Length / 2; i++)
{
left_sum += array[i];
}
for (int i = array.Length / 2; i < array.Length; i++)
{
right_sum += array[i];
}
return left_sum == right_sum;
}
...
if (!isRepeat(main_arr))
{
if (isEqual(main_arr))
{
print(main_arr);
}
}
Вроде бы всё работает, но не пойму как убрать повторения массивов?
1 7 3 5 1 7 5 3 //у обоих массивов сумма левой и правой части одинакова
Как сделать такой вывод массива без учёта перестановок? Пробовал добавлять массивы в СкопированоList<int[]>,каждый раз сортировать новый массив и делать посимвольное сравнение из этого общего списка, но программа тогда останавливается и ничего не выводит вовсе.
Цитата: Adler от 13.09.2022, 14:45Приветствую. На вскидку это все делается в один запрос средствами Linq. Дубликаты удаляются через Distinct(), а другие условия можно через Where() сделать.
Приветствую. На вскидку это все делается в один запрос средствами Linq. Дубликаты удаляются через Distinct(), а другие условия можно через Where() сделать.
Цитата: BlendLog от 13.09.2022, 14:55Цитата: Adler от 13.09.2022, 14:45Приветствую. В теории это все делается в одну строку через Linq. Дубликаты удаляются через Distinct(), а другие условия можно через Where() сделать.
Как правильно применить такую операцию? И можно ли вообще применять Distinct() к двумерному массиву?
Цитата: Adler от 13.09.2022, 14:45Приветствую. В теории это все делается в одну строку через Linq. Дубликаты удаляются через Distinct(), а другие условия можно через Where() сделать.
Как правильно применить такую операцию? И можно ли вообще применять Distinct() к двумерному массиву?
Цитата: Adler от 13.09.2022, 15:12Возможно я не совсем верно понял задачу, чуть позже вникну...
Возможно я не совсем верно понял задачу, чуть позже вникну...
Цитата: Viсtor от 13.09.2022, 17:30Цитата: Вячеслав от 13.09.2022, 14:34Всем привет! Имеется такая задача, в которой нужно вывести список массивов, состоящий из 4 элементов, каждый элемент которого может принимать некоторое число от 1 до 8. При этом числа в массиве не должны повторяться между собой.
Привет Вячеслав. Лично мне сложновато понять условия по такому описанию. Я могу понять примерно такое условие "Имеется такая задача, в которой нужно вывести список массивов. Массивы состоят из 4 элементов. Элемент массива это число от 1 до 8 включительно. Необходимо отсортировать массивы по двум условиям. Первое числа в массиве не должны повторяться между собой. Второе нужно чтобы сумма двух первых и двух последних чисел совпадала." Для такой формулировки могу предложить примерно такое решение.
[spoiler title="Входные данные"]internal static List<IEnumerable<int>> ListArrayInt = new List<IEnumerable<int>>() { new int[4]{ 1, 2, 3, 4 }, new int[4]{ 1, 2, 3, 5 }, new int[4]{ 1, 2, 3, 6 }, new int[4]{ 1, 2, 3, 7 }, new int[4]{ 1, 2, 3, 8 }, new int[4]{ 1, 2, 4, 3 }, new int[4]{ 1, 2, 4, 5 }, new int[4]{ 1, 2, 4, 6 }, new int[4]{ 1, 2, 4, 7 }, new int[4]{ 1, 2, 4, 8 }, new int[4]{ 1, 2, 5, 3 }, new int[4]{ 1, 2, 5, 4 }, new int[4]{ 1, 2, 5, 6 }, new int[4]{ 1, 2, 5, 7 }, new int[4]{ 1, 2, 5, 8 }, new int[4]{ 1, 7, 3, 5 }, new int[4]{ 1, 7, 5, 3 }, };[/spoiler]
[spoiler title="Сортировка"]
ListArrayInt.Where(x => { int[] array1 = x.ToArray()[0..2]; int[] array2 = x.ToArray()[2..]; if (array1.Distinct().Count() < array1.Length || array2.Distinct().Count() < array2.Length) return false; if (array1.Sum() != array2.Sum()) return false; else return true; }).ToList().ForEach(x => Console.WriteLine(string.Concat(x.Select(x => x.ToString()).Select(x => x.Replace(x,$" {x} ")))));[/spoiler]
Я не тестировал на нормальных входных данных. Если условия другие уточните, ох уж эти формулировки.🙂
Цитата: Вячеслав от 13.09.2022, 14:34Всем привет! Имеется такая задача, в которой нужно вывести список массивов, состоящий из 4 элементов, каждый элемент которого может принимать некоторое число от 1 до 8. При этом числа в массиве не должны повторяться между собой.
Привет Вячеслав. Лично мне сложновато понять условия по такому описанию. Я могу понять примерно такое условие "Имеется такая задача, в которой нужно вывести список массивов. Массивы состоят из 4 элементов. Элемент массива это число от 1 до 8 включительно. Необходимо отсортировать массивы по двум условиям. Первое числа в массиве не должны повторяться между собой. Второе нужно чтобы сумма двух первых и двух последних чисел совпадала." Для такой формулировки могу предложить примерно такое решение.
internal static List<IEnumerable<int>> ListArrayInt = new List<IEnumerable<int>>()
{
new int[4]{ 1, 2, 3, 4 },
new int[4]{ 1, 2, 3, 5 },
new int[4]{ 1, 2, 3, 6 },
new int[4]{ 1, 2, 3, 7 },
new int[4]{ 1, 2, 3, 8 },
new int[4]{ 1, 2, 4, 3 },
new int[4]{ 1, 2, 4, 5 },
new int[4]{ 1, 2, 4, 6 },
new int[4]{ 1, 2, 4, 7 },
new int[4]{ 1, 2, 4, 8 },
new int[4]{ 1, 2, 5, 3 },
new int[4]{ 1, 2, 5, 4 },
new int[4]{ 1, 2, 5, 6 },
new int[4]{ 1, 2, 5, 7 },
new int[4]{ 1, 2, 5, 8 },
new int[4]{ 1, 7, 3, 5 },
new int[4]{ 1, 7, 5, 3 },
};
ListArrayInt.Where(x =>
{
int[] array1 = x.ToArray()[0..2];
int[] array2 = x.ToArray()[2..];
if (array1.Distinct().Count() < array1.Length || array2.Distinct().Count() < array2.Length) return false;
if (array1.Sum() != array2.Sum()) return false;
else return true;
}).ToList().ForEach(x => Console.WriteLine(string.Concat(x.Select(x => x.ToString()).Select(x => x.Replace(x,$" {x} ")))));
Я не тестировал на нормальных входных данных. Если условия другие уточните, ох уж эти формулировки.🙂
Цитата: BlendLog от 13.09.2022, 19:11Цитата: Viktor от 13.09.2022, 17:30Цитата: Вячеслав от 13.09.2022, 14:34Всем привет! Имеется такая задача, в которой нужно вывести список массивов, состоящий из 4 элементов, каждый элемент которого может принимать некоторое число от 1 до 8. При этом числа в массиве не должны повторяться между собой.
Привет Вячеслав. Лично мне сложновато понять условия по такому описанию. Я могу понять примерно такое условие "Имеется такая задача, в которой нужно вывести список массивов. Массивы состоят из 4 элементов. Элемент массива это число от 1 до 8 включительно. Необходимо отсортировать массивы по двум условиям. Первое числа в массиве не должны повторяться между собой. Второе нужно чтобы сумма двух первых и двух последних чисел совпадала."
В примере под спойлером, где 1 2 3 4... это то, что выводит код ниже - это входные данные. Затем они обрабатываются вторым условием, то есть сумма правой и левой части должна совпадать. Но проблема в другом, как удалить дубликаты с одинаковыми суммами с обоих сторон, при этом оставив разные числа для каждого массива. Сортировать список не нужно, это я пытался таким образом посимвольно сравнивать элементы для каждого массива в списке, чтобы узнать, если ли этот массив уже там.
[spoiler title="Что выводит программа сейчас"]1 4 2 3 1 4 3 2 1 5 2 4 1 5 4 2 1 6 2 5 1 6 3 4 1 6 4 3 1 6 5 2 1 7 2 6 1 7 3 5 1 7 5 3 1 7 6 2 1 8 2 7 1 8 3 6 1 8 4 5 1 8 5 4 1 8 6 3 1 8 7 2 2 3 1 4 2 3 4 1 2 4 1 5 2 4 5 1 2 5 1 6 2 5 3 4 2 5 4 3 2 5 6 1 2 6 1 7 2 6 3 5 2 6 5 3 2 6 7 1 2 7 1 8 2 7 3 6 2 7 4 5 2 7 5 4 2 7 6 3 2 7 8 1 2 8 3 7 2 8 4 6 2 8 6 4 2 8 7 3 3 2 1 4 3 2 4 1 3 4 1 6 3 4 2 5 3 4 5 2 3 4 6 1 3 5 1 7 3 5 2 6 3 5 6 2 3 5 7 1 3 6 1 8 3 6 2 7 3 6 4 5 3 6 5 4 3 6 7 2 3 6 8 1 3 7 2 8 3 7 4 6 3 7 6 4 3 7 8 2 3 8 4 7 3 8 5 6 3 8 6 5 3 8 7 4 4 1 2 3 4 1 3 2 4 2 1 5 4 2 5 1 4 3 1 6 4 3 2 5 4 3 5 2 4 3 6 1 4 5 1 8 4 5 2 7 4 5 3 6 4 5 6 3 4 5 7 2 4 5 8 1 4 6 2 8 4 6 3 7 4 6 7 3 4 6 8 2 4 7 3 8 4 7 5 6 4 7 6 5 4 7 8 3 4 8 5 7 4 8 7 5 5 1 2 4 5 1 4 2 5 2 1 6 5 2 3 4 5 2 4 3 5 2 6 1 5 3 1 7 5 3 2 6 5 3 6 2 5 3 7 1 5 4 1 8 5 4 2 7 5 4 3 6 5 4 6 3 5 4 7 2 5 4 8 1 5 6 3 8 5 6 4 7 5 6 7 4 5 6 8 3 5 7 4 8 5 7 8 4 5 8 6 7 5 8 7 6 6 1 2 5 6 1 3 4 6 1 4 3 6 1 5 2 6 2 1 7 6 2 3 5 6 2 5 3 6 2 7 1 6 3 1 8 6 3 2 7 6 3 4 5 6 3 5 4 6 3 7 2 6 3 8 1 6 4 2 8 6 4 3 7 6 4 7 3 6 4 8 2 6 5 3 8 6 5 4 7 6 5 7 4 6 5 8 3 6 7 5 8 6 7 8 5 7 1 2 6 7 1 3 5 7 1 5 3 7 1 6 2 7 2 1 8 7 2 3 6 7 2 4 5 7 2 5 4 7 2 6 3 7 2 8 1 7 3 2 8 7 3 4 6 7 3 6 4 7 3 8 2 7 4 3 8 7 4 5 6 7 4 6 5 7 4 8 3 7 5 4 8 7 5 8 4 7 6 5 8 7 6 8 5 8 1 2 7 8 1 3 6 8 1 4 5 8 1 5 4 8 1 6 3 8 1 7 2 8 2 3 7 8 2 4 6 8 2 6 4 8 2 7 3 8 3 4 7 8 3 5 6 8 3 6 5 8 3 7 4 8 4 5 7 8 4 7 5 8 5 6 7 8 5 7 6[/spoiler]
Как мне удалить такие вот дубликаты?
[spoiler title="Спойлер"]... 8 4 5 7 8 4 7 5 //дубликат массива выше 8 5 6 7 8 5 7 6 //дубликат массива вышеУ них просто 2 последних числа поменялись местами, и так почти во всем списке.
[/spoiler]
Цитата: Viktor от 13.09.2022, 17:30Цитата: Вячеслав от 13.09.2022, 14:34Всем привет! Имеется такая задача, в которой нужно вывести список массивов, состоящий из 4 элементов, каждый элемент которого может принимать некоторое число от 1 до 8. При этом числа в массиве не должны повторяться между собой.
Привет Вячеслав. Лично мне сложновато понять условия по такому описанию. Я могу понять примерно такое условие "Имеется такая задача, в которой нужно вывести список массивов. Массивы состоят из 4 элементов. Элемент массива это число от 1 до 8 включительно. Необходимо отсортировать массивы по двум условиям. Первое числа в массиве не должны повторяться между собой. Второе нужно чтобы сумма двух первых и двух последних чисел совпадала."
В примере под спойлером, где 1 2 3 4... это то, что выводит код ниже - это входные данные. Затем они обрабатываются вторым условием, то есть сумма правой и левой части должна совпадать. Но проблема в другом, как удалить дубликаты с одинаковыми суммами с обоих сторон, при этом оставив разные числа для каждого массива. Сортировать список не нужно, это я пытался таким образом посимвольно сравнивать элементы для каждого массива в списке, чтобы узнать, если ли этот массив уже там.
1 4 2 3 1 4 3 2 1 5 2 4 1 5 4 2 1 6 2 5 1 6 3 4 1 6 4 3 1 6 5 2 1 7 2 6 1 7 3 5 1 7 5 3 1 7 6 2 1 8 2 7 1 8 3 6 1 8 4 5 1 8 5 4 1 8 6 3 1 8 7 2 2 3 1 4 2 3 4 1 2 4 1 5 2 4 5 1 2 5 1 6 2 5 3 4 2 5 4 3 2 5 6 1 2 6 1 7 2 6 3 5 2 6 5 3 2 6 7 1 2 7 1 8 2 7 3 6 2 7 4 5 2 7 5 4 2 7 6 3 2 7 8 1 2 8 3 7 2 8 4 6 2 8 6 4 2 8 7 3 3 2 1 4 3 2 4 1 3 4 1 6 3 4 2 5 3 4 5 2 3 4 6 1 3 5 1 7 3 5 2 6 3 5 6 2 3 5 7 1 3 6 1 8 3 6 2 7 3 6 4 5 3 6 5 4 3 6 7 2 3 6 8 1 3 7 2 8 3 7 4 6 3 7 6 4 3 7 8 2 3 8 4 7 3 8 5 6 3 8 6 5 3 8 7 4 4 1 2 3 4 1 3 2 4 2 1 5 4 2 5 1 4 3 1 6 4 3 2 5 4 3 5 2 4 3 6 1 4 5 1 8 4 5 2 7 4 5 3 6 4 5 6 3 4 5 7 2 4 5 8 1 4 6 2 8 4 6 3 7 4 6 7 3 4 6 8 2 4 7 3 8 4 7 5 6 4 7 6 5 4 7 8 3 4 8 5 7 4 8 7 5 5 1 2 4 5 1 4 2 5 2 1 6 5 2 3 4 5 2 4 3 5 2 6 1 5 3 1 7 5 3 2 6 5 3 6 2 5 3 7 1 5 4 1 8 5 4 2 7 5 4 3 6 5 4 6 3 5 4 7 2 5 4 8 1 5 6 3 8 5 6 4 7 5 6 7 4 5 6 8 3 5 7 4 8 5 7 8 4 5 8 6 7 5 8 7 6 6 1 2 5 6 1 3 4 6 1 4 3 6 1 5 2 6 2 1 7 6 2 3 5 6 2 5 3 6 2 7 1 6 3 1 8 6 3 2 7 6 3 4 5 6 3 5 4 6 3 7 2 6 3 8 1 6 4 2 8 6 4 3 7 6 4 7 3 6 4 8 2 6 5 3 8 6 5 4 7 6 5 7 4 6 5 8 3 6 7 5 8 6 7 8 5 7 1 2 6 7 1 3 5 7 1 5 3 7 1 6 2 7 2 1 8 7 2 3 6 7 2 4 5 7 2 5 4 7 2 6 3 7 2 8 1 7 3 2 8 7 3 4 6 7 3 6 4 7 3 8 2 7 4 3 8 7 4 5 6 7 4 6 5 7 4 8 3 7 5 4 8 7 5 8 4 7 6 5 8 7 6 8 5 8 1 2 7 8 1 3 6 8 1 4 5 8 1 5 4 8 1 6 3 8 1 7 2 8 2 3 7 8 2 4 6 8 2 6 4 8 2 7 3 8 3 4 7 8 3 5 6 8 3 6 5 8 3 7 4 8 4 5 7 8 4 7 5 8 5 6 7 8 5 7 6
Как мне удалить такие вот дубликаты?
... 8 4 5 7 8 4 7 5 //дубликат массива выше 8 5 6 7 8 5 7 6 //дубликат массива выше
У них просто 2 последних числа поменялись местами, и так почти во всем списке.
Цитата: Viсtor от 13.09.2022, 23:02Я плоховат в LINQ, но это вроде работает.
[spoiler title="Код"].Select(x => { int[] ar = x.ToArray(); return ($"{ar[0]}{ar[1]}", $"{ar[2]}{ar[3]}"); }); IEnumerable<(string, string)> resDistinc = res2.DistinctBy(x => x.Item1).DistinctBy(x => x.Item2); var res1 = (resDistinc.Select(x => x.Item1.ToCharArray().Select(x => int.Parse(x.ToString()))), resDistinc.Select(x=> x.Item2.ToCharArray().Select(x => int.Parse(x.ToString())))); var retRes = new List<int[]>(); for (int i = 0; i < res1.Item1.Count(); i++) { retRes.Add(new int[] { res1.Item1.ToArray()[i].ToArray()[0], res1.Item1.ToArray()[i].ToArray()[1], res1.Item2.ToArray()[i].ToArray()[0], res1.Item2.ToArray()[i].ToArray()[1] }); }
[/spoiler]
P.S. А почему нету кнопки со спойлером?
Я плоховат в LINQ, но это вроде работает.
.Select(x =>
{
int[] ar = x.ToArray();
return ($"{ar[0]}{ar[1]}", $"{ar[2]}{ar[3]}");
});
IEnumerable<(string, string)> resDistinc = res2.DistinctBy(x => x.Item1).DistinctBy(x => x.Item2);
var res1 = (resDistinc.Select(x => x.Item1.ToCharArray().Select(x => int.Parse(x.ToString()))), resDistinc.Select(x=> x.Item2.ToCharArray().Select(x => int.Parse(x.ToString()))));
var retRes = new List<int[]>();
for (int i = 0; i < res1.Item1.Count(); i++)
{
retRes.Add(new int[] { res1.Item1.ToArray()[i].ToArray()[0], res1.Item1.ToArray()[i].ToArray()[1], res1.Item2.ToArray()[i].ToArray()[0], res1.Item2.ToArray()[i].ToArray()[1] });
}
P.S. А почему нету кнопки со спойлером?
Цитата: Андрей от 14.09.2022, 08:06Добрый день.
P.S. А почему нету кнопки со спойлером?
Это какой-то глюк движка форума.
Есть такой вариант: формируем пост без спойлера, публикуем и сразу редактируем. В режиме редактирования кнопка спойлера есть всегда.
В режиме ответа кнопка спойлера то есть, то нет, какой-то глюк движка форума.
Добрый день.
P.S. А почему нету кнопки со спойлером?
Это какой-то глюк движка форума.
Есть такой вариант: формируем пост без спойлера, публикуем и сразу редактируем. В режиме редактирования кнопка спойлера есть всегда.
В режиме ответа кнопка спойлера то есть, то нет, какой-то глюк движка форума.
Цитата: BlendLog от 14.09.2022, 08:38Цитата: Viktor от 13.09.2022, 23:02Я плоховат в LINQ, но это вроде работает.
ругается на res2. Откуда это?
[spoiler title="Оффтоп"]
В firefox нету спойлера, а в edge есть 🤷♂️
[/spoiler]
Цитата: Viktor от 13.09.2022, 23:02Я плоховат в LINQ, но это вроде работает.
ругается на res2. Откуда это?
В firefox нету спойлера, а в edge есть 🤷♂️
Цитата: Viсtor от 14.09.2022, 12:40Это результат прошлой сортировки из прошлого поста, только тут строчку почистил т.к фигню написал. Логика тут такая. ↓
[spoiler title="Картинка"][/spoiler]
Просто есть методы в LINQ, которые позволяют это сделать проще. Я пока мало знаю.
Это результат прошлой сортировки из прошлого поста, только тут строчку почистил т.к фигню написал. Логика тут такая. ↓

Просто есть методы в LINQ, которые позволяют это сделать проще. Я пока мало знаю.
Цитата: Dapofig от 14.09.2022, 17:06Приветствую.
Если нет никаких ограничений по производительности, можно решить задачу полностью на LINQ. Проверка уникальности и удаление дубликатов реализовывается через HashSet коллекцию, которая не может содержать повторяющиеся элементы. В принципе, можно и обычный List использовать, только с дополнительной проверкой существования элемента в коллекции. Ещё один вариант – использовать метод расширения Distinct из LINQ с собственной логикой сравнения.
Уверен, что некоторые методы можно реализовать проще, но надеюсь направлю в нужном направлении, если, конечно, условие понял правильно 🙃
[spoiler title="Листинг"]public class ProblemSolver { private readonly HashSet<int> _hashSet = new HashSet<int>(); public List<IEnumerable<int>> GetSets() { return Enumerable.Range(1000, 9000) .Select(ConvertToSetOfDigits) .Where(DigitsInRange) .Where(UniqueDigits) .Where(EqualSides) .Where(DistinctPermutations) .ToList(); } private IEnumerable<int> ConvertToSetOfDigits(int number) { return number.ToString().Select(c => int.Parse(c.ToString())); } private bool DigitsInRange(IEnumerable<int> set) { return set.All(digit => 1 <= digit && digit <= 8); } private bool UniqueDigits(IEnumerable<int> set) { return set.ToHashSet().Count == 4; } private bool EqualSides(IEnumerable<int> set) { return set.Take(2).Sum() == set.TakeLast(2).Sum(); } private bool DistinctPermutations(IEnumerable<int> set) { var leftSide = set.Take(2).OrderBy(digit => digit); var rightSide = set.TakeLast(2).OrderBy(digit => digit); return _hashSet.Add(leftSide.Concat(rightSide).Aggregate((digit, acc) => acc += digit * 10)); } }[/spoiler]
Приветствую.
Если нет никаких ограничений по производительности, можно решить задачу полностью на LINQ. Проверка уникальности и удаление дубликатов реализовывается через HashSet коллекцию, которая не может содержать повторяющиеся элементы. В принципе, можно и обычный List использовать, только с дополнительной проверкой существования элемента в коллекции. Ещё один вариант – использовать метод расширения Distinct из LINQ с собственной логикой сравнения.
Уверен, что некоторые методы можно реализовать проще, но надеюсь направлю в нужном направлении, если, конечно, условие понял правильно 🙃
public class ProblemSolver
{
private readonly HashSet<int> _hashSet = new HashSet<int>();
public List<IEnumerable<int>> GetSets()
{
return Enumerable.Range(1000, 9000)
.Select(ConvertToSetOfDigits)
.Where(DigitsInRange)
.Where(UniqueDigits)
.Where(EqualSides)
.Where(DistinctPermutations)
.ToList();
}
private IEnumerable<int> ConvertToSetOfDigits(int number)
{
return number.ToString().Select(c => int.Parse(c.ToString()));
}
private bool DigitsInRange(IEnumerable<int> set)
{
return set.All(digit => 1 <= digit && digit <= 8);
}
private bool UniqueDigits(IEnumerable<int> set)
{
return set.ToHashSet().Count == 4;
}
private bool EqualSides(IEnumerable<int> set)
{
return set.Take(2).Sum() == set.TakeLast(2).Sum();
}
private bool DistinctPermutations(IEnumerable<int> set)
{
var leftSide = set.Take(2).OrderBy(digit => digit);
var rightSide = set.TakeLast(2).OrderBy(digit => digit);
return _hashSet.Add(leftSide.Concat(rightSide).Aggregate((digit, acc) => acc += digit * 10));
}
}
Цитата: BlendLog от 14.09.2022, 20:46@farmv, теперь ругается на DistinctBy, говорит не знает такого метода, предлагает заменить на Distinct, но тогда ругается на Item1, мол нельзя преобразовать лямбда выражение. У меня Net Core 3, если что.
@dapofig, ограничений по памяти нет. Задача вроде бы решена сортировкой каждой последовательности из списка и приведение её к String, но вариант с выводом не устроил. Да, условия по сумме левой и правой части соблюдаются циклом перед выводом, но визуально это не воспринимается.
@farmv, теперь ругается на DistinctBy, говорит не знает такого метода, предлагает заменить на Distinct, но тогда ругается на Item1, мол нельзя преобразовать лямбда выражение. У меня Net Core 3, если что.
@dapofig, ограничений по памяти нет. Задача вроде бы решена сортировкой каждой последовательности из списка и приведение её к String, но вариант с выводом не устроил. Да, условия по сумме левой и правой части соблюдаются циклом перед выводом, но визуально это не воспринимается.
Цитата: Вася от 14.09.2022, 22:44Привет!
Генерацию входной последовательности (двумерного массива для тестирования) и фильтрацию с условиями сделал через методы расширения:[spoiler title="Методы расширения"]
using System; using System.Collections.Generic; using System.Linq; using static System.Linq.Enumerable; namespace ConsoleApp { public static class ExtendedEnumerable { /// <summary> /// Разбивает последовательность на равные по количеству подпоследовательности. /// </summary> /// <param name="numberOfSubSequences">Количество подпоследовательностей</param> /// <exception cref="ArgumentException"></exception> public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int numberOfSubSequences) { var sourceCount = source.Count(); if (numberOfSubSequences < 1) { throw new ArgumentException($"Не возможно разбить последовательность на {numberOfSubSequences} равных подпоследовательностей!"); } if (sourceCount % numberOfSubSequences != 0) { throw new ArgumentException($"Не возможно разбить последовательность размером {sourceCount} на {numberOfSubSequences} равных подпоследовательностей!"); } var subSequences = new T[numberOfSubSequences][]; var sequenceCount = sourceCount / numberOfSubSequences; var sourceEnumerator = source.GetEnumerator(); while (sourceEnumerator.MoveNext()) { for (var i = 0; i < numberOfSubSequences; i++) { var part = new T[sequenceCount]; for (var j = 0; j < sequenceCount; j++) { part[j] = sourceEnumerator.Current; sourceEnumerator.MoveNext(); } subSequences[i] = part; } } return subSequences; } /// <summary> /// Фильтрует последовательность по заданным условиям. /// </summary> /// <param name="conditions">Последовательность условий фильтрации</param> /// <returns></returns> public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, IEnumerable<Predicate<T>> conditions) { return source.Where((item) => conditions.Aggregate(true, (result, condition) => result && condition(item))); } /// <summary> /// Генерирует все возможные перестановки элементов последовательности с повторениями. /// </summary> /// <param name="selectionCount">Количество элементов выборки</param> /// <exception cref="ArgumentException"></exception> public static IEnumerable<IEnumerable<T>> PermutationsWithRepetition<T>(this IEnumerable<T> source, int selectionCount) { var sourceCount = source.Count(); if (selectionCount < 0) { throw new ArgumentException("Количество элементов не может быть меньше нуля!"); } if (selectionCount == 0) { return Empty<IEnumerable<T>>(); } if (selectionCount == 1) { return source.Split(sourceCount); } var permutationsCount = (int)Math.Pow(sourceCount, selectionCount); var permutations = new List<IEnumerable<T>>(permutationsCount); foreach (var item in source) { foreach (var placement in PermutationsWithRepetition(source, selectionCount - 1)) { permutations.Add(placement.Prepend(item)); } } return permutations; } /// <summary> /// Генерирует все возможные перестановки элементов последовательности без повторений. /// </summary> /// <param name="selectionCount">Количество элементов выборки</param> /// <exception cref="ArgumentException"></exception> public static IEnumerable<IEnumerable<T>> PermutationsWithoutRepetition<T>(this IEnumerable<T> source, int selectionCount) { return PermutationsWithRepetition(source, selectionCount).Where((sequence) => sequence.Distinct().Count() == sequence.Count()); } } }[/spoiler]
Для отсеивания дубликатов сделал Comparer, только не уверен насчёт метода генерации хеш кода, но с задачей вроде справляется.
[spoiler title="IntSequenceComparer"]using System.Collections.Generic; using System.Linq; namespace ConsoleApp { public class IntSequenceComparer : IEqualityComparer<IEnumerable<int>> { /// <summary> /// Сравнивает последовательности без учёта порядка элементов. /// </summary> public bool Equals(IEnumerable<int> first, IEnumerable<int> second) { return first.Except(second).SequenceEqual(Enumerable.Empty<int>()); } /// <summary> /// Генерирует уникальное значение последовательности без учёта порядка элементов. /// </summary> public int GetHashCode(IEnumerable<int> sequence) { return sequence.Sum() * sequence.Count(); } } }[/spoiler]
Ну и, собственно, использование этого всего:
[spoiler title="Main метод"]using System; using System.Collections.Generic; using System.Linq; using static System.Console; namespace ConsoleApp { internal class Program { public static void Main(string[] args) { const int numberOfParts = 2; const int selectionCount = 4; const int min = 1; const int max = 9; // Условия фильтрации var conditions = new Predicate<IEnumerable<int>>[] { // Элементы не повторяются. (collection) => collection.Distinct().Count() == collection.Count(), // Суммы всех (в нашем случае двух) частей равны (collection) => collection.Split(numberOfParts).GroupBy((item) => item.Sum()).Count() == 1, }; // Генерация входной последовательности var inputSequence = Enumerable.Range(min, max - min).PermutationsWithRepetition(selectionCount); // Фильтрация входной последовательности var outputSequence = inputSequence.Filter(conditions).Distinct(new IntSequenceComparer()); Print(outputSequence); ReadKey(); } private static void Print<T>(IEnumerable<T> collection) { foreach (var item in collection) { Write($"{item} "); } WriteLine(); } private static void Print<T>(IEnumerable<IEnumerable<T>> collection) { foreach (var item in collection) { Print(item); } } } }[/spoiler]
[spoiler title="Результат"][/spoiler]
Привет!
Генерацию входной последовательности (двумерного массива для тестирования) и фильтрацию с условиями сделал через методы расширения:
using System;
using System.Collections.Generic;
using System.Linq;
using static System.Linq.Enumerable;
namespace ConsoleApp
{
public static class ExtendedEnumerable
{
/// <summary>
/// Разбивает последовательность на равные по количеству подпоследовательности.
/// </summary>
/// <param name="numberOfSubSequences">Количество подпоследовательностей</param>
/// <exception cref="ArgumentException"></exception>
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int numberOfSubSequences)
{
var sourceCount = source.Count();
if (numberOfSubSequences < 1)
{
throw new ArgumentException($"Не возможно разбить последовательность на {numberOfSubSequences} равных подпоследовательностей!");
}
if (sourceCount % numberOfSubSequences != 0)
{
throw new ArgumentException($"Не возможно разбить последовательность размером {sourceCount} на {numberOfSubSequences} равных подпоследовательностей!");
}
var subSequences = new T[numberOfSubSequences][];
var sequenceCount = sourceCount / numberOfSubSequences;
var sourceEnumerator = source.GetEnumerator();
while (sourceEnumerator.MoveNext())
{
for (var i = 0; i < numberOfSubSequences; i++)
{
var part = new T[sequenceCount];
for (var j = 0; j < sequenceCount; j++)
{
part[j] = sourceEnumerator.Current;
sourceEnumerator.MoveNext();
}
subSequences[i] = part;
}
}
return subSequences;
}
/// <summary>
/// Фильтрует последовательность по заданным условиям.
/// </summary>
/// <param name="conditions">Последовательность условий фильтрации</param>
/// <returns></returns>
public static IEnumerable<T> Filter<T>(this IEnumerable<T> source, IEnumerable<Predicate<T>> conditions)
{
return source.Where((item) => conditions.Aggregate(true, (result, condition) => result && condition(item)));
}
/// <summary>
/// Генерирует все возможные перестановки элементов последовательности с повторениями.
/// </summary>
/// <param name="selectionCount">Количество элементов выборки</param>
/// <exception cref="ArgumentException"></exception>
public static IEnumerable<IEnumerable<T>> PermutationsWithRepetition<T>(this IEnumerable<T> source, int selectionCount)
{
var sourceCount = source.Count();
if (selectionCount < 0)
{
throw new ArgumentException("Количество элементов не может быть меньше нуля!");
}
if (selectionCount == 0)
{
return Empty<IEnumerable<T>>();
}
if (selectionCount == 1)
{
return source.Split(sourceCount);
}
var permutationsCount = (int)Math.Pow(sourceCount, selectionCount);
var permutations = new List<IEnumerable<T>>(permutationsCount);
foreach (var item in source)
{
foreach (var placement in PermutationsWithRepetition(source, selectionCount - 1))
{
permutations.Add(placement.Prepend(item));
}
}
return permutations;
}
/// <summary>
/// Генерирует все возможные перестановки элементов последовательности без повторений.
/// </summary>
/// <param name="selectionCount">Количество элементов выборки</param>
/// <exception cref="ArgumentException"></exception>
public static IEnumerable<IEnumerable<T>> PermutationsWithoutRepetition<T>(this IEnumerable<T> source, int selectionCount)
{
return PermutationsWithRepetition(source, selectionCount).Where((sequence) => sequence.Distinct().Count() == sequence.Count());
}
}
}
Для отсеивания дубликатов сделал Comparer, только не уверен насчёт метода генерации хеш кода, но с задачей вроде справляется.
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp
{
public class IntSequenceComparer : IEqualityComparer<IEnumerable<int>>
{
/// <summary>
/// Сравнивает последовательности без учёта порядка элементов.
/// </summary>
public bool Equals(IEnumerable<int> first, IEnumerable<int> second)
{
return first.Except(second).SequenceEqual(Enumerable.Empty<int>());
}
/// <summary>
/// Генерирует уникальное значение последовательности без учёта порядка элементов.
/// </summary>
public int GetHashCode(IEnumerable<int> sequence)
{
return sequence.Sum() * sequence.Count();
}
}
}
Ну и, собственно, использование этого всего:
using System;
using System.Collections.Generic;
using System.Linq;
using static System.Console;
namespace ConsoleApp
{
internal class Program
{
public static void Main(string[] args)
{
const int numberOfParts = 2;
const int selectionCount = 4;
const int min = 1;
const int max = 9;
// Условия фильтрации
var conditions = new Predicate<IEnumerable<int>>[]
{
// Элементы не повторяются.
(collection) => collection.Distinct().Count() == collection.Count(),
// Суммы всех (в нашем случае двух) частей равны
(collection) => collection.Split(numberOfParts).GroupBy((item) => item.Sum()).Count() == 1,
};
// Генерация входной последовательности
var inputSequence = Enumerable.Range(min, max - min).PermutationsWithRepetition(selectionCount);
// Фильтрация входной последовательности
var outputSequence = inputSequence.Filter(conditions).Distinct(new IntSequenceComparer());
Print(outputSequence);
ReadKey();
}
private static void Print<T>(IEnumerable<T> collection)
{
foreach (var item in collection)
{
Write($"{item} ");
}
WriteLine();
}
private static void Print<T>(IEnumerable<IEnumerable<T>> collection)
{
foreach (var item in collection)
{
Print(item);
}
}
}
}

Цитата: BlendLog от 15.09.2022, 09:06Цитата: Вася от 14.09.2022, 22:44Привет!
Генерацию входной последовательности (двумерного массива для тестирования) и фильтрацию с условиями сделал через методы расширения...Благодарю за помощь, это то, что нужно!
Цитата: Вася от 14.09.2022, 22:44Привет!
Генерацию входной последовательности (двумерного массива для тестирования) и фильтрацию с условиями сделал через методы расширения...
Благодарю за помощь, это то, что нужно!
