powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Сочетания. Реализация. Вопросы и предложения
14 сообщений из 14, страница 1 из 1
Сочетания. Реализация. Вопросы и предложения
    #38818967
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.
Решил создать новую тему, ибо мне кажется данную задачу можно решить разными способами, и акцент в данном случае не идёт на длинную арифметику. Проблема была в том, что мы хотели сократить знаменатель к единице. Если администрация считает что не стоит создавать новый топик, то не возражаю чтобы, его закрыли.
То что требуется я реализовал сегодня.

Вспомогательные моменты.



Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
struct Number
{
	int num;
	int num2;
	int count;
	int* multipliers;
};

struct Number* initializeNumber(int a)
{
	struct Number* n = (struct Number*)malloc(sizeof(struct Number));
	n->num = a;
	n->num2 = a;
	n->count = 0;
	n->multipliers = NULL;
}

int viewNumber(struct Number* a)
{
	printf("num= %i\n", a->num);
	printf("num2= %i\n", a->num2);
	printf("divisors:");
	for (int i = 0; i < a->count; ++i)
	{
		printf("%i ", a->multipliers[i]);
	}
	printf("\n");
	return 0;
}

//assume a->num > 1
int factorization(struct Number* a)
{
	for (int i = 2; i<=a->num2; ++i) 
	{
		if (a->num2%i == 0)
		{
			a->count += 1;
			a->multipliers = (int*)realloc(a->multipliers, a->count*sizeof(int));
			a->multipliers[a->count - 1] = i;
			
			a->num2 /= i;
			factorization(a);
			break;
		}
	}
	return 0;
}



Как работает factorization. Например на входе 150, находит первый делитель слева 2, дальше рекурсивный запуск 75, находим 3, дальше рекурсивный запус 25, находим 5, дальше рекурсивный запуск 5, находим 5, рекурсивный запуск на 1, приводит к завершению. Вместо 150 получаем массив 2 3 5 5 .
Возможно данную функцию можно реализовать лучше, буду рад предложениям.

Вы наверное догадались зачем нужна эта функция. Фиксируем элемент знаменателя, и пытаемся найти такой элемент числитель, что a%b==0,если такой элемент не найден, то фиксированный элемент знаменателя раскладываем на простейшие и расширяем массив знаменателя . Вместо 150 у нас появится 4 числа 2 3 5 5 . Ниже код


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
//Сочетания
char* la_combination(unsigned n, unsigned m)
{
	m = (n - m > m) ? m : n-m;
	int* up = (int*)malloc(sizeof(int)*m);//числитель
	int* down = (int*)malloc(sizeof(int)*m);//знаменатель

	for (int i = 1; i <= m; ++i)
	{
		*(up + m - i) = n - m + i;
		*(down + m - i) = i;
	}
#ifdef DEBUG
	for (int i = 0; i < m; ++i)
		printf("%i ", up[i]);
	printf("\n");
	for (int i = 0; i < m; ++i)
		printf("%i ", down[i]);
	printf("\n");
#endif

	int len_down = m;
	for (int i = 0; i < len_down; ++i)//1 проход по знаменателю, длина знаменателя меняется
	{
		if (down[i] != 1)
		{
			int j = 0;
			for (j = 0; j < m; ++j)//проход по числителю
			{
				if (!(up[j] % down[i]))
				{
					up[j] /= down[i];
					down[i] = 1;
					break;
				}
			}
			if (j == m && down[i]!=1) //если перебрали все элементы числителя, а фиксированный элемент знаменателя не сократили
			{
				struct Number* n = initializeNumber(down[i]);
				factorization(n); //раскладываю число на множители
				down[i] = 1;
				len_down += n->count;
				down = (int*)realloc(down, sizeof(int)*len_down);
				for (int i = 0; i < n->count; ++i)
				{
					down[len_down - n->count + i] = n->multipliers[i];
				}
				free(n->multipliers);
				free(n);
			}
		}
	}
#ifdef DEBUG
	for (int i = 0; i < m; ++i)
		printf("%i ", up[i]);
	printf("\n");
	for (int i = 0; i < len_down; ++i)
		printf("%i ", down[i]);
	printf("\n");
#endif
	char* res="1";
	char* t = (char*)malloc(10);
	for (int i = 0; i < m; ++i)
	{
		sprintf(t, "%d", up[i]);
		res = la_multiplication(res, t);
	}
	free(t);
	return res;
}



На функцию la_multiplication(res, t) можно не обращать внимание (но если нужна она реализована в соседнем топе), это сложение двух строк.


Мне интересно как вы бы решили аналогичную задачу, ну и возможно у кого-то есть замечания по рефакторингу кода, оптимизации алгоритмов, и конечно-же организации данных. (Может стоит создать статическую переменную под длину массива, и не создавать структуру, например)


PS
Вчера с трудом заснул и снились кошмары(из-за того что меня одолевали сомнения по тернарному оператору). Всё-таки не стоит использовать С++ только из-за расширенных возможностей тернарного оператора, сегодня изменил весь код в длинной арифметике на код Си.
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819429
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ребята, у меня сегодня был мой первый memory leak !!! Буквально 3 часа назад
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819436
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В том смысле, что во время выполнения программы, появилось сообщение Memory leak, и выполнение программы остановилось Первый раз !
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819443
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поздравляю. Прям как первый раз с женщиной....

