powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Новогодний мега-мозг
48 сообщений из 48, показаны все 2 страниц
Новогодний мега-мозг
    #38515940
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот хорошо-бы Пифагоровых троек нагенерить.

Пример:
Код: powershell
1.
2.
3.
4.
5.
$ Pythagore 
(3, 4, 5), (6, 8, 10), (5, 12, 13), (9, 12, 15), (8, 15, 17), (12, 16, 20), (15, 20, 25),
 (7, 24, 25), (10, 24, 26), (20, 21, 29), (18, 24, 30), (16, 30, 34), (21, 28, 35), 
(12, 35, 37), (15, 36, 39), (24, 32, 40), (9, 40, 41), (27, 36, 45), (14, 48, 50),
(30, 40, 50)



P.S. Всех с наступающим!
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516129
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот чуть больше 850 миллионов
Код: plaintext
1.
2.
3.
unsigned int x;
for(unsigned int x=1; x<(2^32)/5; x++)
  printf("%d,%d,%d\n", 3*x, 4*x, 5*x);


Думаю надо усложнить задачу добавив условие что хоть одно из чисел простое.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516130
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гипотенуза растёт монотонно. Хм. Можно взять ее за основу. Как аргумент а катеты подбирать
целочисленно. Хочется избавится от квадратного корня. И в некотором вырожденном виде
существуют треугольники (0,5,5), (0,10,10). Можно старотвать развёртку угла с этого
чахлого треугольника и разворачивать вплоть до 45 градусов. Дальше нет смысла т.к.
будет зеркальное отражение уже найденных Пифагорских троек. А для ускорения
расчёта катетов можно попробовать алгоритм Брезенхейма для рисования дуги окружности.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516132
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T, да. Кст. подобные надо как-то удалять. На каждый найденный пифагорец надо
быстринько поискать в базе уже найденых (ох чую нужен Стебелёк) и дропнуть его.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516200
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как-то так
Код: 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.
#include <stdio.h>
#include <math.h>

#define COUNT 168
unsigned int iNumbers[COUNT] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541
,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997};

int main(int argc, char* argv[])
{
	int i, x, x2, y, y2, z, z2;
	for(i=0; i<COUNT; i++)
	{
		// Гипотенуза простое число
		z = iNumbers[i];
		z2 = z*z;
		for(x = 2; x < z; x++)
		{
			x2 = x*x;
			for(y = x; y < z; y++)
			{
				y2 = y*y;
				if(x2 + y2 == z2) printf("%d,%d,%d\n", x, y, z);
				if(x2 + y2 > z2) break;
			}
		}
		// Катет простое число
		y = iNumbers[i];
		y2 = y*y;
		for(x = 2; x <= y; x++)
		{
			z = sqrt(x*x + y2); 
			z2 = z*z;
			if(x2 + y2 == z2) printf("%d,%d,%d\n", x, y, z);
		}
	}
	return 0;
}


:)

