├── .gitignore ├── LICENSE ├── README.md ├── algorithms ├── adhoc │ ├── date.h │ └── timest.h ├── brute_force │ └── next_combination.h ├── data_structures │ ├── fenwick_tree.h │ ├── product_fenwick_tree.h │ ├── segment_tree.h │ ├── segment_tree_bottom_up.h │ ├── segment_tree_with_lazy_propagation.h │ └── union_find.h ├── dp │ ├── lis.h │ ├── main_lis.cpp │ ├── max1Drangesum.h │ ├── max2Drangesum.h │ └── max3Drangesum.h ├── geometry │ ├── circle.h │ ├── line.h │ ├── point.h │ └── triangle.h ├── graph │ ├── 247.cpp │ ├── 315.cpp │ ├── bfs.h │ ├── bipartite.h │ ├── connected_components.h │ ├── dfs.h │ ├── dfs_topsort.h │ ├── edmonds_karp.h │ ├── graph.h │ ├── graph_check.h │ ├── has_cycle.h │ ├── kruskall.h │ ├── prim.h │ └── tarjan_scc.h └── io │ ├── BufferedIO.java │ ├── IO.java │ ├── async_io.h │ ├── buffered_io.h │ ├── cio.h │ └── io.h ├── tests ├── adhoc │ ├── Makefile │ ├── date.cpp │ └── timest.cpp ├── brute_force │ ├── Makefile │ └── next_combination.cpp ├── catch.hpp ├── data_structures │ ├── Makefile │ ├── segment_tree.cpp │ ├── segment_tree_bottom_up.cpp │ └── segment_tree_with_lazy_propagation.cpp ├── geometry │ ├── Makefile │ ├── circle.cpp │ ├── line.cpp │ └── point.cpp ├── graph │ ├── Makefile │ ├── bfs.cpp │ ├── bipartite.cpp │ ├── connected_components.cpp │ ├── dfs.cpp │ └── has_cycle.cpp └── io │ ├── Makefile │ ├── TestBufferedIO.java │ ├── TestIO.java │ ├── async_io.cpp │ ├── buffered_io.cpp │ ├── cio.c │ ├── ints_100K.in │ ├── ints_1M.in │ └── io.cpp └── util └── bitwise_operations.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.cc 2 | *.class 3 | *.o 4 | *.swp 5 | *.exe 6 | prog 7 | out.txt 8 | elapsed.txt 9 | files 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | 167 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algoritmos 2 | 3 | Códigos para estudo e ensino. 4 | 5 | As classes são codificadas de modo que possam ser copiadas e coladas para uso em resolução de 6 | problemas de programação competitiva. Deste modo, são feitas algumas concessões em relação às 7 | boas práticas de Engenharia de Software (uso de variáveis globais, implementação nos _headers_, 8 | etc) para atingir tal fim. Logo, as classes não visam o reuso e a aplicação em ambientes de 9 | produção. 10 | -------------------------------------------------------------------------------- /algorithms/adhoc/date.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe para a representação de datas (em dias, meses e anos). 3 | * 4 | * Autor: Edson Alves 5 | * Data: 25/03/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef DATE_H 9 | #define DATE_H 10 | 11 | #include 12 | 13 | static const int days_in_month_regular[] {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 14 | static const int days_in_month_leap[] {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 15 | 16 | class Date { 17 | public: 18 | Date(int d = 0, int m = 0, int y = 0) : m_d(d), m_m(m), m_y(y) { } 19 | 20 | void add(int days) 21 | { 22 | long long date_days = days_from_zero(m_d, m_m, m_y); 23 | date_days += days; 24 | date_from_days(date_days, m_d, m_m, m_y); 25 | } 26 | 27 | int day() const { return m_d; } 28 | int month() const { return m_m; } 29 | int year() const { return m_y; } 30 | 31 | std::string format() const 32 | { 33 | char buffer[32]; 34 | sprintf(buffer, "%02d/%02d/%04d", m_d, m_m, m_y); 35 | 36 | return std::string(buffer); 37 | } 38 | 39 | long long operator-(const Date& d) const 40 | { 41 | return days_from_zero(m_d, m_m, m_y) - days_from_zero(d.day(), d.month(), d.year()); 42 | } 43 | 44 | static bool is_leap(int year) 45 | { 46 | return (year % 400 == 0) or (year % 4 == 0 and year % 100 != 0); 47 | } 48 | 49 | static Date from_days(long long days) 50 | { 51 | int d, m, y; 52 | date_from_days(days, d, m, y); 53 | return Date(d, m, y); 54 | } 55 | 56 | private: 57 | int m_d, m_m, m_y; 58 | 59 | static int leaps(int y) 60 | { 61 | int div4 = y / 4; 62 | int div100 = y / 100; 63 | int div400 = y / 400; 64 | 65 | return div4 - div100 + div400; 66 | } 67 | 68 | static long long days_from_zero(int d, int m, int y) 69 | { 70 | long long days = d; 71 | const int *days_in_month = Date::is_leap(y) ? days_in_month_leap : days_in_month_regular; 72 | 73 | for (int i = 1; i < m; i++) 74 | days += days_in_month[i]; 75 | 76 | int leap_years = leaps(y - 1); 77 | days += 365*y + leap_years; 78 | 79 | return days; 80 | } 81 | 82 | static void date_from_days(int days, int& d, int &m, int& y) 83 | { 84 | y = days / 366; 85 | 86 | while (days_from_zero(0, 0, y + 1) < days) 87 | y++; 88 | 89 | days -= days_from_zero(0, 0, y); 90 | 91 | const int *days_in_month = Date::is_leap(y) ? days_in_month_leap : days_in_month_regular; 92 | 93 | m = 1; 94 | 95 | while (days > days_in_month[m]) 96 | { 97 | days -= days_in_month[m]; 98 | m++; 99 | } 100 | 101 | d = days; 102 | } 103 | }; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /algorithms/adhoc/timest.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe para a representação de tempo (em horas, minutos e segundos). 3 | * 4 | * Autor: Edson Alves 5 | * Data: 24/03/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef TIMEST_H 9 | #define TIMEST_H 10 | 11 | #include 12 | 13 | const int SECS_IN_A_DAY { 86400 }; 14 | const int SECS_IN_A_HOUR { 3600 }; 15 | const int SECS_IN_A_MIN { 60 }; 16 | 17 | class Time { 18 | public: 19 | Time(int h = 0, int m = 0, int s = 0) 20 | { 21 | m_secs = SECS_IN_A_HOUR*h + SECS_IN_A_MIN*m + s; 22 | } 23 | 24 | int hours() const 25 | { 26 | int h = m_secs / SECS_IN_A_HOUR; 27 | return h; 28 | } 29 | 30 | int minutes() const 31 | { 32 | int m = (m_secs % SECS_IN_A_HOUR) / SECS_IN_A_MIN; 33 | return m; 34 | } 35 | 36 | int seconds() const 37 | { 38 | int s = m_secs % SECS_IN_A_MIN; 39 | return s; 40 | } 41 | 42 | void add(const Time& t) 43 | { 44 | m_secs += t.m_secs; 45 | m_secs %= SECS_IN_A_DAY; 46 | } 47 | 48 | std::string format() const 49 | { 50 | char buffer[32]; 51 | sprintf(buffer, "%02d:%02d:%02d", hours(), minutes(), seconds()); 52 | 53 | return std::string(buffer); 54 | } 55 | 56 | private: 57 | int m_secs; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /algorithms/brute_force/next_combination.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Rotina que gera as C(n, m) combinações. 3 | * 4 | * Baseada no artigo The Coolest Way To Generate Combinations, de Frank Ruskey e Aaron Williams. 5 | * Uma combinação será representada por uma string s de zeros e uns, onde s[i] = 1 indica que o 6 | * elemento i pertence à combinação. Cada combinação é gerada em O(1): a estratégia de chamar 7 | * prev_permutation() a partir da string inicial s = "11111...100000" tem complexidade O(n) por 8 | * combinação. 9 | * 10 | * Autor: Edson Alves 11 | * Data: 11/05/2018 12 | * Licença: LGPL. Sem copyright. 13 | */ 14 | #ifndef COMBINATIONS_H 15 | #define COMBINATIONS_H 16 | 17 | #include 18 | 19 | // Na primeira chamada, a string combination deve ser nula (size == 0) 20 | bool next_combination(int n, int m, std::string& combination, int& x, int& y) 21 | { 22 | // Caso base: primeira combinação 23 | if (combination.empty()) 24 | { 25 | combination = std::string(m, '1'); 26 | combination.resize(n, '0'); 27 | 28 | x = -1; 29 | y = -1; 30 | 31 | return true; 32 | } 33 | 34 | // Caso base: inicialização de x e y 35 | if (y == -1) 36 | { 37 | combination[m] = '1'; 38 | combination[0] = '0'; 39 | x = 1; 40 | y = 0; 41 | 42 | return true; 43 | } 44 | 45 | // Caso base: não há mais combinações 46 | if (x == n - 1) 47 | return false; 48 | 49 | combination[x] = '0'; 50 | combination[y] = '1'; 51 | combination[0] = combination[x + 1]; 52 | combination[x + 1] = '1'; 53 | 54 | x = x * (1 - (combination[1] - '0') + (combination[1] - '0')*(combination[0] - '0')) + 1; 55 | y = (y + 1)*(combination[0] - '0'); 56 | 57 | return true; 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /algorithms/data_structures/fenwick_tree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe Fenwick (BIT) Tree 3 | * 4 | * Esta versão mais simples suporta Point Updates com Range Queries. 5 | * 6 | * Autor: Edson Alves 7 | * Data: 04/09/2015 8 | * Licença: LGPL. Sem copyright. 9 | */ 10 | #ifndef FENWICK_TREE_H 11 | #define FENWICK_TREE_H 12 | 13 | #include 14 | 15 | using namespace std; 16 | 17 | typedef long long ll; 18 | 19 | #define FENWICK_TREE_MAX 1000005 20 | 21 | ll tree[FENWICK_TREE_MAX]; 22 | 23 | inline ll least_significative_bit(ll n) { return n & (-n); } 24 | 25 | class FenwickTree 26 | { 27 | public: 28 | FenwickTree(ll N) 29 | : m_N(N) 30 | { 31 | memset(tree, 0, (N + 1) * sizeof(ll)); 32 | } 33 | 34 | ll RSQ(ll a, ll b) 35 | { 36 | return a == 1 ? RSQ(b) : RSQ(b) - RSQ(a - 1); 37 | } 38 | 39 | void update(ll k, ll v) 40 | { 41 | while (k <= m_N) 42 | { 43 | tree[k] += v; 44 | k += least_significative_bit(k); 45 | } 46 | } 47 | 48 | private: 49 | ll RSQ(ll b) 50 | { 51 | ll sum = 0; 52 | 53 | while (b) 54 | { 55 | sum += tree[b]; 56 | b -= least_significative_bit(b); 57 | } 58 | 59 | return sum; 60 | } 61 | 62 | private: 63 | ll m_N; 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /algorithms/data_structures/product_fenwick_tree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe Fenwick (BIT) Tree para sinal do produto dos elementos. 3 | * 4 | * Os pares do vetor ft armazenam, respectivamente, o número de zeros e o 5 | * sinal do produto no intervalo correspondente ao índice i. 6 | * 7 | * Para modificar o valor do elemento na posição i, é preciso primeiro 8 | * apagar o elemento (método erase()) para depois chamar o update(). 9 | * 10 | * Autor: Edson Alves 11 | * Data: 07/09/2015 12 | * Licença: LGPL. Sem copyright. 13 | */ 14 | #ifndef PRODUCT_FENWICK_TREE_H 15 | #define PRODUCT_FENWICK_TREE_H 16 | 17 | #include 18 | 19 | using namespace std; 20 | 21 | #define LSB(n) ((n) & (-n)) 22 | 23 | class ProductFenwickTree 24 | { 25 | private: 26 | int m_N; 27 | vector< pair > ft; 28 | vector ns; 29 | 30 | public: 31 | ProductFenwickTree(int N) 32 | : m_N(N) 33 | { 34 | ft.assign(N + 1, make_pair(0, 1)); 35 | ns.assign(N + 1, 1); 36 | } 37 | 38 | int RPQ(int a, int b) 39 | { 40 | auto A = (a == 1) ? make_pair(0, 1) : RPQ(a - 1); 41 | auto B = RPQ(b); 42 | 43 | return (B.first > A.first) ? 0 : B.second * A.second; 44 | } 45 | 46 | void erase(int i) 47 | { 48 | int n = i; 49 | 50 | while (n <= m_N) 51 | { 52 | switch (ns[i]) { 53 | case 0: 54 | --ft[n].first; 55 | break; 56 | 57 | case -1: 58 | ft[n].second *= -1; 59 | break; 60 | } 61 | 62 | n += LSB(n); 63 | } 64 | 65 | ns[i] = 1; 66 | } 67 | 68 | void update(int i, int v) 69 | { 70 | int n = i; 71 | 72 | while (n <= m_N) 73 | { 74 | switch (v) { 75 | case 0: 76 | ++ft[n].first; 77 | break; 78 | 79 | case -1: 80 | ft[n].second *= -1; 81 | break; 82 | } 83 | 84 | n += LSB(n); 85 | } 86 | 87 | ns[i] = v; 88 | } 89 | 90 | private: 91 | 92 | pair RPQ(int b) 93 | { 94 | auto p = make_pair(0, 1); 95 | 96 | while (b) 97 | { 98 | p.first += ft[b].first; 99 | p.second *= ft[b].second; 100 | b -= LSB(b); 101 | } 102 | 103 | return p; 104 | } 105 | }; 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /algorithms/data_structures/segment_tree.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que representa uma árvore de segmentos. 3 | * 4 | * Suporta range queries e point updates, com implementação recursiva. 5 | * 6 | * Autor: Edson Alves 7 | * Data: 06/05/2018 8 | * Licença: LGPL. Sem copyright. 9 | */ 10 | #ifndef SEGMENT_TREE_H 11 | #define SEGMENT_TREE_H 12 | 13 | using std::vector; 14 | 15 | 16 | template 17 | class SegmentTree 18 | { 19 | int n; 20 | vector tree; 21 | 22 | public: 23 | SegmentTree(int N) 24 | : n(N), tree(4*n, 0) // 4N is a upper bound to the number of nodes 25 | { 26 | } 27 | 28 | T sum(int i, int j) 29 | { 30 | return sum(1, 0, n - 1, i, j); 31 | } 32 | 33 | void add(int i, T value) 34 | { 35 | add(1, 0, n - 1, i, value); 36 | } 37 | 38 | int size() const 39 | { 40 | return tree.size(); 41 | } 42 | 43 | private: 44 | 45 | int left(int p) 46 | { 47 | return 2 * p; 48 | } 49 | 50 | int right(int p) 51 | { 52 | return 2 * p + 1; 53 | } 54 | 55 | T sum(int p, int L, int R, int i, int j) 56 | { 57 | if (i > R or j < L) // [i, j] don't intersect [L, R] 58 | return 0; 59 | 60 | if (i <= L and R <= j) // [i, j] contain [L, R] 61 | return tree[p]; 62 | 63 | T a = sum(left(p), L, (L + R)/2, i, j); 64 | T b = sum(right(p), (L + R)/2 + 1, R, i, j); 65 | 66 | return a + b; 67 | } 68 | 69 | void add(int p, int L, int R, int a, T value) 70 | { 71 | if (a > R or a < L) // Base case: a is not int [L, R] 72 | return; 73 | 74 | tree[p] += value; 75 | 76 | if (L == R) // Base case: we reached a leaf 77 | return; 78 | 79 | add(left(p), L, (L+R)/2, a, value); 80 | add(right(p), (L+R)/2 + 1, R, a, value); 81 | } 82 | }; 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /algorithms/data_structures/segment_tree_bottom_up.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que representa uma árvore de segmentos. 3 | * 4 | * Esta versão suporta range queries e point updates e não usa recursão. Baseada no exemplo 5 | * dado no livro Competitive Programmers Handbook's, pg. 89. 6 | * 7 | * Autor: Edson Alves 8 | * Data: 04/05/2017 9 | * Licença: LGPL. Sem copyright. 10 | */ 11 | #ifndef SEGMENT_TREE_H 12 | #define SEGMENT_TREE_H 13 | 14 | #include 15 | 16 | using std::vector; 17 | 18 | 19 | template 20 | class SegmentTree 21 | { 22 | int n; 23 | vector tree; 24 | 25 | public: 26 | SegmentTree(int N) 27 | : n(least_power_of_2_greater_or_equals(N)), tree(2*n, 0) 28 | { 29 | } 30 | 31 | void add(int i, T v) // Adds v to position i 32 | { 33 | int a = i + n; 34 | 35 | tree[a] += v; // Update the leaf 36 | 37 | while (a >>= 1) 38 | tree[a] = tree[2*a] + tree[2*a + 1]; // Update its parents 39 | } 40 | 41 | T sum(int i, int j) 42 | { 43 | int a = i + n, b = j + n; // The leaves are in second half of tree array 44 | T s = 0; 45 | 46 | while (a <= b) 47 | { 48 | if (a & 1) // a is a right child and must be added to the total 49 | s += tree[a++]; 50 | 51 | if (not (b & 1)) // b is a left child and must be added to the total 52 | s += tree[b--]; 53 | 54 | // If a is a left child of b is a right child the parent node covers them 55 | 56 | // Move up one level 57 | a /= 2; 58 | b /= 2; 59 | } 60 | 61 | return s; 62 | } 63 | 64 | int size() const 65 | { 66 | return n; 67 | } 68 | }; 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /algorithms/data_structures/segment_tree_with_lazy_propagation.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que representa uma árvore de segmentos. 3 | * 4 | * Esta versão suporta range updates com lazy propagation. 5 | * 6 | * Autor: Edson Alves 7 | * Data: 30/09/2015 8 | * Licença: LGPL. Sem copyright. 9 | */ 10 | #ifndef SEGMENT_TREE_H 11 | #define SEGMENT_TREE_H 12 | 13 | #include 14 | 15 | using namespace std; 16 | using std::vector; 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | template 23 | class SegmentTree 24 | { 25 | int n; 26 | vector tree, lazy; 27 | 28 | public: 29 | SegmentTree(int N) 30 | : n(N), tree(4*n, 0), lazy(4*n, 0) // 4N is a upper bound to the number of nodes 31 | { 32 | } 33 | 34 | T sum(int i, int j) 35 | { 36 | return sum(1, 0, n - 1, i, j); 37 | } 38 | 39 | void add(int i, int j, T v) 40 | { 41 | add(1, 0, n - 1, i, j, v); 42 | } 43 | 44 | private: 45 | 46 | int left(int p) 47 | { 48 | return 2 * p; 49 | } 50 | 51 | int right(int p) 52 | { 53 | return 2 * p + 1; 54 | } 55 | 56 | T sum(int p, int L, int R, int a, int b) 57 | { 58 | // Lazy propagation 59 | if (lazy[p]) 60 | { 61 | tree[p] += (R - L + 1) * lazy[p]; 62 | 63 | if (L < R) // If its not a leaf and not zero, propagates 64 | { 65 | lazy[left(p)] += lazy[p]; 66 | lazy[right(p)] += lazy[p]; 67 | } 68 | 69 | lazy[p] = 0; 70 | } 71 | 72 | if (a > R or b < L) // Base case: [a, b] intersection [L, R] is empty 73 | return 0; 74 | 75 | if (a <= L and R <= b) // Base case: [a, b] contain [L, R] 76 | return tree[p]; 77 | 78 | T x = sum(left(p), L, (L + R)/2, a, b); 79 | T y = sum(right(p), (L + R)/2 + 1, R, a, b); 80 | 81 | return x + y; 82 | } 83 | 84 | void add(int p, int L, int R, int a, int b, T value) 85 | { 86 | // Lazy propagation 87 | if (lazy[p]) 88 | { 89 | tree[p] += (R - L + 1) * lazy[p]; 90 | 91 | if (L < R) // If its not a leaf and not zero, propagates 92 | { 93 | lazy[left(p)] += lazy[p]; 94 | lazy[right(p)] += lazy[p]; 95 | } 96 | 97 | lazy[p] = 0; 98 | } 99 | 100 | if (a > R or b < L) // Base case: [a, b] intersection [L, R] is empty 101 | return; 102 | 103 | if (a <= L and R <= b) // Base case: [a, b] contain [L, R] 104 | { 105 | tree[p] += (R - L + 1) * value; 106 | 107 | if (L < R) // If its not a leaf and not zero, propagates 108 | { 109 | lazy[left(p)] += value; 110 | lazy[right(p)] += value; 111 | } 112 | 113 | return; 114 | } 115 | 116 | add(left(p), L, (L + R)/2, a, b, value); 117 | add(right(p), (L + R)/2 + 1, R, a, b, value); 118 | 119 | tree[p] = tree[left(p)] + tree[right(p)]; 120 | } 121 | 122 | public: 123 | void print() const 124 | { 125 | queue> q; 126 | 127 | q.emplace(1, 0, n - 1, tree[1], lazy[1]); 128 | 129 | while (not q.empty()) 130 | { 131 | int p, a, b, v, L; 132 | 133 | tie(p, a, b, v, L) = q.front(); 134 | q.pop(); 135 | 136 | cout << "[" << a << ", " << b << "] = " << v << ", lazy = " << L << '\n'; 137 | 138 | if (a < b) 139 | { 140 | q.emplace(2*p, a, (a + b)/2, tree[2*p], lazy[2*p]); 141 | q.emplace(2*p + 1, (a + b)/2 + 1, b, tree[2*p + 1], lazy[2*p + 1]); 142 | } 143 | } 144 | } 145 | }; 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /algorithms/data_structures/union_find.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe UDFS (Union-Find Disjoint Sets) 3 | * 4 | * Autor: Edson Alves 5 | * Data: 31/08/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef UNION_FIND_H 9 | #define UNION_FIND_H 10 | 11 | #define UDFS_MAX_N 1000005 12 | 13 | int parent[UDFS_MAX_N]; 14 | int rank[UDFS_MAX_N]; 15 | 16 | class UnionFind 17 | { 18 | public: 19 | UnionFind(int N) 20 | : m_N(N), m_count(N) 21 | { 22 | for (int i = 1; i <= N; ++i) 23 | { 24 | parent[i] = i; 25 | rank[i] = 0; 26 | } 27 | } 28 | 29 | bool is_same_set(int i, int j) 30 | { 31 | return find_set(i) == find_set(j); 32 | } 33 | 34 | void union_set(int i, int j) 35 | { 36 | if (is_same_set(i, j)) 37 | return; 38 | 39 | int p = find_set(i); 40 | int q = find_set(j); 41 | 42 | if (rank[p] > rank[q]) 43 | parent[q] = p; 44 | else if (rank[q] > rank[p]) 45 | parent[p] = q; 46 | else 47 | { 48 | parent[q] = p; 49 | ++rank[p]; 50 | } 51 | 52 | --m_count; 53 | } 54 | 55 | int count() const { return m_count; } 56 | 57 | int find_set(int i) 58 | { 59 | int p = i; 60 | 61 | vector ps; 62 | 63 | while (p != parent[p]) 64 | { 65 | ps.push_back(p); 66 | p = parent[p]; 67 | } 68 | 69 | for (auto x : ps) 70 | { 71 | parent[x] = p; 72 | } 73 | 74 | return p; 75 | } 76 | 77 | private: 78 | int m_N; 79 | int m_count; 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /algorithms/dp/lis.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que contém algoritmos para o problema LIS (longest increasing 3 | * subsequence). 4 | * 5 | * Autor: Edson Alves 6 | * Data: 01/10/2015 7 | * Licença: LGPL. Sem copyright. 8 | */ 9 | #ifndef LIS_H 10 | #define LIS_H 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #define LIS_MAX_N 1000010 17 | 18 | int lis[LIS_MAX_N], index[LIS_MAX_N], parent[LIS_MAX_N]; 19 | 20 | using std::vector; 21 | using std::max; 22 | using std::lower_bound; 23 | 24 | class LIS 25 | { 26 | public: 27 | 28 | /* O algoritmo DP tem por estado LIS(i), que contém o tamanho da maior 29 | * subsequencia crescente que termina no índice i do array base. 30 | * Cada etapa tenha estender as sequências anteriores, escolhendo a 31 | * maior delas possível. 32 | * 33 | * Complexidade: O(n^2) 34 | */ 35 | static int dp(const vector& v) 36 | { 37 | size_t N = v.size(); 38 | int max_len = 0; 39 | 40 | for (size_t i = 0; i < N; ++i) 41 | { 42 | lis[i] = 1; 43 | 44 | for (size_t j = 0; j < i; ++j) 45 | { 46 | if (v[i] >= v[j]) 47 | lis[i] = max(lis[j] + 1, lis[i]); 48 | } 49 | 50 | max_len = max(lis[i], max_len); 51 | } 52 | 53 | return max_len; 54 | } 55 | 56 | /* A solução gulosa com D&C mantém um vetor ordenado (lis) que contém 57 | * o menor elemento que encerra uma subsequência de comprimento i, e 58 | * procurar pelo maior elemento menor do que A[i] para tentar ampliar 59 | * ou melhorar a sequência lis. 60 | * 61 | * Complexidade: O(n log k), k - comprimento de lis 62 | */ 63 | static int greedy(const vector& A) 64 | { 65 | lis[0] = A[0]; 66 | index[0] = 0; 67 | parent[0] = 0; 68 | int k = 1; 69 | 70 | for (size_t i = 1; i < A.size(); ++i) 71 | { 72 | parent[i] = i; 73 | 74 | auto it = lower_bound(lis, lis + k, A[i]); 75 | 76 | if (it == lis + k) 77 | { 78 | parent[i] = index[k - 1]; 79 | lis[k] = A[i]; 80 | index[k++] = i; 81 | } else 82 | { 83 | int pos = it - lis; 84 | 85 | if (lis[pos] > A[i]) 86 | { 87 | lis[pos] = A[i]; 88 | index[pos] = i; 89 | 90 | if (pos > 0) 91 | parent[i] = index[pos - 1]; 92 | } 93 | } 94 | } 95 | 96 | return k; 97 | } 98 | }; 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /algorithms/dp/main_lis.cpp: -------------------------------------------------------------------------------- 1 | #include "lis.h" 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | vector A { -7, 10, 9, 2, 3, 8, 8, 1, 2, 3, 4 }; 8 | 9 | cout << LIS::greedy(A) << endl; 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /algorithms/dp/max1Drangesum.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que contém algoritmos para o problema max 1D range sum. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 28/09/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef MAX_1D_RANGE_SUM_H 9 | #define MAX_1D_RANGE_SUM_H 10 | 11 | #include 12 | 13 | using std::vector; 14 | 15 | class Max1DRangeSum 16 | { 17 | public: 18 | 19 | /* O algoritmo de Kadane tenta ampliar a soma de forma gulosa, resetando-a 20 | * caso se torne negativa (melhor reiniciar de zero do que partir de uma 21 | * quantia negativa). Equivale a uma DP de um parâmetro como redução de 22 | * memória. 23 | * 24 | * Complexidade: O(n) 25 | */ 26 | static int kadane(const vector& v) 27 | { 28 | int sum = 0, max_sum = 0; 29 | 30 | for (auto n : v) 31 | { 32 | sum += n; 33 | max_sum = max(sum, max_sum); 34 | 35 | if (sum < 0) sum = 0; 36 | } 37 | 38 | return max_sum; 39 | } 40 | 41 | /* Algoritmo DP para o problema. É mais lento do que o algoritmo de 42 | * Kadane, porém é mais geral e adaptável. Pré-computa as somas acumuladas 43 | * e depois testa todos os pares de índices possíveis em busca da 44 | * maior soma. 45 | * 46 | * Complexidade: O(n^2) 47 | */ 48 | static int dp(const vector& v) 49 | { 50 | // Caso trivial 51 | if (v.size() == 0) 52 | return 0; 53 | 54 | // Pré-computa as somas acumuladas 55 | vector& a { v[0] }; 56 | 57 | for (size_t i = 1; i < v.size(); ++i) 58 | a[i] += a[i - 1]; 59 | 60 | /* Testa todos os pares possíveis: 61 | * Soma[0, j] = a[j] 62 | * Soma[i, j] = a[j] - a[i - j], i != 0 63 | */ 64 | int max_sum = 0; 65 | 66 | for (size_t i = 0; i < v.size(): ++i) 67 | for (size_t j = i; j < v.size(); ++j) 68 | { 69 | if (i == 0) 70 | max_sum = max(a[j], max_sum); 71 | else 72 | max_sum = max(a[j] - a[i - 1], max_sum); 73 | } 74 | 75 | return max_sum; 76 | } 77 | }; 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /algorithms/dp/max2Drangesum.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que contém algoritmos para o problema max 2D range sum. 3 | * 4 | * Os pontos P e Q representam o canto superior esquerdo e o ponto inferior 5 | * direito do retângulo, respectivamente. 6 | * 7 | * Autor: Edson Alves 8 | * Data: 28/09/2015 9 | * Licença: LGPL. Sem copyright. 10 | */ 11 | #ifndef MAX_2D_RANGE_SUM_H 12 | #define MAX_2D_RANGE_SUM_H 13 | 14 | #include 15 | #include 16 | 17 | using std::vector; 18 | using std::max; 19 | 20 | #define MAX_N 110 21 | 22 | class Max2DRangeSum 23 | { 24 | public: 25 | 26 | /* Algoritmo de Busca Completa para o problema. Lento, mas correto. 27 | * 28 | * Complexidade: O(n^6) 29 | */ 30 | static int cs(const int A[][MAX_N], int m, int n) 31 | { 32 | int max_sum = -(1 << 30); 33 | 34 | // Escolhe a região retangular 35 | for (int px = 0; px < m; ++px) 36 | for (int py = 0; py < n; ++py) 37 | for (int qx = px; qx < m; ++qx) 38 | for (int qy = py; qy < n; ++qy) 39 | { 40 | int sum = 0; 41 | 42 | // Computa a soma da região retangular 43 | for (int i = px; i <= qx; ++i) 44 | for (int j = py; j <= qy; ++j) 45 | sum += A[i][j]; 46 | 47 | max_sum = max(sum, max_sum); 48 | } 49 | 50 | return max_sum; 51 | } 52 | 53 | /* Algoritmo DP para o problema. Pré-computa as somas acumuladas 54 | * e depois testa todos os pares de índices possíveis em busca da 55 | * maior soma. Evita a soma de um termo múltiplas vezes utilizando o 56 | * princípio a inclusão-exclusão. 57 | * 58 | * Obs.: o algoritmo irá modificar a matriz de entrada para guardar as 59 | * somas acumuladas. 60 | * 61 | * Complexidade: O(n^4) 62 | */ 63 | static int dp(int A[][MAX_N], int m, int n) 64 | { 65 | // Pré-computa as somas acumuladas 66 | for (int i = 0; i < m; ++i) 67 | for (int j = 0; j < n; ++j) 68 | { 69 | if (i > 0) A[i][j] += A[i - 1][j]; 70 | if (j > 0) A[i][j] += A[i][j - 1]; 71 | if (i > 0 and j > 0) A[i][j] -= A[i - 1][j - 1]; 72 | } 73 | 74 | // Testa todos os pares possíveis: 75 | int max_sum = -(1 << 30); 76 | 77 | for (int px = 0; px < m; ++px) 78 | for (int py = 0; py < n; ++py) 79 | for (int qx = px; qx < m; ++qx) 80 | for (int qy = py; qy < n; ++qy) 81 | { 82 | int sum = A[qx][qy]; 83 | 84 | if (px > 0) sum -= A[px - 1][qy]; 85 | if (py > 0) sum -= A[qx][py - 1]; 86 | if (px > 0 and py > 0) sum += A[px - 1][py - 1]; 87 | 88 | max_sum = max(sum, max_sum); 89 | } 90 | 91 | return max_sum; 92 | } 93 | }; 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /algorithms/dp/max3Drangesum.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | #define MAX 22 6 | 7 | long long M[MAX][MAX][MAX]; 8 | 9 | int main() 10 | { 11 | int T; 12 | scanf("%d", &T); 13 | 14 | for (int test = 0; test < T; ++test) 15 | { 16 | int A, B, C; 17 | scanf("%d %d %d", &A, &B, &C); 18 | 19 | for (int x = 0; x < A; ++x) 20 | for (int y = 0; y < B; ++y) 21 | for (int z = 0; z < C; ++z) 22 | { 23 | scanf("%lld", &M[x][y][z]); 24 | 25 | if (x > 0) M[x][y][z] += M[x - 1][y][z]; 26 | if (y > 0) M[x][y][z] += M[x][y - 1][z]; 27 | if (z > 0) M[x][y][z] += M[x][y][z - 1]; 28 | 29 | if (x > 0 and y > 0) M[x][y][z] -= M[x - 1][y - 1][z]; 30 | if (x > 0 and z > 0) M[x][y][z] -= M[x - 1][y][z - 1]; 31 | if (y > 0 and y > 0) M[x][y][z] -= M[x][y - 1][z - 1]; 32 | 33 | if (x > 0 and y > 0 and z > 0) M[x][y][z] += M[x-1][y-1][z-1]; 34 | } 35 | 36 | long long max_sum = -(1LL << 60); 37 | 38 | for (int x = 0; x < A; ++x) 39 | for (int y = 0; y < B; ++y) 40 | for (int z = 0; z < C; ++z) 41 | for (int a = x; a < A; ++a) 42 | for (int b = y; b < B; ++b) 43 | for (int c = z; c < C; ++c) 44 | { 45 | long long sum = M[a][b][c]; 46 | 47 | if (x > 0) sum -= M[x - 1][b][c]; 48 | if (y > 0) sum -= M[a][y - 1][c]; 49 | if (z > 0) sum -= M[a][b][z - 1]; 50 | 51 | if (x > 0 and y > 0) sum += M[x - 1][y - 1][c]; 52 | if (x > 0 and z > 0) sum += M[x - 1][b][z - 1]; 53 | if (y > 0 and y > 0) sum += M[a][y - 1][z - 1]; 54 | 55 | if (x > 0 and y > 0 and z > 0) sum -= M[x-1][y-1][z-1]; 56 | 57 | max_sum = max(sum, max_sum); 58 | } 59 | 60 | if (test) printf("\n"); 61 | 62 | printf("%lld\n", max_sum); 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /algorithms/geometry/circle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que representa um círculo no espaço bidimensional 3 | * 4 | * Autor: Edson Alves 5 | * Data: 18/07/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef GEOMETRY_CIRCLE_H 9 | #define GEOMETRY_CIRCLE_H 10 | 11 | #include 12 | 13 | #include "point.h" 14 | 15 | class Circle { 16 | public: 17 | Point C; 18 | double r; 19 | 20 | typedef enum { IN, OUT, ON } PointPosition; 21 | 22 | Circle(const Point& Cv = Point(0.0, 0.0), double rv = 1.0) : C(Cv), r(rv) {} 23 | 24 | bool operator==(const Circle& c) const 25 | { 26 | return C == c.C and equals(r, c.r); 27 | } 28 | 29 | bool operator!=(const Circle& c) const 30 | { 31 | return not (*this == c); 32 | } 33 | 34 | PointPosition position(const Point& P) const 35 | { 36 | auto d = P.distance(C); 37 | 38 | return equals(d, r) ? ON : (d < r ? IN : OUT); 39 | } 40 | 41 | double perimeter() const 42 | { 43 | return 2.0 * M_PI * r; 44 | } 45 | 46 | double area() const 47 | { 48 | return M_PI * r * r; 49 | } 50 | 51 | double arc(double a) const 52 | { 53 | return (a / (2*M_PI)) * perimeter(); 54 | } 55 | 56 | double chord(double a) const 57 | { 58 | return 2 * r * sin(a/2); 59 | } 60 | 61 | double sector(double a) const 62 | { 63 | return (a / (2*M_PI)) * area(); 64 | } 65 | 66 | double segment(double a) const 67 | { 68 | auto c = chord(a); 69 | auto s = (r + r + c)/2.0; // Semiperímetro 70 | auto T = sqrt(s*(s - r)*(s - r)*(s - c)); // Área do triângulo 71 | 72 | return sector(a) - T; 73 | } 74 | 75 | static std::vector 76 | from_2_points_and_radius(const Point& P, const Point& Q, double r) 77 | { 78 | std::vector cs; 79 | 80 | if (P == Q) 81 | { 82 | cs.push_back(Circle(P.translate(r, 0), r)); 83 | cs.push_back(Circle(P.translate(0, r), r)); 84 | cs.push_back(Circle(P.translate(-r, 0), r)); 85 | cs.push_back(Circle(P.translate(0, -r), r)); 86 | 87 | return cs; 88 | } 89 | 90 | double d2 = (P.x - Q.x) * (P.x - Q.x) + (P.y - Q.y) * (P.y - Q.y); 91 | double det = r * r / d2 - 0.25; 92 | 93 | if (det < 0.0) 94 | return cs; 95 | 96 | double h = sqrt(det); 97 | 98 | auto x = (P.x + Q.x) * 0.5 + (P.y - Q.y) * h; 99 | auto y = (P.y + Q.y) * 0.5 + (Q.x - P.x) * h; 100 | 101 | cs.push_back(Circle(Point(x, y), r)); 102 | 103 | x = (Q.x + P.x) * 0.5 + (Q.y - P.y) * h; 104 | y = (Q.y + P.y) * 0.5 + (P.x - Q.x) * h; 105 | 106 | cs.push_back(Circle(Point(x, y), r)); 107 | 108 | return cs; 109 | } 110 | 111 | static std::vector 112 | from_3_points(const Point& P, const Point& Q, const Point& R) 113 | { 114 | std::vector cs; 115 | 116 | auto a = 2*(Q.x - P.x); 117 | auto b = 2*(Q.y - P.y); 118 | auto c = 2*(R.x - P.x); 119 | auto d = 2*(R.y - P.y); 120 | 121 | auto det = a*d - b*c; 122 | 123 | // Colinear points 124 | if (equals(det, 0)) 125 | return cs; 126 | 127 | auto k1 = (Q.x*Q.x + Q.y*Q.y) - (P.x*P.x + P.y*P.y); 128 | auto k2 = (R.x*R.x + R.y*R.y) - (P.x*P.x + P.y*P.y); 129 | 130 | auto cx = (k1*d - k2*b)/det; 131 | auto cy = (a*k2 - c*k1)/det; 132 | 133 | Point C(cx, cy); 134 | auto r = C.distance(P); 135 | 136 | cs.push_back(Circle(C, r)); 137 | 138 | return cs; 139 | } 140 | }; 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /algorithms/geometry/line.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que representa retas no espaço bidimensional 3 | * 4 | * Autor: Edson Alves 5 | * Data: 19/07/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef GEOMETRY_LINE_H 9 | #define GEOMETRY_LINE_H 10 | 11 | #include "point.h" 12 | 13 | #include 14 | 15 | using std::pair; 16 | 17 | class Line { 18 | void normalize() 19 | { 20 | auto k = a ? a : b; 21 | 22 | a /= k; 23 | b /= k; 24 | c /= k; 25 | } 26 | 27 | public: 28 | double a; 29 | double b; 30 | double c; 31 | 32 | typedef enum { ZERO, ONE, INF } Intersections; 33 | 34 | Line(double av, double bv, double cv) : a(av), b(bv), c(cv) { normalize(); } 35 | 36 | Line(const Point& P, const Point& Q) 37 | { 38 | a = P.y - Q.y; 39 | b = Q.x - P.x; 40 | c = P.x * Q.y - P.y * Q.x; 41 | 42 | normalize(); 43 | } 44 | 45 | bool operator==(const Line& r) const 46 | { 47 | return equals(a, r.a) and equals(b, r.b) and equals(c, r.c); 48 | } 49 | 50 | bool operator!=(const Line& r) const 51 | { 52 | return not (*this == r); 53 | } 54 | 55 | bool parallel(const Line& r) const 56 | { 57 | return equals(a * r.b - b * r.a, 0) and not equals(c, r.c); 58 | } 59 | 60 | bool concurrent(const Line& r) const 61 | { 62 | return not equals(a * r.b - b * r.a, 0); 63 | } 64 | 65 | pair intersections(const Line& r) 66 | { 67 | auto det = a * r.b - b * r.a; 68 | 69 | if (equals(det, 0)) 70 | { 71 | // Coincidentes 72 | if (*this == r) 73 | return pair(INF, Point()); 74 | else 75 | return pair(ZERO, Point()); // Paralelas 76 | } else // Concorrentes 77 | { 78 | double x = (-c * r.b + r.c * b) / det; 79 | double y = (-r.c * a + c * r.a) / det; 80 | 81 | return pair(ONE, Point(x, y)); 82 | } 83 | } 84 | }; 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /algorithms/geometry/point.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que representa pontos no espaço bidimensional 3 | * 4 | * Autor: Edson Alves 5 | * Data: 18/07/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef GEOMEdoubleRY_POINdouble_H 9 | #define GEOMEdoubleRY_POINdouble_H 10 | 11 | #include 12 | 13 | bool equals(double a, double b) 14 | { 15 | static const auto EPS = 1e-9; 16 | return fabs(a - b) < EPS; 17 | } 18 | 19 | class Point { 20 | public: 21 | double x, y; 22 | 23 | Point(double xv = 0, double yv = 0) : x(xv), y(yv) {} 24 | 25 | bool operator==(const Point& P) const 26 | { 27 | return equals(x, P.x) and equals(y, P.y); 28 | } 29 | 30 | bool operator!=(const Point& P) const 31 | { 32 | return not (*this == P); 33 | } 34 | 35 | bool operator<(const Point& P) const 36 | { 37 | return equals(x, P.x) ? y < P.y : x < P.x; 38 | } 39 | 40 | double distance(const Point& P) const 41 | { 42 | return hypot(x - P.x, y - P.y); 43 | } 44 | 45 | Point rotate(double angle) 46 | { 47 | auto px = cos(angle) * x - sin(angle) * y; 48 | auto py = sin(angle) * x + cos(angle) * y; 49 | 50 | return Point { double(px), double(py) }; 51 | } 52 | 53 | Point translate(double dx, double dy) const 54 | { 55 | return Point(x + dx, y + dy); 56 | } 57 | 58 | Point scale(double kx, double ky) const 59 | { 60 | return Point(kx*x, ky*y); 61 | } 62 | 63 | Point scale(double k) const 64 | { 65 | return scale(k, k); 66 | } 67 | }; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /algorithms/geometry/triangle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Classe que representa um triângulo no espaço bidimensional 3 | * 4 | * Autor: Edson Alves 5 | * Data: 30/07/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef GEOMETRY_TRIANGLE_H 9 | #define GEOMETRY_TRIANGLE_H 10 | 11 | #include "point.h" 12 | 13 | class Triangle { 14 | public: 15 | Point A, B, C; 16 | double a, b, c; 17 | 18 | Triangle(const Point& P, const Point& Q, const Point& R) : A(P), B(Q), C(R) 19 | { 20 | a = P.distance(Q); 21 | b = Q.distance(R); 22 | c = R.distance(P); 23 | } 24 | 25 | Triangle(double av, double bv, double cv) : 26 | A(), B(), C(), a(av), b(bv), c(cv) {} 27 | 28 | typedef enum { EQUILATERAL, ISOSCELES, SCALENE } Sides; 29 | 30 | Sides classification_by_sides() const 31 | { 32 | if (a == b and b == c) 33 | return EQUILATERAL; 34 | 35 | if (a == b or a == c or b == c) 36 | return ISOSCELES; 37 | 38 | return SCALENE; 39 | } 40 | 41 | typedef enum { RIGHT, ACUTE, OBTUSE } Angles; 42 | 43 | Angles classification_by_angles() const 44 | { 45 | auto AB = acos((c*c - a*a - b*b)/(2*a*b)); 46 | auto AC = acos((b*b - a*a - c*c)/(2*a*c)); 47 | auto BC = acos((a*a - b*b - c*c)/(2*b*c)); 48 | 49 | auto right = PI / 2.0; 50 | 51 | if (equals(AB, right) or equals(AC, right) or equals(BC, right)) 52 | return RIGHT; 53 | 54 | if (AB > right or AC > right or BC > right) 55 | return OBTUSE; 56 | 57 | return ACUTE; 58 | } 59 | 60 | double perimeter() const 61 | { 62 | return a + b + c; 63 | } 64 | 65 | double area() const 66 | { 67 | auto s = perimetro() / 2.0; 68 | 69 | return sqrt(s*(s - a)*(s - b)*(s - c)); 70 | } 71 | 72 | double area2() const 73 | { 74 | double det = (A.x*B.y + A.y*C.x + B.x*C.y) - (C.x*B.y + C.y*A.x + B.x*A.y); 75 | 76 | return 0.5 * fabs(det); 77 | } 78 | 79 | Point barycenter() const 80 | { 81 | auto x = (A.x + B.x + C.x) / 3.0; 82 | auto y = (A.y + B.y + C.y) / 3.0; 83 | 84 | return Point(x, y); 85 | } 86 | 87 | double inradius() const 88 | { 89 | return (2 * area()) / perimeter(); 90 | } 91 | 92 | // Centro do círculo inscrito 93 | Point incenter() const 94 | { 95 | auto p = perimeter(); 96 | auto x = (a*A.x + b*B.x + c.C.x)/p; 97 | auto y = (a*A.y + b*B.y + c.C.y)/p; 98 | 99 | return Point(x, y); 100 | } 101 | 102 | double circumradius() const 103 | { 104 | return (a * b * c)/(4 * area()); 105 | } 106 | 107 | Point circumcenter() const 108 | { 109 | auto d = 2*(A.x*(B.y - C.y) + B.x*(C.y - A.y) + C.x*(A.y - B.y)); 110 | 111 | auto A2 = A.x*A.x + A.y*A.y; 112 | auto B2 = B.x*B.x + B.y*B.y; 113 | auto C2 = C.x*C.x + C.y*C.y; 114 | 115 | auto x = (A2*(B.y - C.y) + B2*(C.y - A.y) + C2*(A.y - B.y))/d; 116 | auto y = (A2*(C.x - B.x) + B2*(A.x - C.x) + C2*(B.x - A.x))/d; 117 | 118 | return Point(x, y); 119 | } 120 | }; 121 | 122 | 123 | #endif 124 | 125 | -------------------------------------------------------------------------------- /algorithms/graph/247.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | #define MAX 100 8 | 9 | #include 10 | #include 11 | 12 | #define UNVISITED 0 13 | #define VISITED 1 14 | 15 | using si = stack; 16 | using vi = vector; 17 | 18 | int adj[MAX][MAX]; 19 | int edges[MAX]; 20 | 21 | void SCC(int u, int& sccs, int& dfs_counter, si& S, vi& dfs_num, vi& dfs_low, vi& visited, map& names) 22 | { 23 | dfs_low[u] = dfs_num[u] = ++dfs_counter; 24 | S.push(u); 25 | visited[u] = 1; 26 | //printf("u = %d, low = %d, num = %d, edges = %d\n", u, dfs_low[u], dfs_num[u], edges[u]); 27 | for (int i = 0; i < edges[u]; ++i) 28 | { 29 | int v = adj[u][i]; 30 | 31 | if (dfs_num[v] == UNVISITED) 32 | SCC(v, sccs, dfs_counter, S, dfs_num, dfs_low, visited, names); 33 | 34 | if (visited[v]) 35 | dfs_low[u] = min(dfs_low[u], dfs_low[v]); 36 | } 37 | 38 | //printf("fechando u = %u, low = %d, num = %d\n", u, dfs_low[u], dfs_num[u]); 39 | vi us; 40 | 41 | if (dfs_low[u] == dfs_num[u]) 42 | { 43 | ++sccs; 44 | int v; 45 | 46 | do { 47 | v = S.top(); 48 | S.pop(); 49 | visited[v] = 0; 50 | 51 | us.push_back(v); 52 | } while (v != u); 53 | } 54 | 55 | //printf("us.size() = %lu\n", us.size()); 56 | 57 | if (us.size() == 0) 58 | return; 59 | 60 | printf("%s", names[us[0]].c_str()); 61 | 62 | for (size_t i = 1; i < us.size(); ++i) 63 | printf(", %s", names[us[i]].c_str()); 64 | 65 | printf("\n"); 66 | } 67 | 68 | int tarjan(int V, map& names) 69 | { 70 | vi dfs_num(V + 1, UNVISITED); 71 | vi dfs_low(V + 1, 0); 72 | vi visited(V + 1, 0); 73 | int sccs = 0, dfs_counter = 0; 74 | si S; 75 | 76 | for (int i = 1; i <= V; ++i) 77 | { 78 | //printf("Processing [%s]\n", names[i].c_str()); 79 | if (dfs_num[i] == UNVISITED) 80 | SCC(i, sccs, dfs_counter, S, dfs_num, dfs_low, visited, names); 81 | } 82 | 83 | return sccs; 84 | } 85 | 86 | int main() 87 | { 88 | int n, m, test = 0; 89 | 90 | while (scanf("%d %d", &n, &m), n | m) 91 | { 92 | memset(edges, 0, sizeof edges); 93 | 94 | map ids; 95 | map names; 96 | 97 | int id = 0; 98 | 99 | while (m--) 100 | { 101 | char a[MAX], b[MAX]; 102 | scanf("%s %s", a, b); 103 | 104 | if (ids.find(a) == ids.end()) 105 | { 106 | ids[a] = ++id; 107 | names[id] = a; 108 | } 109 | 110 | if (ids.find(b) == ids.end()) 111 | { 112 | ids[b] = ++id; 113 | names[id] = b; 114 | } 115 | 116 | int u = ids[a]; 117 | int v = ids[b]; 118 | 119 | adj[u][edges[u]++] = v; 120 | } 121 | 122 | if (test) 123 | printf("\n"); 124 | 125 | printf("Calling circles for data set %d:\n", ++test); 126 | tarjan(n, names); 127 | } 128 | 129 | return 0; 130 | } 131 | 132 | -------------------------------------------------------------------------------- /algorithms/graph/315.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | #define MAX 110 8 | #define MAXL 4096 9 | #define INF -1 10 | 11 | #define UNVISITED 0 12 | 13 | int adj[MAX][MAX]; 14 | int edges[MAX], dfs_num[MAX], dfs_low[MAX], parents[MAX], articulations[MAX]; 15 | int num_counter, root_children; 16 | char line[MAXL]; 17 | 18 | void dfs(int u) 19 | { 20 | dfs_low[u] = dfs_num[u] = ++num_counter; 21 | 22 | for (int i = 0; i < edges[u]; ++i) 23 | { 24 | int v = adj[u][i]; 25 | 26 | if (dfs_num[v] == UNVISITED) 27 | { 28 | parents[v] = u; 29 | 30 | if (u == 1) ++root_children; 31 | 32 | dfs(v); 33 | 34 | if (dfs_low[v] >= dfs_num[u]) 35 | articulations[u] = 1; 36 | 37 | dfs_low[u] = min(dfs_low[u], dfs_low[v]); 38 | } else if (v != parents[u]) 39 | dfs_low[u] = min(dfs_low[u], dfs_num[v]); 40 | } 41 | } 42 | 43 | int main() 44 | { 45 | while (fgets(line, MAXL, stdin)) 46 | { 47 | int N = atoi(line); 48 | 49 | if (N == 0) 50 | break; 51 | 52 | memset(edges, 0, sizeof edges); 53 | 54 | while (true) 55 | { 56 | fgets(line, MAXL, stdin); 57 | istringstream is(line); 58 | 59 | int u; 60 | is >> u; 61 | 62 | if (u == 0) 63 | break; 64 | 65 | int v; 66 | 67 | while (is >> v) 68 | { 69 | adj[u][edges[u]++] = v; 70 | adj[v][edges[v]++] = u; 71 | } 72 | } 73 | 74 | memset(dfs_num, UNVISITED, sizeof dfs_num); 75 | memset(dfs_low, UNVISITED, sizeof dfs_low); 76 | memset(parents, 0, sizeof parents); 77 | memset(articulations, 0, sizeof articulations); 78 | num_counter = root_children = 0; 79 | 80 | dfs(1); 81 | 82 | articulations[1] = (root_children > 1 ? 1 : 0); 83 | 84 | int points = 0; 85 | 86 | for (int i = 1; i <= N; ++i) 87 | points += articulations[i]; 88 | 89 | printf("%d\n", points); 90 | } 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /algorithms/graph/bfs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementação do BFS em lista de adjacências. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 25/02/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef BFS_H 9 | #define BFS_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | const int MAX { 100010 }; 19 | bitset visited; 20 | vector adj[MAX]; 21 | int dist[MAX]; 22 | 23 | void bfs(int s, function process) 24 | { 25 | queue q; 26 | 27 | dist[s] = 0; 28 | visited[s] = true; 29 | q.push(s); 30 | 31 | while (not q.empty()) 32 | { 33 | auto u = q.front(); 34 | q.pop(); 35 | 36 | process(u); 37 | 38 | for (const auto& v : adj[u]) 39 | { 40 | if (not visited[v]) 41 | { 42 | dist[v] = dist[u] + 1; 43 | visited[v] = true; 44 | q.push(v); 45 | } 46 | } 47 | } 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /algorithms/graph/bipartite.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementação do algoritmo que verifica se um grafo é bipartido ou não. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 27/09/2018 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef BIPARTITE_H 9 | #define BIPARTITE_H 10 | 11 | #include 12 | 13 | using namespace std; 14 | using ii = pair; 15 | 16 | const int MAX { 100010 }, NONE = 0, BLUE = 1, RED = 2; 17 | int color[MAX]; 18 | vector adj[MAX]; 19 | bitset visited; 20 | 21 | bool bfs(int s) 22 | { 23 | queue q; 24 | q.push(s); 25 | color[s] = BLUE; 26 | 27 | while (not q.empty()) 28 | { 29 | auto u = q.front(); 30 | q.pop(); 31 | 32 | for (const auto& v : adj[u]) 33 | if (color[v] == NONE) 34 | { 35 | color[v] = 3 - color[u]; 36 | q.push(v); 37 | } else if (color[v] == color[u]) 38 | return false; 39 | } 40 | 41 | return true; 42 | } 43 | 44 | bool is_bipartite(int N) 45 | { 46 | for (int u = 1; u <= N; ++u) 47 | color[u] = NONE; 48 | 49 | for (int u = 1; u <= N; ++u) 50 | if (color[u] == NONE and not bfs(u)) 51 | return false; 52 | 53 | return true; 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /algorithms/graph/connected_components.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementação do algoritmo de identificação de componentes conectados 3 | * através do DFS. 4 | * 5 | * Autor: Edson Alves 6 | * Data: 25/02/2016 7 | * Licença: LGPL. Sem copyright. 8 | */ 9 | #ifndef CONNECTED_COMPONENTS_H 10 | #define CONNECTED_COMPONENTS_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using namespace std; 18 | using ii = pair; 19 | 20 | const int MAX { 100010 }; 21 | bitset visited; 22 | vector adj[MAX]; 23 | 24 | void dfs(int u, function process) 25 | { 26 | if (visited[u]) return; 27 | visited[u] = true; 28 | 29 | process(u); 30 | 31 | for (const auto& v : adj[u]) 32 | dfs(v, process); 33 | } 34 | 35 | vector> connected_components(int N) 36 | { 37 | visited.reset(); 38 | vector> ans; 39 | 40 | for (int u = 1; u <= N; ++u) 41 | { 42 | if (not visited[u]) 43 | { 44 | vector cs; 45 | dfs(u, [&](int u) { cs.push_back(u); }); 46 | ans.push_back(vector(cs)); 47 | } 48 | } 49 | 50 | return ans; 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /algorithms/graph/dfs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementação do DFS em lista de adjacências. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 12/02/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef DFS_H 9 | #define DFS_H 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | const int MAX { 100010 }; 18 | bitset visited; 19 | vector adj[MAX]; 20 | 21 | // a variável visited deve ser inicializada com falso (visited.reset()) antes da chamada 22 | // desta função 23 | void dfs(int u, function process) 24 | { 25 | if (visited[u]) 26 | return; 27 | 28 | visited[u] = true; 29 | process(u); 30 | 31 | for (const auto& v : adj[u]) 32 | dfs(v, process); 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /algorithms/graph/dfs_topsort.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementação do algoritmo de geração de ordenação topológica via DFS. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 05/03/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef DFS_TOPSORT_H 9 | #define DFS_TOPSORT_H 10 | 11 | #include "graph.h" 12 | 13 | #include 14 | 15 | using std::stack; 16 | 17 | #define UNVISITED 0 18 | #define VISITED 1 19 | 20 | int dfs(const Graph& g, vi& states, stack& order, int u) 21 | { 22 | status[u] = VISITED; 23 | 24 | for (auto v : g.adj()[u]) 25 | { 26 | if (states[v.first] == UNVISITED) 27 | dfs(v.first, states, g); 28 | } 29 | 30 | order.push(u); 31 | } 32 | 33 | stack topsort(const Graph& g) 34 | { 35 | vi states; 36 | states.assign(g.V() + 1, UNVISITED); 37 | 38 | stack order; 39 | 40 | for (int u = 1; u <= g.V(); ++u) 41 | if (states[u] == UNVISITED) 42 | dfs(g, states, order, u); 43 | 44 | return order; 45 | } 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /algorithms/graph/edmonds_karp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Algoritmo de Edmonds Karp para fluxo de rede. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 09/07/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef EDMONDS_KARP_H 9 | #define EDMONDS_KARP_H 10 | 11 | #define INF 1000000000 12 | 13 | #include 14 | #include 15 | 16 | using std::vector; 17 | using std::queue; 18 | 19 | using vi = vector; 20 | 21 | #define MAXV 1010 22 | 23 | int augment(int s, int v, int adj[MAXV][MAVX], const vi& p, int min_edge) 24 | { 25 | if (v == s) 26 | return min_edge; 27 | 28 | int flow = augment(s, p[v], adj, p, min(min_edge, adj[p[v]][v])); 29 | 30 | adj[p[v]][v] -= flow; 31 | adj[v][p[v]] += flow; 32 | 33 | return flow; 34 | } 35 | 36 | int edmonds_karp(int s, int t, int adj[MAXV][MAXV]) 37 | { 38 | int max_flow = 0; 39 | 40 | while (true) 41 | { 42 | // Finding a path from s to t (BFS) 43 | vi dist(MAXV, INF); 44 | dist[x] = 0; 45 | 46 | queue q; 47 | q.push(s); 48 | 49 | vi parents(MAXV, -1); 50 | 51 | while (not q.empty()) 52 | { 53 | int u = q.front(); 54 | q.pop(); 55 | 56 | if (u == t) 57 | break; 58 | 59 | for (int v = 0; v < MAXV; ++v) 60 | { 61 | if (adj[u][v] > 0 and dist[v] == INF) 62 | { 63 | dist[v] = dist[u] + 1; 64 | q.push(v); 65 | p[v] = u; 66 | } 67 | } 68 | } 69 | 70 | int flow = augment(t, adj, p, INF); 71 | 72 | if (flow == 0) 73 | break; 74 | 75 | max_flow += flow; 76 | } 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /algorithms/graph/graph.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementação de um grafo por lista de adjacências 3 | * 4 | * Autor: Edson Alves 5 | * Data: 12/02/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef GRAPH_H 9 | #define GRAPH_H 10 | 11 | #include 12 | #include 13 | 14 | using std::vector; 15 | using std::pair; 16 | 17 | typedef pair ii; // (v, w) - vértice/peso 18 | typedef vector vii; 19 | typedef vector vvii; 20 | 21 | class Graph 22 | { 23 | int m_V; // número de vértices 24 | vvii m_adj; // lista de adjacências 25 | 26 | public: 27 | Graph(int V) : m_V(V) 28 | { 29 | m_adj.assign(V + 1, vii()); 30 | } 31 | 32 | void add_edge(int u, int v, int w = 1, bool bidirecional = false) 33 | { 34 | m_adj[u].push_back(ii(v, w)); 35 | 36 | if (bidirecional) 37 | m_adj[v].push_back(ii(u, w)); 38 | } 39 | 40 | int V() const { return m_V; } 41 | 42 | int E(bool bidirecional = false) 43 | { 44 | int sum = 0; 45 | 46 | for (auto v : m_adj) 47 | sum += v.size(); 48 | 49 | if (bidirecional) sum /= 2; 50 | 51 | return sum; 52 | } 53 | 54 | const vvii& adj() const { return m_adj; } 55 | }; 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /algorithms/graph/graph_check.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementação do algoritmo de verificação das propriedades das arestas de um 3 | * grafo através do DFS. 4 | * 5 | * Autor: Edson Alves 6 | * Data: 08/03/2016 7 | * Licença: LGPL. Sem copyright. 8 | */ 9 | #ifndef GRAPH_CHECK_H 10 | #define GRAPH_CHECK_H 11 | 12 | #include "graph.h" 13 | 14 | typedef vector vi; 15 | 16 | #define UNVISITED 0 17 | #define VISITED 1 18 | #define EXPLORED 2 19 | 20 | void check(const Graph& g, vi& states, vi& parents, int u) 21 | { 22 | states[u] = EXPLORED; 23 | 24 | for (auto v : g.adj()[u]) 25 | { 26 | switch (states[v.first]) { 27 | case UNVISITED: // Tree edge 28 | parents[v.first] = u; 29 | check(g, states, parents, v.first); 30 | break; 31 | 32 | case VISITED: // Forward edge 33 | printf("Forward: (%d, %d)\n", u, v.first); 34 | break; 35 | 36 | case EXPLORED: // Back edge 37 | if (v.first == parents[u]) 38 | printf("Bidirecional edge (%d, %d)\n", u, v.first); 39 | else 40 | printf("Back edge/cycle (%d, %d)\n", u, v.first); 41 | break; 42 | } 43 | } 44 | 45 | states[u] = VISITED; 46 | } 47 | 48 | void check(const Graph& g, int u) 49 | { 50 | vi states; 51 | states.assign(g.V() + 1, UNVISITED); 52 | 53 | vi parents; 54 | parents.reserve(g.V() + 1); 55 | 56 | for (int i = 0; i <= g.V(); ++i) 57 | parents[i] = i; 58 | 59 | check(g, states, parents, u); 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /algorithms/graph/has_cycle.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Rotinas de detecção de ciclos em grafos. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 25/02/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef HAS_CYCLE_H 9 | #define HAS_CYCLE_H 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | using ii = pair; 18 | 19 | const int MAX { 100010 }; 20 | bitset visited; 21 | vector adj[MAX]; 22 | 23 | void dfs(int u, function process) 24 | { 25 | if (visited[u]) return; 26 | visited[u] = true; 27 | 28 | process(u); 29 | 30 | for (const auto& v : adj[u]) 31 | dfs(v, process); 32 | } 33 | 34 | bool has_cycle(int N) 35 | { 36 | visited.reset(); 37 | 38 | for (int u = 1; u <= N; ++u) 39 | { 40 | if (not visited[u]) 41 | { 42 | vector cs; 43 | size_t edges = 0; 44 | 45 | dfs(u, [&](int u) { 46 | cs.push_back(u); 47 | 48 | for (const auto& v : adj[u]) 49 | edges += (visited[v] ? 0 : 1); 50 | }); 51 | 52 | // if edges == (cs.size() - 1) there is no cycle 53 | if (edges >= cs.size()) 54 | return true; 55 | } 56 | } 57 | 58 | return false; 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /algorithms/graph/kruskall.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Algoritmo de Kruskall para árvore mínima geradora. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 27/12/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef KRUSKALL_H 9 | #define KRUSKALL_H 10 | 11 | #define UDFS_MAX_N 1000005 12 | 13 | #include 14 | 15 | using std::vector; 16 | 17 | int parent[UDFS_MAX_N]; 18 | int rank[UDFS_MAX_N]; 19 | 20 | typedef pair ii; 21 | vector< pair > edges; 22 | 23 | class UnionFind 24 | { 25 | public: 26 | UnionFind(int N) 27 | : m_N(N), m_count(N) 28 | { 29 | for (int i = 1; i <= N; ++i) 30 | { 31 | parent[i] = i; 32 | rank[i] = 0; 33 | } 34 | } 35 | 36 | bool is_same_set(int i, int j) 37 | { 38 | return find_set(i) == find_set(j); 39 | } 40 | 41 | void union_set(int i, int j) 42 | { 43 | if (is_same_set(i, j)) 44 | return; 45 | 46 | int p = find_set(i); 47 | int q = find_set(j); 48 | 49 | if (rank[p] > rank[q]) 50 | parent[q] = p; 51 | else if (rank[q] > rank[p]) 52 | parent[p] = q; 53 | else 54 | { 55 | parent[q] = p; 56 | ++rank[p]; 57 | } 58 | 59 | --m_count; 60 | } 61 | 62 | int count() const { return m_count; } 63 | 64 | int find_set(int i) 65 | { 66 | int p = i; 67 | 68 | vector ps; 69 | 70 | while (p != parent[p]) 71 | { 72 | ps.push_back(p); 73 | p = parent[p]; 74 | } 75 | 76 | for (auto x : ps) 77 | { 78 | parent[x] = p; 79 | } 80 | 81 | return p; 82 | } 83 | 84 | private: 85 | int m_N; 86 | int m_count; 87 | }; 88 | 89 | int kruskall(int V) 90 | { 91 | sort(edges.begin(), edges.end()); 92 | 93 | int cost = 0; 94 | UnionFind ufds(V); 95 | 96 | for (auto edge : edges) 97 | { 98 | int w = edge.first; 99 | int u = edge.second.first; 100 | int v = edge.second.second; 101 | 102 | if (not ufds.same_set(u, v)) 103 | { 104 | cost += w; 105 | ufds.union_set(u, v); 106 | } 107 | } 108 | 109 | return cost; 110 | } 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /algorithms/graph/prim.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Algoritmo de Prim para árvore mínima geradora. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 26/04/2016 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef PRIM_H 9 | #define PRIM_H 10 | 11 | #define UDFS_MAX_N 1000005 12 | 13 | #include 14 | #include 15 | 16 | using std::priority_queue; 17 | using ii = pair; 18 | using std::greater; 19 | 20 | int prim(const Graph& g) 21 | { 22 | vi taken(g.V() + 1, 0); 23 | priority_queue, greater > pq; 24 | int cost = 0; 25 | 26 | taken[1] = 1; 27 | 28 | for (auto v : g.adj()[u]) 29 | if (not taken[v]) 30 | pq.push(ii(v.second, v.first)); 31 | 32 | while (not pq.empty()) 33 | { 34 | ii edge = pq.top(); 35 | pq.pop(); 36 | 37 | int w = edge.first; 38 | int u = edge.second; 39 | 40 | if (not taken[u]) 41 | { 42 | taken[u] = 1; 43 | cost += w; 44 | 45 | for (auto v : g.adj()[u]) 46 | if (not taken[v]) 47 | pq.push(ii(v.second, v.first)); 48 | } 49 | } 50 | 51 | return cost; 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /algorithms/graph/tarjan_scc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementação do algoritmo de Tarjan para detecção de componentes fortemente 3 | * conectados (SCC). 4 | * 5 | * Autor: Edson Alves 6 | * Data: 07/04/2016 7 | * Licença: LGPL. Sem copyright. 8 | */ 9 | #ifndef TARJAN_SCC_H 10 | #define TARJAN_SCC_H 11 | 12 | #include "dfs.h" 13 | 14 | #include 15 | using std::stack 16 | using si = stack; 17 | 18 | vi SCC(int u, int& sccs, int& dfs_counter, si& S, vi& dfs_num, vi& dfs_low, vi& visited) 19 | { 20 | dfs_low[u] = dfs_num[u] = dfs_counter++; 21 | S.push_back(u): 22 | visited[u] = 1; 23 | 24 | for (auto v : g.adj()[u]) 25 | { 26 | if (dfs_num[v.first] == UNVISITED) 27 | SCC(v, sccs, dfs_counter, dfs_num, dfs_low, visited); 28 | 29 | if (visited[v.first]) 30 | dfs_low[u] = min(dfs_low[u], dfs_low[v.first]); 31 | } 32 | 33 | vi us; 34 | 35 | if (dfs_low[u] == dfs_num[u]) 36 | { 37 | ++sccs; 38 | 39 | do { 40 | int v = S.top(); 41 | S.pop(); 42 | visited[v] = 0; 43 | 44 | us.push_back(v); 45 | } while (v != u); 46 | } 47 | 48 | return us; 49 | } 50 | 51 | int tarjan(const Graph& g) 52 | { 53 | vi dfs_num(g.V() + 1, UNVISITED); 54 | vi dfs_low(g.V() + 1, 0); 55 | vi visited(g.V() + 1, 0); 56 | int sccs = 0, dfs_counter = 0; 57 | si S; 58 | 59 | for (size_t i = 1; i <= g.V(); ++i) 60 | if (dfs_num[i] == UNVISITED) 61 | SCC(i, sccs, dfs_counter, dfs_num, dfs_low, visited); 62 | 63 | return sccs; 64 | } 65 | 66 | int connected_components(const Graph& g) 67 | { 68 | int cc = 0; 69 | vi states(g.V() + 1, UNVISITED); 70 | 71 | for (int i = 1; i <= g.V(); ++i) 72 | { 73 | if (states[i] == UNVISITED) 74 | { 75 | printf("CC %d:", ++c); 76 | dfs_rec(i, states, g); 77 | printf("\n"); 78 | } 79 | } 80 | } 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /algorithms/io/BufferedIO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Rotinas de IO em console utilizando buffers. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 17/02/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | package algorithms.io; 9 | 10 | import java.io.IOException; 11 | import java.io.BufferedReader; 12 | import java.io.BufferedWriter; 13 | import java.io.InputStreamReader; 14 | import java.io.OutputStreamWriter; 15 | 16 | import java.util.ArrayList; 17 | 18 | public class BufferedIO { 19 | 20 | private InputStreamReader isr = new InputStreamReader(System.in); 21 | private BufferedReader br = new BufferedReader(isr); 22 | 23 | private OutputStreamWriter osw = new OutputStreamWriter(System.out); 24 | private BufferedWriter bw = new BufferedWriter(osw); 25 | 26 | public final int[] read() { 27 | ArrayList list = new ArrayList(); 28 | String line; 29 | 30 | try { 31 | while ((line = br.readLine()) != null) { 32 | line = line.trim(); 33 | 34 | if (line.length() < 1) { 35 | continue; 36 | } 37 | 38 | String[] tokens = line.split(" "); 39 | 40 | for (String token : tokens) { 41 | if (token.length() < 1) { 42 | continue; 43 | } 44 | 45 | int n = Integer.parseInt(token); 46 | list.add(n); 47 | } 48 | } 49 | } catch (IOException ex) { 50 | return null; 51 | } 52 | 53 | int[] ns = new int[list.size()]; 54 | 55 | for (int i = 0; i < ns.length; i++) { 56 | ns[i] = list.get(i).intValue(); 57 | } 58 | 59 | return ns; 60 | } 61 | 62 | public final void write(final int[] ns) { 63 | try { 64 | for (int i : ns) { 65 | bw.write(Integer.toString(i)); 66 | bw.newLine(); 67 | } 68 | 69 | bw.flush(); 70 | } catch (IOException ex) { 71 | return; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /algorithms/io/IO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Classe para operações de I/O em console utilizando a classe Scanner para 3 | * a entrada. 4 | * 5 | * Autor: Edson Alves 6 | * Data: 18/02/2015 7 | * Licença: LGPL. Sem copyright. 8 | */ 9 | package algorithms.io; 10 | 11 | import java.util.Scanner; 12 | import java.util.ArrayList; 13 | 14 | public class IO { 15 | 16 | private Scanner sc = new Scanner(System.in); 17 | 18 | public final int[] read() { 19 | ArrayList list = new ArrayList(); 20 | 21 | while (sc.hasNext()) { 22 | int n = sc.nextInt(); 23 | list.add(n); 24 | } 25 | 26 | int[] ns = new int[list.size()]; 27 | 28 | for (int i = 0; i < ns.length; i++) { 29 | ns[i] = list.get(i).intValue(); 30 | } 31 | 32 | return ns; 33 | } 34 | 35 | public final void write(final int[] ns) { 36 | for (int i : ns) { 37 | System.out.println("" + i); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /algorithms/io/async_io.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Métodos de entrada/saída em console. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 09/02/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef IO_H 9 | #define IO_H 10 | 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | template 17 | class IO 18 | { 19 | public: 20 | IO() 21 | { 22 | ios::sync_with_stdio(false); 23 | } 24 | 25 | vector read() const 26 | { 27 | vector ns; 28 | T n; 29 | 30 | while (cin >> n) 31 | ns.push_back(n); 32 | 33 | return ns; 34 | } 35 | 36 | void write(const vector& ns) const 37 | { 38 | for (const T& n : ns) 39 | cout << n << endl; 40 | } 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /algorithms/io/buffered_io.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Métodos de entrada/saída em console utilizando I/O da linguagem C. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 10/02/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef IO_H 9 | #define IO_H 10 | 11 | #include 12 | #include 13 | 14 | const int BUFFER_SIZE { 4096 }; 15 | 16 | using namespace std; 17 | 18 | vector read() 19 | { 20 | vector ns; 21 | char buffer[BUFFER_SIZE]; 22 | int n = 0, digits = 0, bytes = 0, signal = 1; 23 | 24 | while ((bytes = fread(buffer, sizeof(char), BUFFER_SIZE, stdin))) 25 | { 26 | for (int i = 0; i < bytes; i++) 27 | { 28 | char c = buffer[i]; 29 | 30 | if (isdigit(c)) 31 | { 32 | n *= 10; 33 | n += (c - '0'); 34 | digits++; 35 | } else if (c == '-') 36 | { 37 | signal = -1; 38 | } else if (digits) 39 | { 40 | ns.push_back(n*signal); 41 | n = 0; 42 | signal = 1; 43 | digits = 0; 44 | } 45 | } 46 | } 47 | 48 | if (digits) 49 | ns.push_back(n*signal); 50 | 51 | return ns; 52 | } 53 | 54 | void write(const vector& ns) 55 | { 56 | char buffer[BUFFER_SIZE]; 57 | int bytes = 0; 58 | 59 | for (int n : ns) 60 | { 61 | if (BUFFER_SIZE - bytes < 15) 62 | { 63 | fwrite(buffer, bytes, sizeof(char), stdout); 64 | bytes = 0; 65 | } 66 | 67 | bytes += sprintf(buffer + bytes, "%d\n", n); 68 | } 69 | 70 | if (bytes) 71 | fwrite(buffer, bytes, sizeof(char), stdout); 72 | } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /algorithms/io/cio.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Métodos de entrada/saída em console utilizando I/O da linguagem C. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 10/02/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef CIO_H 9 | #define CIO_H 10 | 11 | #include 12 | 13 | #define MAX 1000010 14 | 15 | int cio_buffer[MAX]; 16 | 17 | int read() 18 | { 19 | int x, n = 0; 20 | 21 | while (scanf("%d", &x) != EOF) 22 | cio_buffer[n++] = x; 23 | 24 | return n; 25 | } 26 | 27 | void write(int n) 28 | { 29 | for (int i = 0; i < n; ++i) 30 | printf("%d\n", cio_buffer[i]); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /algorithms/io/io.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Métodos de entrada/saída em console. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 11/02/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef IO_NAIVE_H 9 | #define IO_NAIVE_H 10 | 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | template 17 | class IO 18 | { 19 | public: 20 | static vector read() 21 | { 22 | vector ns; 23 | T n; 24 | 25 | while (cin >> n) 26 | ns.push_back(n); 27 | 28 | return ns; 29 | } 30 | 31 | static void write(const vector& ns) 32 | { 33 | for (const T& n : ns) 34 | cout << n << '\n'; 35 | } 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /tests/adhoc/Makefile: -------------------------------------------------------------------------------- 1 | CPPC = g++ 2 | CPPFLAGS = -std=c++11 -Wall -W -Wextra -Werror -O2 3 | INCLUDES = -I../../ -I../../algorithms 4 | 5 | SRC = ${wildcard *.cpp} 6 | TESTS = ${SRC:.cpp=.exe} 7 | 8 | .PHONY: clean dist-clean dist 9 | 10 | all: 11 | $(MAKE) $(TESTS) 12 | 13 | %.exe: %.cpp 14 | @echo Building $@ 15 | $(CPPC) $(CPPFLAGS) $(INCLUDES) $< -o $@ 16 | 17 | clean: 18 | @echo Cleaning... 19 | @rm -rf *~ *.o prog out.txt *.d *.class 20 | 21 | dist-clean: clean 22 | @rm -rf *.exe 23 | -------------------------------------------------------------------------------- /tests/adhoc/date.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include "adhoc/date.h" 5 | 6 | SCENARIO("Date construction", "[date]") 7 | { 8 | GIVEN("A day, a month and an year") 9 | { 10 | int day = 5, month = 3, year = 945; 11 | 12 | WHEN("A date is constructed") 13 | { 14 | Date date(day, month, year); 15 | 16 | THEN("then the formatted date is in dd/mm/aaaa format") 17 | { 18 | REQUIRE(date.format() == "05/03/0945"); 19 | } 20 | } 21 | } 22 | 23 | GIVEN("A number N of days from the zero") 24 | { 25 | WHEN("N is equals to one") 26 | { 27 | int days = 1; 28 | 29 | THEN("the corresponding date is 01/01/0000") 30 | { 31 | Date date = Date::from_days(days); 32 | 33 | REQUIRE(date.format() == "01/01/0000"); 34 | } 35 | } 36 | } 37 | } 38 | 39 | SCENARIO("Date operations", "[date]") 40 | { 41 | GIVEN("The date 28/02/2000") 42 | { 43 | Date date(28, 2, 2000); 44 | 45 | WHEN("We add two days to it") 46 | { 47 | date.add(2); 48 | 49 | THEN("we get the date 01/03/2000, because 2000 is a leap year") 50 | { 51 | REQUIRE(date.format() == "01/03/2000"); 52 | } 53 | } 54 | } 55 | 56 | GIVEN("The date 28/02/1900") 57 | { 58 | Date date(28, 2, 1900); 59 | 60 | WHEN("We add two days to it") 61 | { 62 | date.add(2); 63 | 64 | THEN("we get the date 02/03/1999, because 1900 is not a leap year") 65 | { 66 | REQUIRE(date.format() == "02/03/1900"); 67 | } 68 | } 69 | } 70 | 71 | GIVEN("Two dates: a = 01/06/1999 and b = 01/06/2000") 72 | { 73 | Date a(1, 6, 1999), b(1, 6, 2000); 74 | 75 | WHEN("We compute the date difference between b and a") 76 | { 77 | auto days = b - a; 78 | 79 | THEN("the difference is equals to 366 days, because 2000 is a leap year") 80 | { 81 | REQUIRE(days == 366); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /tests/adhoc/timest.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include "adhoc/timest.h" 5 | 6 | SCENARIO("Time construction", "[time]") 7 | { 8 | GIVEN("Hours, minutes and seconds") 9 | { 10 | int h = 7, m = 53, s = 21; 11 | 12 | WHEN("A time is constructed") 13 | { 14 | Time time(h, m, s); 15 | 16 | THEN("then the formatted time is in hh:mm:ss format") 17 | { 18 | REQUIRE(time.format() == "07:53:21"); 19 | } 20 | } 21 | } 22 | } 23 | 24 | SCENARIO("Time operations", "[time]") 25 | { 26 | GIVEN("The time 23:59:59") 27 | { 28 | Time time(23, 59, 59); 29 | 30 | WHEN("We add two seconds to it") 31 | { 32 | time.add(Time(0, 0, 2)); 33 | 34 | THEN("we get the time 00:00:01") 35 | { 36 | REQUIRE(time.format() == "00:00:01"); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/brute_force/Makefile: -------------------------------------------------------------------------------- 1 | CPPC = g++ 2 | CPPFLAGS = -std=c++11 -Wall -W -Wextra -Werror -O2 3 | INCLUDES = -I../../ -I../../algorithms 4 | 5 | SRC = ${wildcard *.cpp} 6 | TESTS = ${SRC:.cpp=.exe} 7 | 8 | .PHONY: clean dist-clean dist 9 | 10 | all: 11 | $(MAKE) $(TESTS) 12 | 13 | %.exe: %.cpp 14 | @echo Building $@ 15 | $(CPPC) $(CPPFLAGS) $(INCLUDES) $< -o $@ 16 | 17 | clean: 18 | @echo Cleaning... 19 | @rm -rf *~ *.o prog out.txt *.d *.class 20 | 21 | dist-clean: clean 22 | @rm -rf *.exe 23 | -------------------------------------------------------------------------------- /tests/brute_force/next_combination.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include 5 | #include "brute_force/next_combination.h" 6 | 7 | using namespace std; 8 | 9 | SCENARIO("Next combination generation", "[brute force]") 10 | { 11 | GIVEN("A number N of elements") 12 | { 13 | int N = 10; 14 | 15 | WHEN("We list all possible trio of these elements") 16 | { 17 | vector a, b; 18 | string s(3, '1'); 19 | s.resize(N, '0'); 20 | 21 | do { 22 | a.push_back(s); 23 | } while (prev_permutation(s.begin(), s.end())); 24 | 25 | s = ""; 26 | int x, y; 27 | 28 | while (next_combination(N, 3, s, x, y)) 29 | b.push_back(s); 30 | 31 | sort(a.begin(), a.end()); 32 | sort(b.begin(), b.end()); 33 | 34 | THEN("then we get 120 different trios") 35 | { 36 | REQUIRE(a == b); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/data_structures/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | CFLAGS = -W -Wall -Wextra -pedantic -std=c++11 -Wall 3 | #CFLAGS = -pedantic -std=c++11 -w -MMD -g3 -g -fPIC\ 4 | -W -Wall -Wextra -Wshadow -Wcast-align -Wcast-qual -Wctor-dtor-privacy\ 5 | -Wdisabled-optimization -Wformat=2 -Wlogical-op -Wmissing-declarations\ 6 | -Wmissing-include-dirs -Wnoexcept -Woverloaded-virtual -Wredundant-decls\ 7 | -Wsign-promo -Wstrict-null-sentinel -Wswitch-default -Wundef\ 8 | -Wzero-as-null-pointer-constant -Wuseless-cast -Wnon-virtual-dtor 9 | 10 | INCLUDES = -I../../ -I../../algorithms 11 | LIBS = 12 | 13 | SRC = ${wildcard *.cpp} 14 | TESTS = ${SRC:.cpp=.exe} 15 | 16 | .PHONY: clean depend dist-clean dist 17 | 18 | all: 19 | $(MAKE) $(TESTS) 20 | 21 | %.exe: %.cpp 22 | @echo Building $@ 23 | $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ 24 | 25 | clean: 26 | @echo Cleaning... 27 | @rm -rf *~ *.o prog out.txt *.d 28 | 29 | dist-clean: clean 30 | @rm -rf *.exe 31 | -------------------------------------------------------------------------------- /tests/data_structures/segment_tree.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include 5 | #include 6 | #include "data_structures/segment_tree.h" 7 | 8 | SCENARIO("segment tree initialization", "[segtree]") 9 | { 10 | GIVEN("a positive integer N") 11 | { 12 | int N = 1000; 13 | 14 | REQUIRE(N > 0); 15 | 16 | WHEN("a segment tree is initialized") 17 | { 18 | SegmentTree tree(N); 19 | 20 | THEN("the segment tree has size equals to 4N") 21 | { 22 | REQUIRE(tree.size() == 4*N); 23 | } 24 | } 25 | } 26 | } 27 | 28 | SCENARIO("segment tree point update", "[segtree]") 29 | { 30 | GIVEN("a random vector ns of integers") 31 | { 32 | // Generates N random numbers between [-1000000, 1000000] 33 | srand(time(NULL)); 34 | 35 | int N = (rand() % 1000) + 1; 36 | vector ns(N, 0); 37 | 38 | for (int i = 0; i < N; ++i) 39 | ns[i] = (rand() % 2000001) - 1000000; 40 | 41 | WHEN("a segment tree is filled with ns") 42 | { 43 | SegmentTree tree(N); 44 | 45 | for (int i = 0; i < N; ++i) 46 | tree.add(i, ns[i]); 47 | 48 | THEN("each segment tree leaf i matches ns[i]") 49 | { 50 | for (int i = 0; i < N; ++i) 51 | REQUIRE(tree.sum(i, i) == ns[i]); 52 | } 53 | } 54 | } 55 | } 56 | 57 | SCENARIO("segment tree range sum", "[segtree]") 58 | { 59 | GIVEN("a random vector ns of integers") 60 | { 61 | // Generates N random numbers between [-1000000, 1000000] 62 | srand(time(NULL)); 63 | 64 | int N = (rand() % 1000) + 1; 65 | vector ns(N, 0); 66 | 67 | for (int i = 0; i < N; ++i) 68 | ns[i] = (rand() % 2000001) - 1000000; 69 | 70 | WHEN("a segment tree is filled with ns") 71 | { 72 | SegmentTree tree(N); 73 | 74 | for (int i = 0; i < N; ++i) 75 | tree.add(i, ns[i]); 76 | 77 | THEN("each segment [i, j] sum matches the (ns[i] + ns[i+1] + ... + ns[j])") 78 | { 79 | for (int i = 0; i < N; ++i) 80 | for (int j = i; j < N; ++j) 81 | { 82 | int s = 0; 83 | 84 | for (int k = i; k <= j; ++k) 85 | s += ns[k]; 86 | 87 | REQUIRE(tree.sum(i, j) == s); 88 | } 89 | } 90 | } 91 | } 92 | 93 | GIVEN("a random vector ns of integers") 94 | { 95 | // Generates N random numbers between [-1000000, 1000000] 96 | srand(time(NULL)); 97 | 98 | int N = (rand() % 1000) + 1; 99 | vector ns(N, 0); 100 | 101 | for (int i = 0; i < N; ++i) 102 | ns[i] = (rand() % 2000001) - 1000000; 103 | 104 | WHEN("a segment tree is filled with ns and random values are added to random elements n[i]") 105 | { 106 | SegmentTree tree(N); 107 | 108 | for (int i = 0; i < N; ++i) 109 | tree.add(i, ns[i]); 110 | 111 | int M = (rand() % 1000) + 1; 112 | 113 | while (M--) 114 | { 115 | int i = rand() % N; 116 | int v = (rand() % 2000001) - 1000000; 117 | 118 | ns[i] += v; 119 | tree.add(i, v); 120 | } 121 | 122 | THEN("each segment [i, j] sum matches the (ns[i] + ns[i+1] + ... + ns[j])") 123 | { 124 | for (int i = 0; i < N; ++i) 125 | for (int j = i; j < N; ++j) 126 | { 127 | int s = 0; 128 | 129 | for (int k = i; k <= j; ++k) 130 | s += ns[k]; 131 | 132 | REQUIRE(tree.sum(i, j) == s); 133 | } 134 | } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /tests/data_structures/segment_tree_bottom_up.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include 5 | #include 6 | #include "data_structures/segment_tree_non_recursive.h" 7 | 8 | SCENARIO("segment tree initialization", "[segtree]") 9 | { 10 | GIVEN("a positive integer N") 11 | { 12 | int N = 1000; 13 | 14 | REQUIRE(N > 0); 15 | 16 | WHEN("a segment tree is initialized") 17 | { 18 | SegmentTree tree(N); 19 | 20 | THEN("the segment tree has size equals to a power of 2") 21 | { 22 | int size = tree.size(); 23 | 24 | REQUIRE(size > 0); 25 | REQUIRE(least_significant_bit(size) == size); 26 | } 27 | } 28 | } 29 | } 30 | 31 | SCENARIO("segment tree point update", "[segtree]") 32 | { 33 | GIVEN("a random vector ns of integers") 34 | { 35 | // Generates N random numbers between [-1000000, 1000000] 36 | srand(time(NULL)); 37 | 38 | int N = (rand() % 1000) + 1; 39 | vector ns(N, 0); 40 | 41 | for (int i = 0; i < N; ++i) 42 | ns[i] = (rand() % 2000001) - 1000000; 43 | 44 | WHEN("a segment tree is filled with ns") 45 | { 46 | SegmentTree tree(N); 47 | 48 | for (int i = 0; i < N; ++i) 49 | tree.add(i, ns[i]); 50 | 51 | THEN("each segment tree leaf i matches ns[i]") 52 | { 53 | for (int i = 0; i < N; ++i) 54 | REQUIRE(tree.sum(i, i) == ns[i]); 55 | } 56 | } 57 | } 58 | } 59 | 60 | SCENARIO("segment tree range sum", "[segtree]") 61 | { 62 | GIVEN("a random vector ns of integers") 63 | { 64 | // Generates N random numbers between [-1000000, 1000000] 65 | srand(time(NULL)); 66 | 67 | int N = (rand() % 1000) + 1; 68 | vector ns(N, 0); 69 | 70 | for (int i = 0; i < N; ++i) 71 | ns[i] = (rand() % 2000001) - 1000000; 72 | 73 | WHEN("a segment tree is filled with ns") 74 | { 75 | SegmentTree tree(N); 76 | 77 | for (int i = 0; i < N; ++i) 78 | tree.add(i, ns[i]); 79 | 80 | THEN("each segment [i, j] sum matches the (ns[i] + ns[i+1] + ... + ns[j])") 81 | { 82 | for (int i = 0; i < N; ++i) 83 | for (int j = i; j < N; ++j) 84 | { 85 | int s = 0; 86 | 87 | for (int k = i; k <= j; ++k) 88 | s += ns[k]; 89 | 90 | REQUIRE(tree.sum(i, j) == s); 91 | } 92 | } 93 | } 94 | } 95 | 96 | GIVEN("a random vector ns of integers") 97 | { 98 | // Generates N random numbers between [-1000000, 1000000] 99 | srand(time(NULL)); 100 | 101 | int N = (rand() % 1000) + 1; 102 | vector ns(N, 0); 103 | 104 | for (int i = 0; i < N; ++i) 105 | ns[i] = (rand() % 2000001) - 1000000; 106 | 107 | WHEN("a segment tree is filled with ns and random values are added to random elements n[i]") 108 | { 109 | SegmentTree tree(N); 110 | 111 | for (int i = 0; i < N; ++i) 112 | tree.add(i, ns[i]); 113 | 114 | int M = (rand() % 1000) + 1; 115 | 116 | while (M--) 117 | { 118 | int i = rand() % N; 119 | int v = (rand() % 2000001) - 1000000; 120 | 121 | ns[i] += v; 122 | tree.add(i, v); 123 | } 124 | 125 | THEN("each segment [i, j] sum matches the (ns[i] + ns[i+1] + ... + ns[j])") 126 | { 127 | for (int i = 0; i < N; ++i) 128 | for (int j = i; j < N; ++j) 129 | { 130 | int s = 0; 131 | 132 | for (int k = i; k <= j; ++k) 133 | s += ns[k]; 134 | 135 | REQUIRE(tree.sum(i, j) == s); 136 | } 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /tests/data_structures/segment_tree_with_lazy_propagation.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include 5 | #include 6 | #include "data_structures/segment_tree_with_lazy_propagation.h" 7 | 8 | using std::min; 9 | using std::max; 10 | 11 | SCENARIO("segment tree range update with lazy propagation", "[segtree]") 12 | { 13 | GIVEN("a tree filled with a vector ns of integers") 14 | { 15 | // Generates N random numbers between [-1000000, 1000000] 16 | srand(time(NULL)); 17 | 18 | int N = (rand() % 1000) + 1, s = 0; 19 | vector ns(N, 0); 20 | 21 | for (int i = 0; i < N; ++i) 22 | { 23 | ns[i] = (rand() % 2000001) - 1000000; 24 | s += ns[i]; 25 | } 26 | 27 | SegmentTree tree(N); 28 | 29 | for (int i = 0; i < N; ++i) 30 | tree.add(i, i, ns[i]); 31 | 32 | REQUIRE(tree.sum(0, N - 1) == s); 33 | 34 | WHEN("a random segment [a,b] is updated with a random value v") 35 | { 36 | THEN("each segment [a,b] matches (ns[a] + ns[a+1] + ... + ns[b])") 37 | { 38 | for (int sample = 0; sample < 1000; ++sample) 39 | { 40 | int i = rand() % N, j = rand() % N; 41 | int a = min(i, j), b = max(i, j); 42 | int v = (rand() % 2000001) - 1000000; 43 | 44 | for (int k = a; k <= b; ++k) 45 | ns[k] += v; 46 | 47 | tree.add(a, b, v); 48 | 49 | i = rand() % N, j = rand() % N; 50 | a = min(i, j), b = max(i, j); 51 | 52 | s = 0; 53 | 54 | for (int k = a; k <= b; ++k) 55 | s += ns[k]; 56 | 57 | REQUIRE(tree.sum(a, b) == s); 58 | } 59 | } 60 | } 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /tests/geometry/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | CFLAGS = -std=c++11 -Wall -W -Wextra -Werror -O2 3 | #CFLAGS = -pedantic -std=c++11 -w -MMD -g3 -g -fPIC\ 4 | -W -Wall -Wextra -Wshadow -Wcast-align -Wcast-qual -Wctor-dtor-privacy\ 5 | -Wdisabled-optimization -Wformat=2 -Wlogical-op -Wmissing-declarations\ 6 | -Wmissing-include-dirs -Wnoexcept -Woverloaded-virtual -Wredundant-decls\ 7 | -Wsign-promo -Wstrict-null-sentinel -Wswitch-default -Wundef\ 8 | -Wzero-as-null-pointer-constant -Wuseless-cast -Wnon-virtual-dtor 9 | 10 | INCLUDES = -I../../ -I../../algorithms 11 | LIBS = 12 | 13 | SRC = ${wildcard *.cpp} 14 | TESTS = ${SRC:.cpp=.exe} 15 | 16 | .PHONY: clean depend dist-clean dist 17 | 18 | all: 19 | $(MAKE) $(TESTS) 20 | 21 | %.exe: %.cpp 22 | @echo Building $@ 23 | $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ 24 | 25 | clean: 26 | @echo Cleaning... 27 | @rm -rf *~ *.o prog out.txt *.d 28 | 29 | dist-clean: clean 30 | @rm -rf *.exe 31 | -------------------------------------------------------------------------------- /tests/geometry/circle.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define CATCH_CONFIG_MAIN 3 | #include "tests/catch.hpp" 4 | 5 | #include "geometry/circle.h" 6 | 7 | SCENARIO("circle initialization and point position", "[circle]") 8 | { 9 | GIVEN ("A circle and a point P") 10 | { 11 | Circle c(Point(0.0, 0.0), 5.0); 12 | 13 | REQUIRE(c.C == Point(0.0, 0.0)); 14 | REQUIRE(equals(c.r, 5.0)); 15 | 16 | Point P(3.0, 4.0); 17 | 18 | WHEN("P are on the circle") 19 | { 20 | THEN("position must return ON") 21 | { 22 | REQUIRE(c.position(P) == Circle::ON); 23 | } 24 | } 25 | 26 | WHEN("P are inside the circle") 27 | { 28 | P = Point(2.0, 2.0); 29 | 30 | THEN("position must return IN") 31 | { 32 | REQUIRE(c.position(P) == Circle::IN); 33 | } 34 | } 35 | 36 | WHEN ("P are outside the circle") 37 | { 38 | P = Point(4.0, 4.0); 39 | 40 | THEN("position must return OUT") 41 | { 42 | REQUIRE(c.position(P) == Circle::OUT); 43 | } 44 | } 45 | 46 | } 47 | } 48 | 49 | SCENARIO("circle perimeter and area", "[circle]") 50 | { 51 | GIVEN("A circle") 52 | { 53 | Circle c(Point(0.0, 0.0)); 54 | 55 | WHEN("radius equals 1.0") 56 | { 57 | c.r = 1.0; 58 | 59 | THEN("perimeter equals 2*PI") 60 | { 61 | REQUIRE(equals(c.perimeter(), 2.0 * M_PI)); 62 | } 63 | 64 | THEN("area equals PI") 65 | { 66 | REQUIRE( equals(c.area(), M_PI) ); 67 | } 68 | } 69 | 70 | WHEN("radius equals PI") 71 | { 72 | c.r = M_PI; 73 | 74 | THEN("perimeter equals 2*PI*PI") 75 | { 76 | REQUIRE(equals(c.perimeter(), 2.0 * M_PI * M_PI)); 77 | } 78 | 79 | THEN("area equals PI**3") 80 | { 81 | REQUIRE(equals(c.area(), M_PI * M_PI * M_PI)); 82 | } 83 | } 84 | } 85 | } 86 | 87 | SCENARIO("circles with radius r that contains P and Q", "[circle]") 88 | { 89 | GIVEN ("Two points P and Q and a radius r") 90 | { 91 | Point P, Q(8.0, 0.0); 92 | double r = 5.0; 93 | Circle c; 94 | 95 | WHEN("P equals Q") 96 | { 97 | Q = P; 98 | 99 | THEN("infinite number of circles with radius r that contains P") 100 | { 101 | auto cs = Circle::from_2_points_and_radius(P, Q, r); 102 | 103 | REQUIRE(cs.size() > 2); 104 | 105 | for (const auto& x : cs) 106 | REQUIRE(x.position(P) == Circle::ON); 107 | } 108 | } 109 | 110 | WHEN("r is lesser or equals than half the distance dist(P, Q)") 111 | { 112 | r = 3.0; 113 | 114 | THEN("there no circle that passes through P and Q with radius r") 115 | { 116 | auto cs = Circle::from_2_points_and_radius(P, Q, r); 117 | 118 | REQUIRE(cs.empty()); 119 | } 120 | } 121 | 122 | WHEN("r is greater than half the distance dist(P, Q)") 123 | { 124 | THEN( "there are two circles" ) 125 | { 126 | auto cs = Circle::from_2_points_and_radius(P, Q, r); 127 | REQUIRE(cs.size() == 2); 128 | REQUIRE(cs.front() != cs.back()); 129 | 130 | for (const auto& x : cs) 131 | { 132 | REQUIRE(x.position(P) == Circle::ON); 133 | REQUIRE(x.position(Q) == Circle::ON); 134 | } 135 | } 136 | } 137 | } 138 | } 139 | 140 | SCENARIO("circles from 3 points", "[circle]") 141 | { 142 | GIVEN ("Three points P, Q and R") 143 | { 144 | Point P, Q, R; 145 | 146 | WHEN("P, Q and R are colinear") 147 | { 148 | THEN("there no circle that passes through P, Q and R") 149 | { 150 | auto cs = Circle::from_3_points(P, Q, R); 151 | 152 | REQUIRE(cs.empty()); 153 | } 154 | } 155 | 156 | WHEN("P, Q and R are not colinear") 157 | { 158 | Q = Point(2.0, 3.0); 159 | R = Point(-1.0, 5.0); 160 | 161 | THEN("there is one circle that passes through P, Q and R") 162 | { 163 | auto cs = Circle::from_3_points(P, Q, R); 164 | 165 | REQUIRE(cs.size() == 1); 166 | 167 | auto c = cs.front(); 168 | 169 | REQUIRE(c.position(P) == Circle::ON); 170 | REQUIRE(c.position(Q) == Circle::ON); 171 | REQUIRE(c.position(R) == Circle::ON); 172 | } 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /tests/geometry/line.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include "geometry/line.h" 5 | 6 | SCENARIO( "line initialization and comparison", "[line]" ) 7 | { 8 | GIVEN ( "Two lines" ) 9 | { 10 | Line r(1, 2, 3), s(2, 4, 6); 11 | 12 | WHEN ( "they have the same coefficients" ) 13 | { 14 | THEN ( "they are equals" ) 15 | { 16 | REQUIRE( r == s ); 17 | } 18 | } 19 | 20 | WHEN ( "they have the same inclination, but aren't the same" ) 21 | { 22 | THEN ( "they are parallel" ) 23 | { 24 | REQUIRE( not r.parallel(s) ); 25 | 26 | s.c = 5; 27 | 28 | REQUIRE( r.parallel(s) ); 29 | } 30 | } 31 | 32 | WHEN ( "they don't have the same inclination" ) 33 | { 34 | THEN ( "they are concurrent" ); 35 | 36 | r = Line(1, 0, 1); 37 | s = Line(0, 1, 1); 38 | 39 | REQUIRE( r.concurrent(s) ); 40 | 41 | r = Line(1, 0, 1); 42 | s = Line(1, 1, 1); 43 | 44 | REQUIRE( r.concurrent(s) ); 45 | 46 | r = Line(1, 1, 1); 47 | s = Line(1, 0, 1); 48 | 49 | REQUIRE( r.concurrent(s) ); 50 | 51 | r = Line(1, 1, 1); 52 | s = Line(1, 1, 1); 53 | 54 | REQUIRE( not r.concurrent(s) ); 55 | 56 | r = Line(1, 2, 1); 57 | s = Line(3, 4, 1); 58 | 59 | REQUIRE( r.concurrent(s) ); 60 | 61 | r = Line(1, 0, 1); 62 | s = Line(1, 1, 1); 63 | 64 | REQUIRE( r.concurrent(s) ); 65 | } 66 | } 67 | } 68 | 69 | SCENARIO( "lines intersection", "[line]" ) 70 | { 71 | GIVEN ( "Two lines" ) 72 | { 73 | Line r(1, 2, 3), s(2, 4, 6); 74 | 75 | WHEN ( "they are coincidents" ) 76 | { 77 | THEN ( "they have all points in comum" ) 78 | { 79 | auto p = r.intersections(s); 80 | 81 | REQUIRE( p.first == Line::INF ); 82 | } 83 | } 84 | 85 | WHEN ( "they are parallel" ) 86 | { 87 | s.c = 5; 88 | 89 | THEN ( "they have no intersection" ) 90 | { 91 | auto p = r.intersections(s); 92 | 93 | REQUIRE( p.first == Line::ZERO ); 94 | } 95 | } 96 | 97 | WHEN ( "they are concurrent" ) 98 | { 99 | THEN ( "they have exactly one intersection point" ) 100 | { 101 | r = Line(2, 1, 1); 102 | s = Line(5, 3, 2); 103 | 104 | auto p = r.intersections(s); 105 | 106 | REQUIRE( p.first == Line::ONE ); 107 | REQUIRE( p.second == Point(-1.0, 1.0) ); 108 | 109 | r = Line(0, 1, -1); 110 | s = Line(2, 0, -4); 111 | 112 | auto q = r.intersections(s); 113 | 114 | REQUIRE( q.first == Line::ONE ); 115 | REQUIRE( q.second == Point(2.0, 1.0) ); 116 | } 117 | } 118 | 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /tests/geometry/point.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include "geometry/point.h" 5 | 6 | SCENARIO("points initialization and distance", "[point]") 7 | { 8 | GIVEN("Two points") 9 | { 10 | Point P, Q(3.0, 4.0); 11 | 12 | REQUIRE((P.x == 0 and P.y == 0)); 13 | REQUIRE((Q.x == 3 and Q.y == 4)); 14 | 15 | REQUIRE(P != Q); 16 | 17 | WHEN("points are different") 18 | { 19 | THEN("distance must positive") 20 | { 21 | auto d = P.distance(Q); 22 | 23 | REQUIRE(d > 0); 24 | REQUIRE(equals(d, 5.0) ); 25 | } 26 | } 27 | 28 | WHEN("points are equals") 29 | { 30 | auto dP = P.distance(P); 31 | auto dQ = Q.distance(Q); 32 | 33 | THEN("distance must be zero") 34 | { 35 | REQUIRE(equals(dP, 0.0)); 36 | REQUIRE(equals(dQ, 0.0)); 37 | } 38 | } 39 | } 40 | } 41 | 42 | SCENARIO("translations, rotations and scale", "[point]") 43 | { 44 | GIVEN("A point P and two deltas (dx and dy)") 45 | { 46 | Point P; 47 | 48 | auto dx = 4.0; 49 | auto dy = -3.0; 50 | 51 | WHEN("P is the origin") 52 | { 53 | REQUIRE(P == Point(0, 0)); 54 | 55 | THEN("the translated point Q must have coordinates (dx, dy)") 56 | { 57 | auto Q = P.translate(dx, dy); 58 | 59 | REQUIRE(equals(Q.x, dx)); 60 | REQUIRE(equals(Q.y, dy)); 61 | } 62 | } 63 | 64 | WHEN("Q is P translated by (dx, dy)") 65 | { 66 | P = Point(-1.0, 2.0); 67 | auto Q = P.translate(dx, dy); 68 | 69 | THEN ("then P and Q must be different") 70 | { 71 | REQUIRE(equals(Q.x, 3.0)); 72 | REQUIRE(equals(Q.y, -1.0)); 73 | REQUIRE(P != Q); 74 | } 75 | } 76 | } 77 | 78 | GIVEN("A point P and two scalars kx and ky)") 79 | { 80 | Point P(-2.5, 3.8); 81 | 82 | auto kx = 4.0; 83 | auto ky = -3.0; 84 | 85 | WHEN("P is scaled by k = kx") 86 | { 87 | THEN("the result is a point Q = kP") 88 | { 89 | auto Q = P.scale(kx); 90 | 91 | REQUIRE(equals(Q.x, kx*P.x)); 92 | REQUIRE(equals(Q.y, kx*P.y)); 93 | } 94 | } 95 | 96 | WHEN("P is scaled on both coordinates by kx and ky") 97 | { 98 | THEN ("the result is a point Q = (kx * Px, ky * Py)") 99 | { 100 | auto Q = P.scale(kx, ky); 101 | 102 | REQUIRE(equals(Q.x, kx*P.x)); 103 | REQUIRE(equals(Q.y, ky*P.y)); 104 | } 105 | } 106 | } 107 | 108 | GIVEN("A point") 109 | { 110 | Point P(1.0, 0.0); 111 | 112 | WHEN("rotated counterclockwise by 90 degrees") 113 | { 114 | THEN("it must be on x ou y axis") 115 | { 116 | P = P.rotate(M_PI/2.0); 117 | REQUIRE(P == Point(0.0, 1.0)); 118 | 119 | P = P.rotate(M_PI/2.0); 120 | REQUIRE(P == Point(-1.0, 0.0)); 121 | 122 | P = P.rotate(M_PI/2.0); 123 | REQUIRE(P == Point(0.0, -1.0)); 124 | 125 | P = P.rotate(M_PI/2.0); 126 | REQUIRE(P == Point(1.0, 0.0)); 127 | } 128 | } 129 | 130 | WHEN("rotated counterclockwise by r degrees") 131 | { 132 | THEN("must lie in a point Q such the segments OP and OQ form a angle of r degrees") 133 | { 134 | double r = M_PI/4.0; 135 | double s = sqrt(2.0)/2.0; 136 | 137 | auto Q = P.rotate(r); 138 | 139 | REQUIRE(P == Point(1.0, 0.0)); 140 | REQUIRE(Q == Point(s, s)); 141 | 142 | r = M_PI/3.0; 143 | s = sqrt(3.0)/2.0; 144 | 145 | Q = P.rotate(r); 146 | 147 | REQUIRE(P == Point(1.0, 0)); 148 | REQUIRE(Q == Point(0.5, s)); 149 | 150 | r = M_PI/6; 151 | 152 | Q = P.rotate(r); 153 | 154 | REQUIRE(P == Point(1.0, 0)); 155 | REQUIRE(Q == Point(s, 0.5)); 156 | 157 | r = M_PI; 158 | 159 | Q = P.rotate(r); 160 | 161 | REQUIRE(P == Point(1.0, 0)); 162 | REQUIRE(Q == Point(-1.0, 0)); 163 | 164 | r = 2*M_PI; 165 | 166 | Q = P.rotate(r); 167 | 168 | REQUIRE(P == Point(1.0, 0)); 169 | REQUIRE(Q == P); 170 | 171 | r = M_PI/7.0; 172 | 173 | double x = 0.9009688679024191; 174 | double y = 0.4338837391175581; 175 | 176 | Q = P.rotate(r); 177 | 178 | REQUIRE(P == Point(1.0, 0.0)); 179 | REQUIRE(Q == Point(x, y)); 180 | } 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /tests/graph/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | CFLAGS = -std=c++11 -Wall -W -Wextra -Werror -O2 3 | #CFLAGS = -pedantic -std=c++11 -w -MMD -g3 -g -fPIC\ 4 | -W -Wall -Wextra -Wshadow -Wcast-align -Wcast-qual -Wctor-dtor-privacy\ 5 | -Wdisabled-optimization -Wformat=2 -Wlogical-op -Wmissing-declarations\ 6 | -Wmissing-include-dirs -Wnoexcept -Woverloaded-virtual -Wredundant-decls\ 7 | -Wsign-promo -Wstrict-null-sentinel -Wswitch-default -Wundef\ 8 | -Wzero-as-null-pointer-constant -Wuseless-cast -Wnon-virtual-dtor 9 | 10 | INCLUDES = -I../../ -I../../algorithms 11 | LIBS = 12 | 13 | SRC = ${wildcard *.cpp} 14 | TESTS = ${SRC:.cpp=.exe} 15 | 16 | .PHONY: clean depend dist-clean dist 17 | 18 | all: 19 | $(MAKE) $(TESTS) 20 | 21 | %.exe: %.cpp 22 | @echo Building $@ 23 | $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ 24 | 25 | clean: 26 | @echo Cleaning... 27 | @rm -rf *~ *.o prog out.txt *.d 28 | 29 | dist-clean: clean 30 | @rm -rf *.exe 31 | -------------------------------------------------------------------------------- /tests/graph/bfs.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include "graph/bfs.h" 5 | 6 | SCENARIO("bfs traversal", "[graph]") 7 | { 8 | GIVEN("An undirected graph") 9 | { 10 | for (int u = 0; u < MAX; ++u) 11 | adj[u].clear(); 12 | 13 | visited.reset(); 14 | 15 | WHEN("there is just one vertex") 16 | { 17 | THEN("the BFS must return [1]") 18 | { 19 | vector res { 1 }, ans; 20 | 21 | bfs(1, [&](int u) { ans.push_back(u); }); 22 | 23 | REQUIRE(ans == res); 24 | } 25 | } 26 | 27 | WHEN("there is 4 connected vertices") 28 | { 29 | adj[1].push_back(3); 30 | adj[3].push_back(1); 31 | adj[1].push_back(4); 32 | adj[4].push_back(1); 33 | adj[3].push_back(4); 34 | adj[4].push_back(3); 35 | adj[2].push_back(4); 36 | adj[4].push_back(2); 37 | 38 | THEN("the BFS must return [1, 3, 4, 2]") 39 | { 40 | vector res { 1, 3, 4, 2 }, ans; 41 | 42 | bfs(1, [&](int u) { ans.push_back(u); }); 43 | 44 | REQUIRE(ans == res); 45 | } 46 | } 47 | 48 | WHEN("there is 4 unconnected vertices") 49 | { 50 | adj[1].push_back(3); 51 | adj[3].push_back(1); 52 | adj[2].push_back(4); 53 | adj[4].push_back(2); 54 | 55 | THEN("the DFS must return [1, 3]") 56 | { 57 | vector res { 1, 3 }, ans; 58 | 59 | bfs(1, [&](int u) { ans.push_back(u); }); 60 | 61 | REQUIRE(ans == res); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/graph/bipartite.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include "graph/bipartite.h" 5 | 6 | SCENARIO("bipartite graph", "[graph]") 7 | { 8 | GIVEN("An undirected graph") 9 | { 10 | for (int u = 0; u < MAX; ++u) 11 | adj[u].clear(); 12 | 13 | visited.reset(); 14 | 15 | WHEN("there is just one vertex") 16 | { 17 | THEN("the graph is bipartite") 18 | { 19 | REQUIRE(is_bipartite(1) == true); 20 | } 21 | } 22 | 23 | WHEN("the graph is 3-complete") 24 | { 25 | adj[1] = {2, 3}; 26 | adj[2] = {1, 3}; 27 | adj[3] = {1, 2}; 28 | 29 | THEN("it is not bipartite") 30 | { 31 | REQUIRE(is_bipartite(1) == false); 32 | } 33 | } 34 | 35 | WHEN("the graph is bipartite") 36 | { 37 | vector edges { ii(1, 2), ii(1, 3), ii(1, 4), ii(1, 5), ii(2, 6), ii(3, 6), 38 | ii(4, 8), ii(5, 7), ii(6, 9), ii(7, 9), ii(8, 9), ii(9, 10) }; 39 | 40 | for (const auto& edge : edges) 41 | { 42 | int u, v; 43 | tie(u, v) = edge; 44 | 45 | adj[u].push_back(v); 46 | adj[v].push_back(u); 47 | } 48 | 49 | THEN("the function is_bipartite() must return true") 50 | { 51 | REQUIRE(is_bipartite(1) == true); 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/graph/connected_components.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include "graph/connected_components.h" 5 | 6 | using ii = pair; 7 | 8 | SCENARIO("dfs traversal", "[graph]") 9 | { 10 | GIVEN("An unconnected undirected graph") 11 | { 12 | vector edges { ii(1, 2), ii(1, 8), ii(2, 10), ii(3, 7), ii(4, 5), 13 | ii(4, 9), ii(5, 9) }; 14 | 15 | for (const auto& edge : edges) 16 | { 17 | auto u = edge.first; 18 | auto v = edge.second; 19 | 20 | adj[u].push_back(v); 21 | adj[v].push_back(u); 22 | } 23 | 24 | WHEN("there is more then one component") 25 | { 26 | THEN("the algorithm mustmust return all of them") 27 | { 28 | vector> res { {1, 2, 10, 8}, {3, 7}, {4, 5, 9}, {6}}; 29 | auto ans = connected_components(10); 30 | 31 | REQUIRE(ans.size() == res.size()); 32 | REQUIRE(ans == res); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/graph/dfs.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include "graph/dfs.h" 5 | 6 | SCENARIO("dfs traversal", "[graph]") 7 | { 8 | GIVEN("An undirected graph") 9 | { 10 | for (int u = 0; u < MAX; ++u) 11 | adj[u].clear(); 12 | 13 | visited.reset(); 14 | 15 | 16 | WHEN("there is just one vertex") 17 | { 18 | THEN("the DFS must return [1]") 19 | { 20 | vector res { 1 }, ans; 21 | 22 | dfs(1, [&](int u) { ans.push_back(u); }); 23 | 24 | REQUIRE(ans == res); 25 | } 26 | } 27 | 28 | WHEN("there is 4 connected vertices") 29 | { 30 | adj[1].push_back(3); 31 | adj[3].push_back(1); 32 | adj[1].push_back(4); 33 | adj[4].push_back(1); 34 | adj[3].push_back(4); 35 | adj[4].push_back(3); 36 | adj[2].push_back(4); 37 | adj[4].push_back(2); 38 | 39 | THEN("the DFS must return [1, 3, 4, 2]") 40 | { 41 | vector res { 1, 3, 4, 2 }, ans; 42 | 43 | dfs(1, [&](int u) { ans.push_back(u); }); 44 | 45 | REQUIRE(ans == res); 46 | } 47 | } 48 | 49 | WHEN("there is 4 unconnected vertices") 50 | { 51 | adj[1].push_back(3); 52 | adj[3].push_back(1); 53 | adj[2].push_back(4); 54 | adj[4].push_back(2); 55 | 56 | THEN("the DFS must return [1, 3]") 57 | { 58 | vector res { 1, 3 }, ans; 59 | 60 | dfs(1, [&](int u) { ans.push_back(u); }); 61 | 62 | REQUIRE(ans == res); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/graph/has_cycle.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "tests/catch.hpp" 3 | 4 | #include "graph/has_cycle.h" 5 | 6 | using ii = pair; 7 | 8 | SCENARIO("cycle detection", "[graph]") 9 | { 10 | GIVEN("An undirected graph") 11 | { 12 | WHEN("there is just one vertex") 13 | { 14 | THEN("there is no cycle") 15 | { 16 | REQUIRE(has_cycle(1) == false); 17 | } 18 | } 19 | 20 | WHEN("there is just two connected vertices") 21 | { 22 | vector edges { ii(1, 2) }; 23 | 24 | for (int u = 1; u <= 2; ++u) 25 | adj[u].clear(); 26 | 27 | for (const auto& edge : edges) 28 | { 29 | auto u = edge.first; 30 | auto v = edge.second; 31 | 32 | adj[u].push_back(v); 33 | adj[v].push_back(u); 34 | } 35 | 36 | 37 | THEN("there is no cycle") 38 | { 39 | REQUIRE(has_cycle(2) == false); 40 | } 41 | } 42 | 43 | WHEN("the graph is 3-complete") 44 | { 45 | vector edges { ii(1, 2), ii(1, 3), ii(2, 3) }; 46 | 47 | for (int u = 1; u <= 3; ++u) 48 | adj[u].clear(); 49 | 50 | for (const auto& edge : edges) 51 | { 52 | auto u = edge.first; 53 | auto v = edge.second; 54 | 55 | adj[u].push_back(v); 56 | adj[v].push_back(u); 57 | } 58 | 59 | 60 | THEN("there is a cycle") 61 | { 62 | REQUIRE(has_cycle(3) == true); 63 | } 64 | } 65 | 66 | WHEN("the graph is connected with more edges than vertices") 67 | { 68 | vector edges { ii(1, 2), ii(1, 3), ii(2, 3), ii(2, 5), ii(2, 6), 69 | ii(3, 4), ii(3, 10), ii(5, 6), ii(5, 7), ii(6, 9), ii(6, 10), 70 | ii(7, 8), ii(7, 9), ii(8, 9) }; 71 | 72 | for (int u = 1; u <= 10; ++u) 73 | adj[u].clear(); 74 | 75 | for (const auto& edge : edges) 76 | { 77 | auto u = edge.first; 78 | auto v = edge.second; 79 | 80 | adj[u].push_back(v); 81 | adj[v].push_back(u); 82 | } 83 | 84 | 85 | THEN("there is a cycle") 86 | { 87 | REQUIRE(has_cycle(10) == true); 88 | } 89 | } 90 | 91 | 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /tests/io/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -W -Wextra -Werror -O2 3 | 4 | CPPC = g++ 5 | CPPFLAGS = -std=c++11 -Wall -W -Wextra -Werror -O2 6 | #CFLAGS = -pedantic -std=c++11 -w -MMD -g3 -g -fPIC\ 7 | -W -Wall -Wextra -Wshadow -Wcast-align -Wcast-qual -Wctor-dtor-privacy\ 8 | -Wdisabled-optimization -Wformat=2 -Wlogical-op -Wmissing-declarations\ 9 | -Wmissing-include-dirs -Wnoexcept -Woverloaded-virtual -Wredundant-decls\ 10 | -Wsign-promo -Wstrict-null-sentinel -Wswitch-default -Wundef\ 11 | -Wzero-as-null-pointer-constant -Wuseless-cast -Wnon-virtual-dtor 12 | 13 | INCLUDES = -I../../ -I../../algorithms 14 | 15 | JAVAC = javac 16 | CLASSPATH = ../../ 17 | 18 | SRC = ${wildcard *.cpp} 19 | TESTS = ${SRC:.cpp=.exe} 20 | 21 | CSRC = ${wildcard *.c} 22 | CTESTS = ${CSRC:.c=.exe} 23 | 24 | JSRC = ${wildcard *.java} 25 | JTESTS = ${JSRC:.java=.class} 26 | 27 | # To execute a java test: 28 | # $ java -cp .:../../ Test < in 29 | 30 | .PHONY: clean depend dist-clean dist 31 | .SUFFIXES: .java 32 | 33 | all: 34 | $(MAKE) $(JTESTS) $(TESTS) $(CTESTS) 35 | 36 | %.exe: %.c 37 | @echo Building $@ 38 | $(CC) $(CFLAGS) $(INCLUDES) $< -o $@ 39 | 40 | %.exe: %.cpp 41 | @echo Building $@ 42 | $(CPPC) $(CPPFLAGS) $(INCLUDES) $< -o $@ 43 | 44 | %.class: %.java 45 | @echo Building $@ 46 | $(JAVAC) -classpath $(CLASSPATH) $< 47 | 48 | clean: 49 | @echo Cleaning... 50 | @rm -rf *~ *.o prog out.txt *.d *.class 51 | 52 | dist-clean: clean 53 | @rm -rf *.exe 54 | -------------------------------------------------------------------------------- /tests/io/TestBufferedIO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Classe para teste dos métodos de IO do Java 3 | * 4 | * Autor: Edson Alves 5 | * Data: 18/02/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | import algorithms.io.BufferedIO; 9 | import util.Test; 10 | 11 | public class TestBufferedIO { 12 | 13 | public static final void main(final String[] args) { 14 | 15 | BufferedIO io = new BufferedIO(); 16 | 17 | long start = System.currentTimeMillis(); 18 | int [] ns = io.read(); 19 | long end = System.currentTimeMillis(); 20 | 21 | long rtime = end - start; 22 | 23 | start = System.currentTimeMillis(); 24 | io.write(ns); 25 | end = System.currentTimeMillis(); 26 | 27 | long wtime = end - start; 28 | 29 | System.out.println("" + rtime + " ms to read " + ns.length + " integers"); 30 | System.out.println("" + wtime + " ms to write " + ns.length + " integers"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/io/TestIO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Classe para teste dos métodos de IO do Java 3 | * 4 | * Autor: Edson Alves 5 | * Data: 18/02/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | import algorithms.io.IO; 9 | import util.Test; 10 | 11 | public class TestIO { 12 | 13 | public static final void main(final String[] args) { 14 | 15 | IO io = new IO(); 16 | 17 | long start = System.currentTimeMillis(); 18 | int [] ns = io.read(); 19 | long end = System.currentTimeMillis(); 20 | 21 | long rtime = end - start; 22 | 23 | start = System.currentTimeMillis(); 24 | io.write(ns); 25 | end = System.currentTimeMillis(); 26 | 27 | long wtime = end - start; 28 | 29 | System.out.println("" + rtime + " ms to read " + ns.length + " integers"); 30 | System.out.println("" + wtime + " ms to write " + ns.length + " integers"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/io/async_io.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Classe para teste de execução do método echo() da classe IO. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 12/03/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #include 9 | 10 | #include 11 | 12 | using namespace std; 13 | 14 | int main() 15 | { 16 | IO io; 17 | 18 | auto start = chrono::system_clock::now(); 19 | auto ns = io.read(); 20 | auto end = chrono::system_clock::now(); 21 | chrono::duration rtime = end - start; 22 | 23 | start = chrono::system_clock::now(); 24 | io.write(ns); 25 | end = chrono::system_clock::now(); 26 | chrono::duration wtime = end - start; 27 | 28 | cout.precision(6); 29 | cout << rtime.count() << "ms to read " << ns.size() << " integers\n"; 30 | 31 | cout.precision(6); 32 | cout << wtime.count() << "ms to write " << ns.size() << " integers\n"; 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /tests/io/buffered_io.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Classe para teste de execução do método echo() da classe IO. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 12/03/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #include 9 | 10 | #include 11 | 12 | using namespace std; 13 | 14 | int main() 15 | { 16 | auto start = chrono::system_clock::now(); 17 | auto ns = read(); 18 | auto end = chrono::system_clock::now(); 19 | chrono::duration rtime = end - start; 20 | 21 | start = chrono::system_clock::now(); 22 | write(ns); 23 | end = chrono::system_clock::now(); 24 | chrono::duration wtime = end - start; 25 | 26 | cout.precision(6); 27 | cout << rtime.count() << "ms to read " << ns.size() << " integers\n"; 28 | 29 | cout.precision(6); 30 | cout << wtime.count() << "ms to write " << ns.size() << " integers\n"; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /tests/io/cio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Classe para teste de execução do método echo() da classe IO. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 12/03/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #define CLOCKS (CLOCKS_PER_SEC*1.0) 14 | 15 | int main() 16 | { 17 | clock_t start, end; 18 | double rtime, wtime; 19 | int n; 20 | 21 | start = clock(); 22 | n = read(); 23 | end = clock(); 24 | rtime = (end - start)/CLOCKS; 25 | 26 | 27 | start = clock(); 28 | write(n); 29 | end = clock(); 30 | wtime = (end - start)/CLOCKS; 31 | 32 | printf("%.6fms to read %d integers\n", rtime, n); 33 | printf("%.6fms to write %d integers\n", wtime, n); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /tests/io/io.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Classe para teste de execução do método echo() da classe IO. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 12/03/2015 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #include 9 | 10 | #include 11 | 12 | using namespace std; 13 | 14 | int main() 15 | { 16 | auto start = chrono::system_clock::now(); 17 | auto ns = IO::read(); 18 | auto end = chrono::system_clock::now(); 19 | chrono::duration rtime = end - start; 20 | 21 | start = chrono::system_clock::now(); 22 | IO::write(ns); 23 | end = chrono::system_clock::now(); 24 | chrono::duration wtime = end - start; 25 | 26 | cout.precision(6); 27 | cout << rtime.count() << "ms to read " << ns.size() << " integers\n"; 28 | 29 | cout.precision(6); 30 | cout << wtime.count() << "ms to write " << ns.size() << " integers\n"; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /util/bitwise_operations.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Operações binárias. 3 | * 4 | * Autor: Edson Alves 5 | * Data: 04/05/2018 6 | * Licença: LGPL. Sem copyright. 7 | */ 8 | #ifndef BITWISE_OPERATIONS_H 9 | #define BITWISE_OPERATIONS_H 10 | 11 | using std::cout; 12 | using std::endl; 13 | 14 | int least_significant_bit(int n) 15 | { 16 | return n & -n; 17 | } 18 | 19 | bool is_power_of_2(int n) 20 | { 21 | return n > 0 and least_significant_bit(n) == n; 22 | } 23 | 24 | int least_power_of_2_greater_or_equals(int n) 25 | { 26 | if (n < 0) 27 | return 1; 28 | 29 | if (is_power_of_2(n)) 30 | return n; 31 | 32 | int most_significant_bit = n; 33 | 34 | while (most_significant_bit & (most_significant_bit - 1)) // Checks if MSB is a power of 2 35 | most_significant_bit &= (most_significant_bit - 1); // Turns LSB off 36 | 37 | return most_significant_bit << 1; 38 | } 39 | 40 | #endif // BITWISE_OPERATIONS_H 41 | --------------------------------------------------------------------------------