seminar2
This commit is contained in:
		
							parent
							
								
									46d1c64684
								
							
						
					
					
						commit
						ab6732eded
					
				
					 98 changed files with 10319 additions and 0 deletions
				
			
		
							
								
								
									
										38
									
								
								seminar02_encapsulation/homework/code/0circle/circle.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								seminar02_encapsulation/homework/code/0circle/circle.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| #include <iostream> | ||||
| #include <math.h> | ||||
| #include "circle.h" | ||||
| #include "point.h" | ||||
| 
 | ||||
| Circle::Circle(const Point& acenter, float aradius) { | ||||
|     mCenter = acenter; | ||||
|     mRadius = aradius; | ||||
| } | ||||
| Circle::Circle() { | ||||
|     mCenter = Point {0, 0}; | ||||
|     mRadius = 1; | ||||
| } | ||||
| Circle::Circle(const Circle& circle) { | ||||
|    mCenter = circle.mCenter; | ||||
|    mRadius = circle.mRadius; | ||||
| } | ||||
| Point Circle::getCenter() const { return mCenter; } | ||||
| float Circle::getRadius() const { return mRadius; } | ||||
| 
 | ||||
| void Circle::setCenter(const Point& p) { | ||||
|     mCenter = p; | ||||
| } | ||||
| void Circle::setRadius(float radius) { | ||||
|     mRadius = radius > 0 ? radius : 0; | ||||
| } | ||||
| float Circle::getArea() const { | ||||
|     return mRadius * mRadius * M_PI; | ||||
| } | ||||
| float Circle::getDistance(const Point& p) { | ||||
|     return mCenter.distance(p) - mRadius;  | ||||
| } | ||||
| bool Circle::isColliding(const Circle& c) const { | ||||
|     return (mCenter.distance(c.getCenter()) - (mRadius + c.getRadius()) > 0) ? false : true; | ||||
| } | ||||
| void Circle::move(const Point& p) { | ||||
|     mCenter = mCenter + p; | ||||
| } | ||||
							
								
								
									
										23
									
								
								seminar02_encapsulation/homework/code/0circle/circle.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								seminar02_encapsulation/homework/code/0circle/circle.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| #include "point.h" | ||||