PS Пример с числами до 1`000, хотел запостить до 1`000`000 но в форум не лезет. Всем желающим продолжить майнинг: качайте таблицу простых чисел и вставляйте в пример.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516283
Slip
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Так известен же общий вид всех пифагоровых троек, так что просто пробежаться по двум параметрам (ну или трем, если хочется и не взаимно простые тройки)
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516313
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хех... я постил где-то генерилку primes.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516316
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T
Код: plaintext
1.
z = sqrt(x*x + y2); 


D’oh!
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516330
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Primegen. По жлобски так. Сердито.

Код: 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.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// 30.12.2013 - Mayton

// TODO: Refactor without IEEE 754
// TODO: Check for MAX_INT or MAX_DOUBLE possible limitations
// TODO: Unit testing...
inline int isqrt(int i){
	return (int)sqrt((double)i);
}


// This is a stuped brute-force prime-gen
// TODO: Improove with In-memory prime cache
int main(int argc,char **argv){
        if (argc>1){
		int maxprime = atoi(argv[1]);
		if (maxprime >= 2){
			printf("2\n");
			for(int i=3;i<=maxprime;i+=2){
				// TODO: Refactor with Bresenham's SQRT function
				int maxdiv = 1 + isqrt(i);
				int isPrime = 1;
				for(int j=3;j<maxdiv;j++){
					if (i % j == 0) {
						isPrime = 0;
						break;
					}
				}
				if (isPrime) printf("%i\n",i);
			}
		}
		return 0;
	} else {
		fprintf(stderr,"Prime Numbers Generator 1.0 of 30 dec 2013, by Mayton\n\nUsage: prime [N]\n\n");
		return 1;	
	}
	
}
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516490
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если оставаться в рамках long, то "взаимно простые" это "остаток целочисленного деления не равен нулю".
В чём проблема бежать во вложенном цикле по "2*m+1", считая квадраты и прочие произведения в охранном условии?
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516503
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov, ты про это?

для некоторых натуральных взаимно простых чисел m > n , разной чётности....

Наоборот, любая такая пара чисел (m,n) задаёт примитивную пифагорову тройку
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516504
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, именно про эту формулу. В целых числах всё должно быть быстренько.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516512
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не додумал - в цикле ничего "охранять" не надо.
Проверять надо взаимную простоту результатов. Что сложнее.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516539
clihlt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovНе додумал - в цикле ничего "охранять" не надо.
Проверять надо взаимную простоту результатов. Что сложнее.

Так вроде же m и n должны быть взамио простые. Т.е. результат на взаимную простоту проверять не надо. А генерить взаимно простые числа с разной четностью просто: m - степень двойки, n - любое нечетное.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516541
clihlt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Или просто генерить m = n + 1, а n перебирать. Тоже будут взаимно простые с разной четностью.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38516884
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот так вот пока.... Подобные треугольники еще не фильтруются.

pyfagor.cpp
Код: 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.
#include <stdio.h>
#include <stdlib.h>

// Greatest Common Divisor
inline int gcd(int a,int b){
  int c;
  while ( a != 0 ) {
     c = a; a = b%a;  b = c;
  }
  return b;
}

inline int relationPrime(int m,int n){
	return gcd(m,n)==1?1:0;
}

// Stuped brute-force pyfagorean triangle generator
int main(int argc,char **argv){

	if (argc>1){
		int maxside = atoi(argv[1]);
		for(int i=1;i<maxside;i++){
		    int ii = i * i;
	            for(int j=1;j<i;j++){
			int jj = j * j;
	   		if (relationPrime(i,j)) {
				printf("(%d,%d,%d)\n",ii - jj,2 * i * j,ii + jj);
			}        
	            }
	            
	        }
		return 0;
	} else {
		fprintf(stderr,"Pyfagorean Triangle Generator 1.0 of 1 jan 2014, by Mayton\n\nUsage: pyfagor [N]\n\n");
		return 1;	
	}

	
	return 0;
}



Код: 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.
(3,4,5)
(8,6,10)
(5,12,13)
(15,8,17)
(7,24,25)
(24,10,26)
(21,20,29)
(16,30,34)
(9,40,41)
(35,12,37)
(11,60,61)
(48,14,50)
(45,28,53)
(40,42,58)
(33,56,65)
(24,70,74)
(13,84,85)
(63,16,65)
(55,48,73)
(39,80,89)
(15,112,113)
(80,18,82)
(77,36,85)
(65,72,97)
(56,90,106)
(32,126,130)
(17,144,145)
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38529456
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ап. С пятницей всех. Внезапно!

Пора фильтровать плохие треугольники.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38529591
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Критерий подобия.

(a1,b1,c1) подобен (а2,b2,c2) тогда, когда



Или в целых числах более точная формула



При этом не забываем разворачивать оба треугольника так чтобы b был больше чем a

Пример (8,6,10) и (3,4,5) приводим к (6,8,10) и (3,4,5)
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38529780
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне кажется так понятнее так написать


k - коэффициент пропорциональности

Я выше предлагал использовать простые числа
Dima TДумаю надо усложнить задачу добавив условие что хоть одно из чисел простое.
Правда не уверен что нет таких троек когда все три числа не простые и при этом нет меньшего подобного.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38529792
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нам нельзя вычислять k - как вещественное. Мы рискуем потерять точность на треугольниках
большого размера. Рациональная форма вида m/n где оба числа целые позволяет решить эту
задачу точно.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38529813
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По твоему алгоритму проверки все найденные надо со всеми сравнивать на подобие. Это долго.
Быстрее с помощью простых чисел меньшее подобное искать, т.е.
перебрать все простые числа (k) меньше a и убедится что все три числа не делятся на k без остатка
Код: plaintext
1.
2.
if (a % k == 0 && b % k == 0 && c % k == 0)
  printf("Меньшее подобное %d, %d, %d", a / k, b / k, c / k);
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38529900
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonНам нельзя вычислять k - как вещественное.
При наличии полного набора троек всегда будет наименьшая подобная для которой k будет целое
т.е. бОльшая подобная выражается как
Код: plaintext
1.
(a*k)^2 + (b*k)^2 = (c*k)^2 


тут k любое число, (a,b,c) - минимальное подобное
т.е. a1 = a * k
т.к. a1 и a целые то k тоже должно быть целое

Если подходит нецелое k то (a,b,c) - не минимальное подобное

Подзабыл как это доказать математически, примерно так:
раскладываем a на простые множители m1*m2*m3 находим те которые дают с умножением на k минимальное целое, например m1*m2*k, следовательно m1*m2 это то целое на которое можно разделить исходное (a,b,c)
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38529913
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут по сути вопрос идёт о сравннении стоимостей поиска в бинарных деревьях
и стоимостей генерации простых неподобных треугольников.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38529986
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне просто кажется что факторизация всех трёх (или двух?) сторон
будет более затратной чем просто binary search.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530124
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonТут по сути вопрос идёт о сравннении стоимостей поиска в бинарных деревьях
и стоимостей генерации простых неподобных треугольников.
Я о принципиально другом подходе к проверке подобных. По твоей формуле надо сравнивать все результаты со всеми, по моей просто узнать есть ли пропорционально меньше, и наименьший считать первым.
Проверять на наличие меньшего так:
Код: plaintext
1.
if(GetDivider(a, b, c) == 1) ... меньше нет


GetDivider(a, b, c)
Код: 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.
#define COUNT 168
unsigned int iPrime[COUNT] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541
,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997};

// Возвращает общий делитель тройки
inline int GetDivider(int a, int b, int c)
{
	int iRet = 1;
	unsigned int iMin = (a < b ? a : b) >> 1;
	unsigned int* ptrRow = &iPrime[0];
	unsigned int* ptrLast = &iPrime[COUNT - 1];
	if(*ptrLast < iMin) MessageBox(NULL, "Таблицу простых чисел надо побольше", "УПС :(", 0);
	while(ptrRow <= ptrLast)
	{
		ptrRow = &iPrime[0];
		while(ptrRow <= ptrLast)
		{
			if (a % *ptrRow == 0 && b % *ptrRow == 0 && c % *ptrRow == 0) 
			{
				iRet = iRet * *ptrRow;
				a = a / *ptrRow;
				b = b / *ptrRow;
				c = c / *ptrRow;
				break;
			}
			ptrRow++;
			if(*ptrRow > iMin) ptrRow = ptrLast + 1;
		}
	}
	//printf("Divider %d Minimum (%d, %d, %d)\n", iRet, a, b, c);
	return iRet;
}


т.е. GetDivider() возвращает наибольший общий делитель для тройки, поделив на который получаем минимально возможную подобную тройку.
Если допилить твой код добавив игнор не минимальных, то будет так
Генератор Майтона поправленный
Код: 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.
#include <stdio.h>
#include <stdlib.h>

// Greatest Common Divisor
inline int gcd(int a,int b){
  int c;
  while ( a != 0 ) {
     c = a; a = b%a;  b = c;
  }
  return b;
}

inline int relationPrime(int m,int n){
	return gcd(m,n)==1?1:0;
}

// Stuped brute-force pyfagorean triangle generator
int main(int argc,char **argv){

	if (argc>1){
		int maxside = atoi(argv[1]);
		for(int i=1;i<maxside;i++){
		    int ii = i * i;
	            for(int j=1;j<i;j++){
			int jj = j * j;
	   		if (relationPrime(i,j)) {
				if(GetDivider(ii - jj, 2 * i * j, ii + jj) == 1) printf("(%d,%d,%d)\n",ii - jj,2 * i * j,ii + jj);
			}        
	            }
	            
	        }
		return 0;
	} else {
		fprintf(stderr,"Pyfagorean Triangle Generator 1.0 of 1 jan 2014, by Mayton\n\nUsage: pyfagor [N]\n\n");
		return 1;	
	}

	
	return 0;
}


Твой алгоритм я не понял (если честно) но если он генерит все последовательно то дубли отфильтруются.

PS В моем примере простые числа до 1000, можно их вычислять, но проще скачать с инета, у меня массив 78498 чисел до миллиона, но исходник в форум не лезет даже в архиве.

PPS Ты цель обозначь. Чего ищем? Максимально большое и непрерывную последовательность?
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530137
miksoft
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tнаибольший общий делитель для тройкиЧтобы отбросить очередную тройку достаточно найти любой делитель больше единицы, не обязательно наибольший.

И проверять можно не до (a < b ? a : b) >> 1, а до корня из (a < b ? a : b).
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530144
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Моей таблицы простых чисел до миллиона хватило меньше чем на 5 минут работы твоего алгоритма, закончилось на этом
автор(2079301,1810020,2756749)
(2076969,1816240,2759081)
(2074629,1822460,2761421)
(2072281,1828680,2763769)
(2067561,1841120,2768489)
(2065189,1847340,2770861)
(2062809,1853560,2773241)
(2060421,1859780,2775629)
(2055621,1872220,2780429)
(2053209,1878440,2782841)
(2050789,1884660,2785261)
(2048361,1890880,2787689)
(2043481,1903320,2792569)
(2041029,1909540,2795021)
(2038569,1915760,2797481)
(2036101,1921980,2799949)
(2028649,1940640,2807401)
(2026149,1946860,2809901)
(2023641,1953080,2812409)
(2018601,1965520,2817449)
(2016069,1971740,2819981)
(2013529,1977960,2822521)
(2010981,1984180,2825069)
(2005861,1996620,2830189)
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530148
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miksoftDima Tнаибольший общий делитель для тройкиЧтобы отбросить очередную тройку достаточно найти любой делитель больше единицы, не обязательно наибольший.

И проверять можно не до (a < b ? a : b) >> 1, а до корня из (a < b ? a : b).
Согласен, ступил. Исправил на
Код: plaintext
1.
unsigned int iMin = ((unsigned int) sqrt(a < b ? a : b)) + 1;


Теперь с моей таблицей вместо максимума в 2 миллиона имеем потолок в 1 триллион.
Запустил считалку. Думаю тут пяти минут не хватит )))
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530160
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TЯ о принципиально другом подходе к проверке подобных. По твоей формуле надо сравнивать все результаты со всеми, по моей просто узнать есть ли пропорционально меньше, и наименьший считать первым.
Со всеми не надо. Мы можем ввести меру. Или метрику.



По смыслу - это котангенс острого угла alpha. Но в нашем примере он может выступать как ключ
ранжирования бесконечного множества треугольников. Далее - дело техники. Red and Black Tree
и поиск за O(log n). Вычислять его численно не нужно. Но эта дробь может участвовать в операциях
поиска в рациональном представлении.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530167
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TPPS Ты цель обозначь. Чего ищем? Максимально большое и непрерывную последовательность?
С твоих слов я не могу понять "критерий непрерывности". Что это в нашем случае?
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530368
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonDima TPPS Ты цель обозначь. Чего ищем? Максимально большое и непрерывную последовательность?
С твоих слов я не могу понять "критерий непрерывности". Что это в нашем случае?
В общих чертах надо задать алгоритм сравнения двух троек на больше/меньше, выставить их в порядке возрастания, тогда непрерывностью будет отсутствие пропусков.
Алгоритм ты уже предложил
mayton

По смыслу - это котангенс острого угла alpha. Но в нашем примере он может выступать как ключ
ранжирования бесконечного множества треугольников. Далее - дело техники. Red and Black Tree
и поиск за O(log n).
Только я не понял это
maytonВычислять его численно не нужно. Но эта дробь может участвовать в операциях
поиска в рациональном представлении.
как сравнить не вычисляя 5/7 и 7/9 ?

Думаю как-то так надо:
1. бОльшая тройка имеет бОльшую гипотенузу
2. при равной гипотенузе бОльшая по сумме катетов

Кстати интересно есть ли разные тройки с одинаковой гипотенузой.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530428
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tкак сравнить не вычисляя 5/7 и 7/9 ?

Думаю как-то так надо:
1. бОльшая тройка имеет бОльшую гипотенузу
2. при равной гипотенузе бОльшая по сумме катетов

Кстати интересно есть ли разные тройки с одинаковой гипотенузой.
Если представить (5,7) и (7,9) как векторы на плоскости то мы можем их
векторно умножить (формулу навскидку не скажу но она простая) и получить
некую величину которая будет по смыслу площадью параллелограмма образованного
этими векторами.

Причем эта площадь будет иметь знак плюс или минус в зависимости от того
"слева" или "справа" по отношению к первому вектору находился другой.

Используя свойство знаковости для площади мы можем все множество "троек"
сортировать или складывать в бинарные деревья. Тоесть у нас есть
метод .compare() и .equal().

Если площадь равна нулю то векторы параллельны (коллинеарны) и мы нашли
"подобный".

Например вектор (3,4) и (6,8) коллинеарны. Образуют вырожденный треугольник
или параллелограмм с нулевой площадью.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530544
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonDima Tкак сравнить не вычисляя 5/7 и 7/9 ?
Если представить (5,7) и (7,9) как векторы на плоскости то мы можем их
векторно умножить (формулу навскидку не скажу но она простая)
не нравится мне "векторно умножить", какая бы не была простая формула - ее надо будет считать при каждом поиске неоднократно для сравнения двух элементов. Надо что-то что считать не надо, а только сравнивать. Ты же писал
maytonВычислять его численно не нужно. Но эта дробь может участвовать в операциях
поиска в рациональном представлении.
вот я и подумал может есть какой чудо-алгоритм.

Лично мне кажется что надо приводить тройку к примитивной (так это в мат.терминологии называется) с помощью простых чисел. И примитивные хранить, сравнивать и т.д.

Перед сохранением приводить тройку к виду a <= b < c

Пары (a,b) достаточно чтобы уникально идентифицировать тройку, сравнивать можно по алгоритму
(a1,b1) < (a2,b2) если a1 < a2 или (a1 = a2 и b1 < b2)

А дальше мне интересно есть различные тройки при одинаковом "а", т.е. можно ли использовать "а" как ключ. Тоже самое надо проверить на "с"

Напишу проверку попозже.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530574
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tmaytonпропущено...

Если представить (5,7) и (7,9) как векторы на плоскости то мы можем их
векторно умножить (формулу навскидку не скажу но она простая)
не нравится мне "векторно умножить", какая бы не была простая формула - ее надо будет считать при каждом поиске неоднократно для сравнения двух элементов. Надо что-то что считать не надо, а только сравнивать. Ты же писал
maytonВычислять его численно не нужно. Но эта дробь может участвовать в операциях
поиска в рациональном представлении.
вот я и подумал может есть какой чудо-алгоритм.

Я над этим думаю. Можно хранить угловой коэффициент K или его обратное
значение (котангенс альфа). Но поскольку мы играем по правилам алгебры
больших целых чисел то нам не хватит разрядности double на очень больших
значениях int64. Тоесть будут такие a1/b1 и a2/b2 различные и НЕ-подобные,
но их угловой коэффициент будет одинаковый в представлении double.
Основание простое - 52 бита мантиссы явно не хватит чтобы различать
эту разницу. Когда это "стрельнет" - я не знаю. Надо посчитать. Возможно
для 32х битных пифагоровых троек их хватит.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530703
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TА дальше мне интересно есть различные тройки при одинаковом "а", т.е. можно ли использовать "а" как ключ. Тоже самое надо проверить на "с"
Оказалось есть повторы и a и с , и числа всего лишь двухзначные.

Так что остается ключом использовать (a, b)

На счет хранения a/b как double сомневаюсь, нехороший это тип для проверки равенства. Не для того он придуман. Может оказаться что для подобных треугольников он будет разный, достаточно чтоб не совпал младший разряд мантиссы.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530710
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот формула расчёта (удвоенной) площади треугольника. Или параллелограмма.

Код: plaintext
1.
2.
3.
int getTwinSquare(int x1,int y1,int x2,int y2,int x3,int y3){
	return (x1 - x3) * (y2 - y3) - (x2 - x3) * (y1 - y3);
}



Где (x1,y1),(x2,y2),(x3,y3) координаты трёх вершин треугольника.

Но для нашего случая где (x1,y1) всегда нулевые можно формулу упростить до такой.

Код: plaintext
1.
2.
3.
int getTwinSquare(int x2,int y2,int x3,int y3){
	return (- x3) * (y2 - y3) - (x2 - x3) * (- y3);
}



Проверяем (чортов Latex. Заколебал) . Для треугольников образованных
векторами (5,7), (7,9) абсолютное значение площади можно посчитать интуитивно по следующей
картинке.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530714
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Проверим нашу целочисленную формулу
Код: 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.
// Отрицательная площадь
	int x1=5;
	int y1=7;

	int x2=7;
	int y2=9;

	int S = getTwinSquare(x1,y1,x2,y2);

	printf("Triangle square = %d \n",S / 2);

	// Меняем точки местами. Положительная площадь
	
	x1=7;
	y1=9;

	x2=5;
	y2=7;

	S = getTwinSquare(x1,y1,x2,y2);

	printf("Triangle square = %d \n",S / 2);

	// Коллинеарные векторы. Нулевая площадь

	x1=5;
	y1=7;

	x2=10;
	y2=14;

	S = getTwinSquare(x1,y1,x2,y2);

	printf("Triangle square = %d \n",S / 2);



Итак механизм есть.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38530716
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TНа счет хранения a/b как double сомневаюсь, нехороший это тип для проверки равенства. Не для того он придуман. Может оказаться что для подобных треугольников он будет разный, достаточно чтоб не совпал младший разряд мантиссы.
Его использование в контексте сравнения вида

Код: plaintext
1.
if (doubleValue1 == doubleValue2) { 


уже само по себе является антипаттерном. Так вещевтенные числа не сравнивают.
Поэтому пролетит он, как напильник над Парижем. Хотя в другом контексте его использования
как аппроксимацию чего-либо я-бы не был против.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38531113
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще одна очень простая формула. Просто сравниваем две дроби (угловые коэфф).



Переносим влево и приводим к знаменателю


И сравниваме результат. Больше нуля или меньше нуля - соотв. Гипотенуза с2 имеет наклон больше
или меньше с1. Если равно нулю - то треугольники подобны.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38531377
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton

И сравниваем результат.
Знаменатель можно не считать



По сути это ты уже предлагал выше
mayton

Только я не понимаю как это использовать, например в <map>. Что использовать в качестве ключа? Та же проблема будет с любой СУБД.
А без ключа все алгоритмы быстрого поиска не работают, т.е. придется перебором сравнивать каждую новую с ранее найденными. Самый тормозной способ.
Ключ должен быть производным от одной тройки, т.е. выражаться из (a,b,c). Если при этом для подобных троек он должен быть одинаковым, то тут только подходит, но это вещественное число, как вариант приводить к целому с округлением, но тут надо как-то вычислить погрешность округления, чтобы понять в какой момент округление начнет давать ошибки.

Чем тебе не нравится мой вариант приведения тройки к примитивной с помощью простых чисел? По сути это поиск наибольшего общего делителя для всех трех чисел. Массив из 78,5 тыс простых чисел позволяет проверить любое число до триллиона (для типа unsigned int достаточно 6543 числа). Нехорошее место с извлечением корня можно заменить на другой алгоритм получения минимального целого больше корня. Думаю мой перебор простых чисел далеко не самый лучший, скорее всего существуют более продвинутые алгоритмы поиска наибольшего общего делителя. Вот 5 алгоритмов вообще без использования простых чисел. Потестю попозже какой быстрее.

По моему лучше сначала привести к тройку к примитивной а затем ее хранить, тогда проблема поиска дублей решается классическими средствами.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38531464
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тройка не нужна. Нам хватит двух катетов (a,b) для того чтобы установить "подобие".

Рациональную дробь a/b придётся хранить в поисковой структуре в качестве ключа.
И именно в таком виде.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38531762
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonНо для нашего случая где (x1,y1) всегда нулевые можно формулу упростить до такой.

Код: plaintext
1.
2.
3.
int getTwinSquare(int x2,int y2,int x3,int y3){
	return (- x3) * (y2 - y3) - (x2 - x3) * (- y3);
}


Упрощаем дальше:
(- x3) * (y2 - y3) - (x2 - x3) * (- y3)
= -x3*y2 + x3*y3 + x2*y3 - x3*y3
= x2*y3 - y2*x3

т.е. опять пришли к

По поводу поиска НОД самым быстрым оказался уже использованный у тебя. Функция gcd(), сначала не понял чего это такое.

Поправил код. Вот окончательный вариант с <map> для хранения результатов
Код: 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.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
// Pifagor.cpp : Defines the entry point for the console application.
//

#pragma warning( disable : 4786)
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <windows.h>
#include <map>


// Greatest Common Divisor
inline unsigned int gcd(unsigned int a, unsigned int b){
  unsigned int c;
  while ( a != 0 ) {
     c = a; a = b%a;  b = c;
  }
  return b;
}

// для хранения ключа
typedef struct {
	unsigned int a;
	unsigned int b;
} sPifagor_t;

struct clsPifagorCompare:
public                                 
std::binary_function<sPifagor_t, sPifagor_t, bool>
{ 
	bool operator() (const sPifagor_t& lhs, const sPifagor_t& rhs) const 
	{
		return lhs.a < rhs.a || (lhs.a == rhs.a && lhs.b < rhs.b);
	}
};

typedef std::map<sPifagor_t, unsigned int, clsPifagorCompare> map_t;
map_t mapRes;
map_t::iterator cur;

unsigned int iStore = 0;

inline void StoreTri(unsigned int a, unsigned int b, unsigned int c)
{
	sPifagor_t sPifagor;
	unsigned int iGCD = gcd(a, b);
	if(iGCD > 1)
	{
		a = a / iGCD;
		b = b / iGCD;
		c = c / iGCD;
	}
	if(a > b)
	{
		sPifagor.a = b;
		sPifagor.b = a;
	}
	else
	{
		sPifagor.a = a;
		sPifagor.b = b;
	}
	
	cur = mapRes.find(sPifagor);
	if(cur != mapRes.end())
	{
		if((*cur).second != c)
		{
			printf("error(%d,%d,%d != %d)\n", a, b, c, (*cur).second);
			MessageBox(NULL, "error", "error", 0);
		}
	}
	else
	{
		mapRes.insert(std::make_pair(sPifagor, c));
		iStore++;
	}

}

inline unsigned int relationPrime(unsigned int m, unsigned int n){
	return gcd(m,n)==1?1:0;
}

// Stuped brute-force pyfagorean triangle generator
int main(int argc,char **argv){

	if (argc>1){
		unsigned int iCount = 0, iNext = 1000000, iStart = GetTickCount();
		unsigned int maxside = atoi(argv[1]);
		for(int i=1;i<maxside;i++){
		    unsigned int ii = i * i;
	            for(int j=1;j<i;j++){
			unsigned int jj = j * j;
	   		if (relationPrime(i,j)) {
				StoreTri(ii - jj,2 * i * j,ii + jj);
				iCount++;
				if(iCount >= iNext) 
				{
					printf("Parse %d Store %d Time %d msec\n", iCount, iStore, GetTickCount() - iStart);
					iNext += 1000000;
				}

			}        
	            }
	            
	        }
		printf("Parse %d Store %d Time %d msec\n", iCount, iStore, GetTickCount() - iStart);
		return 0;
	} else {
		fprintf(stderr,"Pyfagorean Triangle Generator 1.0 of 1 jan 2014, by Mayton\n\nUsage: pyfagor [N]\n\n");
		return 1;	
	}

	
	return 0;
}


Для типа unsigned int можно запустить с параметром 46430 (больше нельзя, т.к. не лезет ii + jj)
Этот код у меня отъедает 2 Гб оперативки под map и вылетает на
Parse 65000000 Store 43332389 Time 148945 msec
65'000'000 это 10% от общего количества 655'264'541.
Можно из найденного сделать вывод что треть это повторы, т.е. примитивных около 433'323'890.
Можно прикинуть размер хранилища: минимум на запись 8 байт (а, b) = 4 Гб, это если использовать <vector> в который валить все результаты (а, b), периодически сортировать и выкидывать повторы.
Для <map> тут надо 20 Гб оперативки (скорее всего поменьше, но не на много).

Вывод: для типов больше 32х разрядов надо задействовать какую-нибудь серьезную СУБД. Бесплатный MS SQL Express с максимальным размером базы 10 Гб будет маловат.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38531789
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я создал проект Пифагора на code.google.com. Если у тебя есть акк - то
можно туда коммитить.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38532175
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это конечно классно что ты задейстовал std::map но моя мысль заключалась в том
чтобы в теле компаратора сравнивать не только на совпадение но и на больше-меньше.
Тогда без факторизации можно пробежаться по дереву и найти либо место для вставки
нового треугольника либо выдать ошибку типа "дубликат" ключа и игнорить вставку.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38532376
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonЯ создал проект Пифагора на code.google.com. Если у тебя есть акк - то
можно туда коммитить.
Нет аккаунта, да и с английским все плохо.

Да и тема исчерпана уже.
Проверил на пропуски
Код: 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.
// Stuped brute-force pyfagorean triangle generator
int main(int argc,char **argv){

	if (argc>1){
		unsigned int iCount = 0, iNext = 1000000, iStart = GetTickCount();
		unsigned int maxside = atoi(argv[1]);
		for(int i=1;i<maxside;i++){
		    unsigned int ii = i * i;
	            for(int j=1;j<i;j++){
			unsigned int jj = j * j;
	   		if (relationPrime(i,j)) {
				StoreTri(ii - jj,2 * i * j,ii + jj);
				iCount++;
				if(iCount >= iNext) 
				{
					printf("Parse %d Store %d Time %d msec\n", iCount, iStore, GetTickCount() - iStart);
					iNext += 1000000;
				}

			}        
	            }
	            
	        }
		printf("Parse %d Store %d Time %d msec\n", iCount, iStore, GetTickCount() - iStart);
		for(unsigned int a = 1; a <40000; a++)
		{
			for(unsigned int b = 1; b < 40000; b++)
			{
				unsigned int c2 = a*a + b*b;
				unsigned int c = sqrt(c2);
				if(c2 == c*c)
				{
					unsigned int iStorePrev = iStore;
					StoreTri(a, b, c);
					if(iStorePrev != iStore)
					{ 
						printf("skip(%d,%d,%d)\n", a, b, c);
						iCount++;
					}
				}

			}
		}
		printf("Parse %d Store %d Time %d msec\n", iCount, iStore, GetTickCount() - iStart);
		map2file();
		return 0;
	} else {
		fprintf(stderr,"Pyfagorean Triangle Generator 1.0 of 1 jan 2014, by Mayton\n\nUsage: pyfagor [N]\n\n");
		return 1;	
	}

	
	return 0;
}


Твой код генерит почти непрерывную последовательность примитивных троек. При a < 40`000 и b < 40`000 всего 7`150 примитивных троек, он находит их все перебрав 14`501 (параметр 219 при запуске).
то же самое подтверждают запуски с ограничением b по значению в StoreTri() (параметр 46400 при запуске)
Код: 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.
inline void StoreTri(unsigned int a, unsigned int b, unsigned int c)
{
	sPifagor_t sPifagor;

	unsigned int iGCD = gcd(a, b);
	if(iGCD > 1)
	{
		a = a / iGCD;
		b = b / iGCD;
		c = c / iGCD;
	}

	if(a > b)
	{
		sPifagor.a = b;
		sPifagor.b = a;
	}
	else
	{
		sPifagor.a = a;
		sPifagor.b = b;
	}
	if(sPifagor.b >= 10000000) return;
....
}


В какой-то момент наступает максимум найденных троек и он больше не меняется.

В итого: для продолжения надо заменить тип на 64-бита и привязать какую-то взрослую СУБД для хранения результата.

PS Непонятно какой практический смысл в этой генерации? Пытался придумать - не смог. Поисковики выдают только то что это было нужно при строительстве египетских пирамид несколько тысяч лет назад.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38532394
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PPS Было интересно отвлечься от постоянных +-*/ в рублях и штуках.
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38532462
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TPS Непонятно какой практический смысл в этой генерации? Пытался придумать - не смог. Поисковики выдают только то что это было нужно при строительстве египетских пирамид несколько тысяч лет назад.
А никакого смысла брадт. Считай что это просто пятничная задачка. Я просто скажу
тебе следующее. Попытка разложить на множители следующее
привела к возникновению комплексных чисел. Попытка исследовать глубоко теорему
Ферма - много лет давала туеву хучу побочных теорем, лемм и гипотез. Зачем
вообще искать практический смысл в проблемах Гильберта? А низачем.

Это игры разума! Добро пожаловать в математику!
...
Рейтинг: 0 / 0
Новогодний мега-мозг
    #38532463
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TВ какой-то момент наступает максимум найденных троек и он больше не меняется.

Кстати если ты в состоянии объяснить этот эффект - то ты понял ограничения
разрядной сетки и самое главное почему и где и как его устранить.
...
Рейтинг: 0 / 0
48 сообщений из 48, показаны все 2 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / Новогодний мега-мозг
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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