А зачем тут рекурсия? Ну ... как-бы обычно ее используют там
где она удобна и наглядна. Деревья поиска там. Обход сложных
связных структур. А тут?
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819444
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryмой первый memory leak
Ага, щас. Далеко уже не первый. Мы просто жалели вас, не сообщали горькую правду :)

ЗЫ. Ничего страшного. У половины человечества ежемесячно бывает leak, и ничего, живут
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819455
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky,

были раньше, но программа никогда не вылетала. А тут вылетела, и всё как надо, сообщение, мол у вас Memory leak, получите распишитесь !
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819468
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton, спасибо :)
Ну а как тут без рекурсии ? Интуитивно она больше всего подходит. Я ведь не все делители числа ищу, а раскладываю число на минимальные множители (по факту на произведение простых чисел)
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819661
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
for (int i = 2; i<=a->num2; ++i) 
	{
		if (a->num2%i == 0)


О некоторых граблях с топорами.

Я расскажу для НЕ-рекурсивного варианта. То как я кодил факторизацию сам.
А ты уж подумай как эту инфу переварить.

Во первых. Не нужно делить на чётные. Нужно деление на 2
вынести из тела цикла. И захардкодить.

А цикл делать начиная от 3 и с шагом в 2.

И верхняя граница должна быть не до числа N которое ты проверяешь
а до SQRT(N). До квадратного корня.

Для квадратного корня не нужно брать вещественный кастинг.
Есть эффективный расчёт для целочисленного корня.
Есть оптимизации на базе производной от этого-же корня.

Уже расчитанные primes нужно складывать в кеш и использовать
их при разложении других неизвестных составных чисел.

Кеш должен адаптивно расти и подстраиваться под диапазон
самых крупных факторизаций.

Кеш можно сжимать исходя из свойств строгой монотонности
хранимых значений. Монотонность имеет характер очень
малого роста.

Последние факты я установил экспериментально.

И последнее. Задачи с primes и факторизациями в прикладных
применениях имеют разрядную сетку во много раз превышающую
int. В задачах критографии например оперируют с составным
числом порядка 128/256/512 бит.
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819687
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я расскажу для НЕ-рекурсивного варианта. То как я кодил факторизацию сам.
А ты уж подумай как эту инфу переварить.

maytonВо первых. Не нужно делить на чётные. Нужно деление на 2
вынести из тела цикла. И захардкодить.

А цикл делать начиная от 3 и с шагом в 2.


Почему ? Какой я результат получу для числа 4, например ?

maytonИ верхняя граница должна быть не до числа N которое ты проверяешь
а до SQRT(N). До квадратного корня.

Если цикл начинать с 2, то видимо так. А если с трёх, то для числа 22 например, корень между 4 и 5, таким образом делителей я не найду, хотя по идее должен был встретить 11(Если пропустить 2).
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819725
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Делителя 4 не должно существовать в принципе. Потому что делитель 4 это суть
дважды делитель по два.

Если ты где-то делишь на 4 значит скорее всего дефект в алгоритме факторизации.
Я говорю СКОРЕЕ ВСЕГО потому что не совсем представляю глубину твоего замысла.
С рекурсией и с глобальное переменной *Number. Мне не совсем ясен ее контракт.
Тоесть как с ней ПРАВИЛЬНО нужно работать.
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819730
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryЕсли цикл начинать с 2, то видимо так. А если с трёх, то для числа 22 например, корень между 4 и 5, таким образом делителей я не найду, хотя по идее должен был встретить 11(Если пропустить 2).
Для снятия дефекта корня просто прибавляй к результату единицу. (Округляй результат в сторону большего).
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819744
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonДелителя 4 не должно существовать в принципе. Потому что делитель 4 это суть
дважды делитель по два.

Если ты где-то делишь на 4 значит скорее всего дефект в алгоритме факторизации.
Я говорю СКОРЕЕ ВСЕГО потому что не совсем представляю глубину твоего замысла.
С рекурсией и с глобальное переменной *Number. Мне не совсем ясен ее контракт.
Тоесть как с ней ПРАВИЛЬНО нужно работать.

Любое число можно разложить по степеням простых чисел.
Например на входе число 150. Находим минмальный делитель этого числа слева, начиная с 2, 150 делится на 2, потому первый делитель будет 2, теперь запускаем эту-же функцию, но с числом 75, проходим числа 2 3 , и находим 3, запускаем алгоритм для 25, находим 5, снова алгоритм для 5, снова находим 5, получили 1, выход.
т.о. 150=2*3*5^2
И если ни один из элементов числителя не делится на 150, то 150 я заменю на эти 4 числа..

Мне нужна структура чтобы храниться число элементов массива делителей(элементов разложения)
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819752
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правильно.

150=2*3*5^2

Ты в этой формуле подтвердил мои слова. Все делители - простые числа. Некоторые - в степенях.

Но такой формы записи у тебя нету. Верно?

150=2*3*10

Потому что 10 - это как и 4 числа составные.
...
Рейтинг: 0 / 0
Сочетания. Реализация. Вопросы и предложения
    #38819756
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,
нет конечно. Как я могу быть уверен что составное число найдёт себе пару сверху ? Зато насчёт простых чисел я всегда уверен
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / C++ [игнор отключен] [закрыт для гостей] / Сочетания. Реализация. Вопросы и предложения
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]