| class Circle | ||||
| { | ||||
| private: | ||||
| 	Point mCenter; | ||||
| 	float mRadius; | ||||
| 
 | ||||
| public: | ||||
|     Circle(const Point& acenter, float aradius); | ||||
|     Circle(); | ||||
|     Circle(const Circle& circle); | ||||
|     Point getCenter() const; | ||||
|     float getRadius() const; | ||||
| 
 | ||||
|     void setCenter(const Point& p);  | ||||
|     void setRadius(float radius);  | ||||
|     float getArea() const; | ||||
|     float getDistance(const Point& p); | ||||
|     bool isColliding(const Circle& c) const; | ||||
|     void move(const Point& p); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										44
									
								
								seminar02_encapsulation/homework/code/0circle/main.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								seminar02_encapsulation/homework/code/0circle/main.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| #include <iostream> | ||||
| #include "point.h" | ||||
| #include "circle.h" | ||||
| 
 | ||||
| using std::cout, std::endl; | ||||
| 
 | ||||
| 
 | ||||
| int main() | ||||
| { | ||||
| 	Point p = {7, -1}; | ||||
| 	Point q = {-4, 2}; | ||||
| 	cout << "Point p = " << p << endl; | ||||
| 	cout << "Point q = " << q << endl; | ||||
| 	cout << "p + q = " << p + q << endl; | ||||
| 
 | ||||
| 
 | ||||
| 	Circle a {{4, 1}, 3}; | ||||
| 	Circle b; | ||||
|     // b = a;
 | ||||
| 
 | ||||
| 	cout << "Circle a: center: " << a.getCenter() << " radius: " << a.getRadius() << endl;  | ||||
| 	cout << "Circle b: center: " << b.getCenter() << " radius: " << b.getRadius() << endl; | ||||
| 
 | ||||
| 	cout << "Area of a = " << a.getArea() << endl; | ||||
| 	cout << "Distance from point p to circle a = " << a.getDistance(p) << endl; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	cout << "Collisions:" << endl; | ||||
| 	if (a.isColliding(b)) | ||||
| 		cout << "Yes, a is colliding b" << endl; | ||||
| 	else | ||||
| 		cout << "No, a isn't colliding b" << endl; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	cout << "Moving b by {1, 1}:" << endl; | ||||
| 	b.move({1, 1}); | ||||
| 	if (a.isColliding(b)) | ||||
| 		cout << "Yes, a is colliding b" << endl; | ||||
| 	else | ||||
| 		cout << "No, a isn't colliding b" << endl; | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										82
									
								
								seminar02_encapsulation/homework/code/0circle/point.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								seminar02_encapsulation/homework/code/0circle/point.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,82 @@ | |||
| #include <iostream> | ||||
| #include <cmath> | ||||
| 
 | ||||
| #include "point.h" | ||||
| 
 | ||||
| 
 | ||||
| Point::Point(float x, float y)  | ||||
| { | ||||
|     mx = x; | ||||
|     my = y; | ||||
| } | ||||
| 
 | ||||
| Point::Point() | ||||
| { | ||||
|     mx = 0; | ||||
|     my = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| float Point::getX() const  | ||||
| { | ||||
| 	return mx; | ||||
| } | ||||
| 
 | ||||
| float Point::getY() const  | ||||
| { | ||||
| 	return my; | ||||
| } | ||||
| 
 | ||||
| void Point::setX(float x)  | ||||
| { | ||||
| 	mx = x; | ||||
| } | ||||
| 
 | ||||
| void Point::setY(float y)  | ||||
| { | ||||
| 	my = y; | ||||
| } | ||||
| 
 | ||||
| float Point::norm() const  | ||||
| { | ||||
| 	return std::sqrt(mx * mx + my * my); | ||||
| } | ||||
| 
 | ||||
| void Point::normalize()  | ||||
| { | ||||
| 	float pnorm = norm(); | ||||
| 	mx /= pnorm; | ||||
| 	my /= pnorm; | ||||
| } | ||||
| 
 | ||||
| float Point::distance(const Point& p) const  | ||||
| { | ||||
| 	return std::sqrt((p.mx - mx) * (p.mx - mx) + (p.my - my) * (p.my - my)); | ||||
| } | ||||
| 
 | ||||
| Point Point::operator+(const Point& right) const  | ||||
| { | ||||
| 	Point result = {mx + right.mx, my + right.my}; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| Point Point::operator*(float a) const  | ||||
| { | ||||
| 	Point result = {a * mx, a * my}; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| Point operator*(float a, const Point& p)  | ||||
| { | ||||
| 	Point result = {a * p.mx, a * p.my}; | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& left, const Point& right)  | ||||
| { | ||||
| 	left << "(" << right.mx << ", " << right.my << ")"; | ||||
| 	return left; | ||||
| } | ||||
							
								
								
									
										37
									
								
								seminar02_encapsulation/homework/code/0circle/point.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								seminar02_encapsulation/homework/code/0circle/point.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| #pragma once | ||||
| 
 | ||||
| /*
 | ||||
|     Поля x и y сделаны приватными | ||||
|     Конкретно для этого класса их можно было сделать публичными | ||||
|     Так как пользователь всё-равно будет иметь доступ без ограничений к этим полям через геттеры и сеттеры | ||||
|     Но они сделаны приватными для образовательных целей | ||||
| */ | ||||
| 
 | ||||
| class Point | ||||
| { | ||||
| private: | ||||
|     float mx, my; | ||||
|      | ||||
| public: | ||||
| 
 | ||||
|     Point(float x, float y); | ||||
|     Point(); | ||||
| 
 | ||||
|     float getX() const; | ||||
|     float getY() const; | ||||
|     void setX(float x); | ||||
|     void setY(float y); | ||||
| 
 | ||||
|     void normalize(); | ||||
|     float distance(const Point& p) const; | ||||
|     float norm() const; | ||||
|     Point operator+(const Point& right) const; | ||||
|     Point operator*(float a) const; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     friend Point operator*(float a, const Point& p); | ||||
|     friend std::ostream& operator<<(std::ostream& left, const Point& right); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										307
									
								
								seminar02_encapsulation/homework/code/1number/number.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								seminar02_encapsulation/homework/code/1number/number.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,307 @@ | |||
| #include <iostream> | ||||
| #include <cstring> | ||||
| #include <iomanip> | ||||
| #include <vector> | ||||
| #include <algorithm> | ||||
| 
 | ||||
| /*
 | ||||
|     Класс Number -- класс положительных больших чисел | ||||
| 
 | ||||
|     Большое число будет храниться в динамическом массиве data | ||||
|     Каждый элемент этого массива содержит разряд числа в 100-ричной системе счисления | ||||
|     (так как base = 100) | ||||
|     По сути, каждый элемент data хранит две цифры числа в десятичной записи | ||||
| 
 | ||||
|     Значение 100 для системы счисления выбрано как компромис между | ||||
|     эффективностью и удобством написания программы. | ||||
|     Если выбрать значения базы 10 - то программа будет не так эффективна по памяти | ||||
|     Если выбрать значения базы 256 (максимально эффективное использование памяти для типа char), | ||||
|     то алгоритм печати на экран сильно усложнится | ||||
|     В качестве альтернативы, можно было выбрать базу 1e9,  | ||||
|     изменив при этом тип элементов c char на int | ||||
| 
 | ||||
|     capacity - размер массива data | ||||
|     size - сколько ячеек занимет число в массиве data | ||||
|     size <= capacity | ||||
| 
 | ||||
|     Для удобства разряды числа хранятся в обратном порядке | ||||
|     Например, число 12345678 соответствует массиву | ||||
|     data = {78, 56, 34, 12} | ||||
|     (это упрощает многие алгоритмы с такими числами) | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| class Number  | ||||
| { | ||||
| private: | ||||
|     static const int base = 100; | ||||
|     std::size_t size; | ||||
|     std::size_t capacity; | ||||
|     char* data; | ||||
| 
 | ||||
| public: | ||||
| 
 | ||||
|     Number(int a)  | ||||
|     { | ||||
| #ifdef _DEBUG_CONSTRUCTOR | ||||
|          std::cout << "(Number constructor "  << a << " -> "; | ||||
| #endif | ||||
|         // Находим размер необходимой памяти под это число
 | ||||
|         int temp = a; | ||||
|         capacity = 0; | ||||
|         while (temp != 0)  | ||||
|         { | ||||
|             temp /= base; | ||||
|             capacity += 1; | ||||
|         } | ||||
| 
 | ||||
|         // Отдельно обрабатываем случай, когда число равно 0
 | ||||
|         if (capacity == 0)  | ||||
|             capacity = 1; | ||||
| 
 | ||||
|         // Выделяем память и записывем число a в массив data
 | ||||
|         // Например, число 12345678 представится в виде массива [78, 56, 34, 12]
 | ||||
|          | ||||
|         data = new char[capacity]; | ||||
| 
 | ||||
|         for (int i = 0; i < capacity; ++i)  | ||||
|         { | ||||
|             data[i] = a % base; | ||||
|             a /= base; | ||||
|         } | ||||
| 
 | ||||
|         // В данном случае размер будет равен вместимости
 | ||||
|         size = capacity; | ||||
| #ifdef _DEBUG_CONSTRUCTOR | ||||
|         std::cout << *this << ")" << std::endl; | ||||
| #endif | ||||
|     } | ||||
|     // Конструктор по умолчанию      
 | ||||
|     Number() : Number(0) {} | ||||
|     // Конструктор копирования
 | ||||
|     Number(const Number& n) { | ||||
|             size = n.size; | ||||
|             capacity = n.capacity; | ||||
|             data = new char[capacity]; | ||||
|             for (int i = 0; i < size; i++) { | ||||
|                 data[i] = n.data[i]; | ||||
|             } | ||||
|     } | ||||
|     Number(const char* str) { | ||||
|         int len = std::strlen(str); | ||||
|         size = (len + len % 2) / 2; | ||||
|         capacity = size; | ||||
|         data = new char[capacity]; | ||||
|         char buf[2]; | ||||
|         for (int i = 0; i < size; i++) { | ||||
|                 buf[1] = str[len - 2 * i - 1]; | ||||
|                 if (len - 2 * i - 1 > 0) { | ||||
|                         buf[0] = str[len - 2 * i - 2]; | ||||
|                 } | ||||
|                 else { | ||||
|                         buf[0] = '0'; | ||||
|                 } | ||||
|                 data[i] = std::stoi(buf);  | ||||
|         } | ||||
|     } | ||||
|     ~Number()  | ||||
|     { | ||||
|         delete [] data; | ||||
|     } | ||||
|     Number& operator=(const Number& right) { | ||||
|             capacity = right.capacity; | ||||
|             size = right.size; | ||||
|             data = new char[capacity]; | ||||
|             for (int i = 0; i < size; i++) { | ||||
|                 data[i] = right.data[i]; | ||||
|             } | ||||
|             return *this; | ||||
|     } | ||||
| 
 | ||||
|     Number operator+(const Number& a) { | ||||
|         Number result; | ||||
|         int i; | ||||
|         char carry = 0; | ||||
|         int max_size = size > a.size ? size : a.size; | ||||
| 
 | ||||
|         result.capacity = max_size + 1; | ||||
|         result.data = new char[capacity]; | ||||
| 
 | ||||
|         for (i = 0; i < max_size; ++i) { | ||||
|             result.data[i] = (data[i] + a.data[i] + carry) % base;  | ||||
|             carry = (data[i] + a.data[i] + carry) / base; | ||||
|         } | ||||
| 
 | ||||
|         if (carry) { | ||||
|             result.data[i] = carry; | ||||
|             result.size = max_size + 1; | ||||
|         } | ||||
|         else { | ||||
|             result.size = max_size; | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|     void operator+=(const Number& a) { | ||||
|         *this = *this + a; | ||||
|     } | ||||
| 
 | ||||
|     bool isEven() const { | ||||
|         if (data[0] % 2) { | ||||
|             return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     Number operator*(const Number& right) const { | ||||
| #ifdef _DEBUG_MUL | ||||
|           std::cout << "arg1=" << *this << "(capacity=" << capacity << ",size=" << size << ")" << " " << "arg2=" << right << "(capacity=" << right.capacity << ",size=" << right.size << ")"<<  std::endl; | ||||
| #endif | ||||
|           int i, j; | ||||
|           int temp; | ||||
|           Number result; | ||||
|            | ||||
|           result.capacity = capacity + right.capacity; | ||||
|           int *carry = (int*)std::calloc(result.capacity, sizeof(int)); | ||||
| 
 | ||||
|           result.data = (char*)calloc(result.capacity, sizeof(char)); | ||||
| #ifdef   _DEBUG_MUL | ||||
|           std::cout << "carry:[" << carry[0]; | ||||
|           for (int k = 1; k < result.capacity; ++k) { | ||||
|             std::cout << "," << carry[k]; | ||||
|           } | ||||
|           std::cout << "]" << std::endl; | ||||
| #endif | ||||
|           for (i = 0; i < size; ++i) { | ||||
|                 for (j = 0; j < right.size; ++j) { | ||||
| #ifdef _DEBUG_MUL | ||||
|                     std::cout << i + j << ":" << static_cast<int>(result.data[i + j]) << " + " << static_cast<int>(data[i]) << " * " << static_cast<int>(right.data[j]) << " + " << carry[i+j] << std::endl; | ||||
| #endif | ||||
|                     temp = (result.data[i + j] + data[i] * right.data[j] + carry[i + j]); | ||||
|                     result.data[i + j] = temp % base; | ||||
|                     carry[i + j + 1] += temp / base; | ||||
|                     carry[i + j] = 0; | ||||
| 
 | ||||
|                 } | ||||
|           } | ||||
| #ifdef _DEBUG_MUL | ||||
|           std::cout << "result before applying carry:" << result << std::endl; | ||||
|           std::cout << "carry:[" << carry[0]; | ||||
|           for (int k = 1; k < result.capacity; ++k) { | ||||
|             std::cout << "," << carry[k]; | ||||
|           } | ||||
|           std::cout << "]" << std::endl; | ||||
| #endif | ||||
|           if (carry[i + j - 1]) { | ||||
|             result.data[i + j - 1] = carry[i + j - 1]; | ||||
|             result.size = i + j; | ||||
|             carry[i + j - 1] = 0; | ||||
|           } | ||||
|           else { | ||||
|             result.size = i + j - 1; | ||||
|           } | ||||
|            | ||||
| #ifdef _DEBUG_MUL | ||||
|           std::cout << "before correcting capacity, result=" << result << std::endl; | ||||
| #endif | ||||
|           // correcting capacity
 | ||||
|           /*char* temp_data = (char *)calloc(result.size, sizeof(char));
 | ||||
|           for (i = 0; i < result.size; ++i) { | ||||
|             temp_data[i] = result.data[i]; | ||||
|           } | ||||
| 
 | ||||
|           free(result.data); | ||||
|           result.capacity = result.size; | ||||
|           result.data = (char*)calloc(result.size,sizeof(char)); | ||||
|           for (i = 0; i < result.size; ++i) { | ||||
|             result.data[i] = temp_data[i]; | ||||
|           } | ||||
| 
 | ||||
|           free(temp_data);*/ | ||||
|           free(carry); | ||||
| #ifdef _DEBUG_MUL | ||||
|           std::cout << "return value=" << result << "(capacity=" << result.capacity << ",size=" << result.size << ")" << std::endl << "======" << std::endl; | ||||
| #endif | ||||
|           return result; | ||||
|     } | ||||
|     void operator*=(const Number& a) { | ||||
|         *this = *this * a; | ||||
|     } | ||||
| 
 | ||||
|     friend std::ostream& operator<<(std::ostream& stream, const Number& right); | ||||
|     friend int main(); | ||||
|     friend Number factorial(int n); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| std::ostream& operator<<(std::ostream& stream, const Number& right) | ||||
| { | ||||
| #ifdef _DEBUG_COUT | ||||
|     stream << "["; | ||||
|     for (std::size_t i = 0; i < right.size; ++i) { | ||||
|         stream << static_cast<int>(right.data[right.size - 2 - i]) << ","; | ||||
|     } | ||||
|     stream << "]"; | ||||
| #else | ||||
|      // Печатаем самый большой разряд
 | ||||
|     stream << (int)right.data[right.size - 1]; | ||||
| 
 | ||||
|     // Печатаем остальные разряды с заполнением нулями до 2-х цифр
 | ||||
|     // setfill и setw это то же самое, что и в языке C спецификатор %02d
 | ||||
|     for (std::size_t i = 0; i < right.size - 1; ++i) | ||||
|         stream << std::setfill('0') << std::setw(2) << (int)right.data[right.size - 2 - i]; | ||||
| #endif | ||||
|     return stream; | ||||
| } | ||||
| 
 | ||||
| Number fib(int n) { | ||||
|     Number a = 0; // F0
 | ||||
|     Number b = 1; // F1
 | ||||
|     for (int i = 1; i <=n; ++i) { | ||||
|         if (i % 2) { | ||||
|             a += b; | ||||
|         } | ||||
|         else { | ||||
|             b += a; | ||||
|         } | ||||
|     } | ||||
|     if (n % 2) { | ||||
|         return b; | ||||
|     } | ||||
|     return a; | ||||
| } | ||||
| 
 | ||||
| Number factorial(int n) { | ||||
|     Number result{1}; | ||||
|     for (int i = 2; i < n + 1; ++i) { | ||||
|         result = Number(i) * result; | ||||
|     } | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| int main()  | ||||
| { | ||||
|     Number x = Number("25852016738884976640000"); | ||||
|     Number y = Number("24"); | ||||
| 
 | ||||
|     //char s[3];
 | ||||
|     //Number result = "1";
 | ||||
|     //for (int i = 1; i < 26; ++i) {
 | ||||
|         //s = std::to_string(i);
 | ||||
|         //sprintf(s, "%d", i);
 | ||||
|     //    result = (Number{i} * result);
 | ||||
|     //}   
 | ||||
|     //x += y;
 | ||||
|     //Number z = x + y;
 | ||||
|     //std::cout << fib(1000) << std::endl;
 | ||||
|     //x = x * Number(24)*Number{25};
 | ||||
|     //y = factorial(5);
 | ||||
|     //std::cout << x << " " << x.capacity << " " << x.size << std::endl;
 | ||||
|     //std::cout << y << " "<< y.capacity << " " << y.size << std::endl;
 | ||||
|     // 90405070506200618121707-18-13-05-18-08
 | ||||
|     //std::cout << "===" << std::endl << Number(2) * Number(3) << " "<< Number(3) * Number(2) << std::endl;
 | ||||
|     //std::cout << "5! = " << Number(2) * Number(3) * Number(4) * Number(5) << std::endl;
 | ||||
|     std::cout << factorial(1000) << std::endl; | ||||
|     //std::cout << Number("620448401733239439360000") * Number(25) << std::endl;
 | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										
											BIN
										
									
								
								seminar02_encapsulation/homework/homework_encapsulation.pdf
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								seminar02_encapsulation/homework/homework_encapsulation.pdf
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										202
									
								
								seminar02_encapsulation/homework/homework_encapsulation.tex
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								seminar02_encapsulation/homework/homework_encapsulation.tex
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,202 @@ | |||
| \documentclass{article} | ||||
| \usepackage[utf8x]{inputenc} | ||||
| \usepackage{ucs} | ||||
| \usepackage{amsmath}  | ||||
| \usepackage{amsfonts} | ||||
| \usepackage{marvosym} | ||||
| \usepackage{wasysym} | ||||
| \usepackage{upgreek} | ||||
| \usepackage[english,russian]{babel} | ||||
| \usepackage{graphicx} | ||||
| \usepackage{float} | ||||
| \usepackage{textcomp} | ||||
| \usepackage{hyperref} | ||||
| \usepackage{geometry} | ||||
|   \geometry{left=2cm} | ||||
|   \geometry{right=1.5cm} | ||||
|   \geometry{top=1cm} | ||||
|   \geometry{bottom=2cm} | ||||
| \usepackage{tikz} | ||||
| \usepackage{ccaption} | ||||
| \usepackage{multicol} | ||||
| \usepackage{fancyvrb} | ||||
| 
 | ||||
| \usepackage{listings} | ||||
| %\setlength{\columnsep}{1.5cm} | ||||
| %\setlength{\columnseprule}{0.2pt} | ||||
| 
 | ||||
| \usepackage{colortbl,graphicx,tikz} | ||||
| \definecolor{X}{rgb}{.5,.5,.5} | ||||
| 
 | ||||
| \date{} | ||||
| \begin{document} | ||||
| \pagenumbering{gobble} | ||||
| 
 | ||||
| \lstset{ | ||||
|   language=C++,                % choose the language of the code | ||||
|   basicstyle=\linespread{1.1}\ttfamily, | ||||
|   columns=fixed, | ||||
|   fontadjust=true, | ||||
|   basewidth=0.5em, | ||||
|   keywordstyle=\color{blue}\bfseries, | ||||
|   commentstyle=\color{gray}, | ||||
|   stringstyle=\ttfamily\color{orange!50!black}, | ||||
|   showstringspaces=false, | ||||
|   %numbers=false,                   % where to put the line-numbers | ||||
|   numbersep=5pt, | ||||
|   numberstyle=\tiny\color{black}, | ||||
|   numberfirstline=true, | ||||
|   stepnumber=1,                   % the step between two line-numbers.         | ||||
|   numbersep=10pt,                  % how far the line-numbers are from the code | ||||
|   backgroundcolor=\color{white},  % choose the background color. You must add \usepackage{color} | ||||
|   showstringspaces=false,         % underline spaces within strings | ||||
|   captionpos=b,                   % sets the caption-position to bottom | ||||
|   breaklines=true,                % sets automatic line breaking | ||||
|   breakatwhitespace=true,         % sets if automatic breaks should only happen at whitespace | ||||
|   xleftmargin=.2in, | ||||
|   extendedchars=\true, | ||||
|   keepspaces = true, | ||||
| } | ||||
| \lstset{literate=% | ||||
|    *{0}{{{\color{red!20!violet}0}}}1 | ||||
|     {1}{{{\color{red!20!violet}1}}}1 | ||||
|     {2}{{{\color{red!20!violet}2}}}1 | ||||
|     {3}{{{\color{red!20!violet}3}}}1 | ||||
|     {4}{{{\color{red!20!violet}4}}}1 | ||||
|     {5}{{{\color{red!20!violet}5}}}1 | ||||
|     {6}{{{\color{red!20!violet}6}}}1 | ||||
|     {7}{{{\color{red!20!violet}7}}}1 | ||||
|     {8}{{{\color{red!20!violet}8}}}1 | ||||
|     {9}{{{\color{red!20!violet}9}}}1 | ||||
|     {~} {$\sim$}{1} | ||||
| } | ||||
| 
 | ||||
| \title{Семинар \#2: Инкапсуляция. Домашнее задание.\vspace{-5ex}}\date{}\maketitle | ||||
| 
 | ||||
| \section*{Класс Circle} | ||||
| Допустим, что мы хотим создать программу, которая будет работать с окружностями (это может быть игра или, например, графический редактор). Для того, чтобы сделать код более понятным и удобным в использовании, мы решили создать класс окружности. Кроме того, мы решили использовать уже ранее написанный класс точки в 2D пространстве (файлы \texttt{point.h} и \texttt{point.cpp}). Создайте класс окружности, который будет включать следующие методы: | ||||
| \begin{itemize} | ||||
| \item Конструктор \texttt{Circle(const Point\& acenter, float aradius)}, который будет задавать поля \texttt{center} и \texttt{radius} соответстующими значениями. | ||||
| \item Конструктор по умолчанию \texttt{Circle()} - задаются значения, соответствующие единичной окружности с центром в начале координат. | ||||
| \item Конструктор копирования \texttt{Circle(const Circle\& circle)} | ||||
| \item Сеттеры и геттеры, для полей \texttt{center} и \texttt{radius}. Поле \texttt{radius} нельзя задать отрицательным числом. При попытке задания его отрицательным числом оно должно устанавливаться в значение \texttt{0}. | ||||
| \item Метод \texttt{float getArea() const}, который будет возвращать площадь поверхности круга. | ||||
| \item Метод \texttt{float getDistance(const Point\& p) const}, который будет возвращать расстояние от точки \texttt{p}, до ближайшей точки окружности. | ||||
| \item Метод \texttt{bool isColliding(const Circle\& c) const}, который будет возвращать \texttt{true}, если круг пересекается с кругом \texttt{c}. | ||||
| \item Метод \texttt{void move(const Point\& p)}, который будет перемещать кружок на вектор \texttt{p}. | ||||
| \end{itemize} | ||||
| Весь начальный код содержится в папке \texttt{0circle}. При компиляции нужно указывать все \texttt{.cpp} файлы, которые вы хотите скомпилировать: | ||||
| \begin{verbatim} | ||||
| g++ main.cpp point.cpp | ||||
| \end{verbatim} | ||||
| \begin{itemize} | ||||
| \item Создайте файлы \texttt{circle.h} и \texttt{circle.cpp} и перенесите реализацию класса окружности из файла \texttt{main.cpp} в эти файлы. | ||||
| \end{itemize} | ||||
| 
 | ||||
| 
 | ||||
| \newpage | ||||
| \section*{Класс Number (большое число)} | ||||
| Стандартные целочисленные  типы данных, такие как \texttt{int} имеют фиксированный небольшой размер. Соответственно значения, которые можно хранить в переменных этих типов ограничены. Типичное максимальное значение \texttt{char} равно $2^7 - 1 = 127$, тип \texttt{int} обычно ограничен $2^{31}-1 = 2147483647$ и даже тип \texttt{unsigned long long} имеет ограничение в $2^{64}-1 = 1.8 * 10^{19}$. Хранить действительно большие числа в этих типах невозможно. В этом задании нужно сделать класс, с помощью которого будет удобно складывать и умножать большие целые положительные числа. Начальный код этого класса содержится в \texttt{1number/number.cpp}. Изучите этот код. | ||||
| 
 | ||||
| 
 | ||||
| \begin{figure}[h!] | ||||
|   \centering | ||||
|   \includegraphics[scale=1]{../images/number1.png} | ||||
|   \caption{Представление числа 12345678 в памяти с помощью нашего класса Number} | ||||
|   \label{fig:nummber1} | ||||
| \end{figure} | ||||
| 
 | ||||
| 
 | ||||
| \subsection*{Задания:} | ||||
| \begin{itemize} | ||||
| \item \textbf{Конструктор по умолчанию:} Напишите конструктор по умолчанию \texttt{Number()}, который будет создавать число равное нулю. | ||||
| \item \textbf{Конструктор копирования:} Напишите конструктор копирования \texttt{Number(const Number\& n)}. | ||||
| \item \textbf{Конструктор из строки:} Напишите конструктор \texttt{Number(const char* str)}, который будет создавать большое число на основе строки. Предполагаем, что на вход конструктору всегда идёт корректная строка. Например, число из примера можно будет создать так: | ||||
| \begin{lstlisting} | ||||
| Number a = Number("12345678"); | ||||
| \end{lstlisting} | ||||
| \item \textbf{Присваивание:} Напишите оператор присваивания \texttt{Number\& operator=(const Number\& right)}. | ||||
| \item \textbf{Сложение:} Напишите и протестируйте операторы сложения \texttt{operator+} и оператор присваивания сложения \texttt{operator+=}.  Реализовывать оба этих оператора с нуля необязательно. Ведь, если написан один из этих операторов, то очень просто написать другой. | ||||
| \item \textbf{Числа Фибоначчи:} Числа Фибоначчи задаются следующим образом: | ||||
| \begin{align*} | ||||
| F_0 &= 0\\ | ||||
| F_1 &= 1\\ | ||||
| F_n &= F_{n-1} + F_{n-2} | ||||
| \end{align*} | ||||
| Используйте класс \texttt{Number}, чтобы вычислить $F_{1000}$. Правильный ответ: | ||||
| \begin{verbatim} | ||||
| F(1000) = 43466557686937456435688527675040625802564660517371780402481729089536555417949051890 | ||||
| 40387984007925516929592259308032263477520968962323987332247116164299644090653318793829896964992 | ||||
| 8516003704476137795166849228875 | ||||
| \end{verbatim} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| \item \textbf{Четность:} Напишите метод \texttt{bool isEven() const}, который будет проверять является ли наше число чётным и, если это верно, возвращает \texttt{true}, в ином случае возвращает \texttt{false}. | ||||
| 
 | ||||
| \item \textbf{Произведение:} Напишите метод \texttt{Number operator*(const Number\& right) const} - оператор умножения одного числа \texttt{Number} на другое. Протестируйте вашу функцию на различных примерах (умножение большого числа на большое, умножение большого числа на небольшое ($< 100$) или на ноль, умножение двух небольших чисел и т. д.).\\ | ||||
| \item \textbf{Факториал:} Используйте написанный оператор для вычисления факториала от 1000. \\ | ||||
| Правильный ответ: | ||||
| \begin{verbatim} | ||||
| 1000! = 40238726007709377354370243392300398571937486421071463254379991042993851239862902059 | ||||
| 2044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759 | ||||
| 9188236277271887325197795059509952761208749754624970436014182780946464962910563938874378864 | ||||
| 8733711918104582578364784997701247663288983595573543251318532395846307555740911426241747434 | ||||
| 9347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379 | ||||
| 5345242215865932019280908782973084313928444032812315586110369768013573042161687476096758713 | ||||
| 4831202547858932076716913244842623613141250878020800026168315102734182797770478463586817016 | ||||
| 4365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186 | ||||
| 1168115536158365469840467089756029009505376164758477284218896796462449451607653534081989013 | ||||
| 8544248798495995331910172335555660213945039973628075013783761530712776192684903435262520001 | ||||
| 5888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838 | ||||
| 9714760885062768629671466746975629112340824392081601537808898939645182632436716167621791689 | ||||
| 0977991190375403127462228998800519544441428201218736174599264295658174662830295557029902432 | ||||
| 4153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690 | ||||
| 8979684825901254583271682264580665267699586526822728070757813918581788896522081643483448259 | ||||
| 9326604336766017699961283186078838615027946595513115655203609398818061213855860030143569452 | ||||
| 7224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136 | ||||
| 4932734975655139587205596542287497740114133469627154228458623773875382304838656889764619273 | ||||
| 8381490014076731044664025989949022222176590433990188601856652648506179970235619389701786004 | ||||
| 0811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614 | ||||
| 8396573822911231250241866493531439701374285319266498753372189406942814341185201580141233448 | ||||
| 2801505139969429015348307764456909907315243327828826986460278986432113908350621709500259738 | ||||
| 9863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826 | ||||
| 2809561214509948717012445164612603790293091208890869420285106401821543994571568059418727489 | ||||
| 9809425474217358240106367740459574178516082923013535808184009699637252423056085590370062427 | ||||
| 1243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000 | ||||
| 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||||
| 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 | ||||
| 0000000000000000000000000000 | ||||
| \end{verbatim} | ||||
| 
 | ||||
| \item \textbf{Числа-градины:} Возьмём некоторое число $n$ и будем последовательно применять к нему следующую функцию: | ||||
| \begin{equation*} | ||||
| f(n) =  | ||||
|     \begin{cases} | ||||
|       n / 2,   &\textup{если n - четное}\\  | ||||
|       3 n + 1, &\textup{если n - нечетное} | ||||
|     \end{cases} | ||||
| \end{equation*} | ||||
| В результате получится некоторая последовательность. Например, при $n = 7$ получится: | ||||
| \begin{verbatim} | ||||
| 7 -> 22 -> 11 -> 34 -> 17 -> 52 -> 26 -> 13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1 | ||||
| \end{verbatim} | ||||
| Последовательность доходит до 1. Вам нужно написать функцию, которая будет по начальному числу находить длину такой последовательности (\texttt{steps}) и максимальное число в этой последовательности(\texttt{max}). Например, для числа $7$, максимальное число в последовательности будет равно $52$, а длина последовательности -- $16$. Напишите программу, которая будет по начальному числу находить длину последовательности и максимальный элемент в ней. | ||||
| 
 | ||||
| Тесты для проверки: | ||||
| \begin{verbatim} | ||||
| n = 7                    steps = 16;      max = 52 | ||||
| n = 256                  steps = 8;       max = 256 | ||||
| n = 1117065              steps = 527;     max = 2974984576 | ||||
| n = 4761963248413673697  steps = 2337;    max = 9926927712374950744648 | ||||
| 
 | ||||
| n = 90560792656972947582439785608972465789628974587264056284658721771 | ||||
| steps = 1630;      | ||||
| max = 773658021643749360792171137214151494851244403993540980838080564520 | ||||
| \end{verbatim} | ||||
| Для решения этой задачи нужно написать оператор сравнения и метод деления на 2 (оператор целочисленного деления можно не писать).  | ||||
| \item \textbf{Раздельная компиляция:} Перенесите объявление класса \texttt{Number} в файл \texttt{number.h}, а определение методов в файл \texttt{number.cpp}. Раздельно скомпилируйте эту программу. | ||||
| \end{itemize} | ||||
| 
 | ||||
| \end{document} | ||||
		Reference in a new issue