diff --git a/algorithms/graph/articulations_bridges.cpp b/algorithms/graph/articulations_bridges.cpp index 2fbb2b63120b75c78962e62ced786756e25f39e5..fd2648439538f0c34b8d8eb5cb6afc40881bf979 100644 --- a/algorithms/graph/articulations_bridges.cpp +++ b/algorithms/graph/articulations_bridges.cpp @@ -1,4 +1,4 @@ -/// Articulations and Bridges - Tarjan +/// Articulations and Bridges /// /// Time: O(V + E) /// Space: O(V + E) diff --git a/algorithms/graph/centroid_decomposition.cpp b/algorithms/graph/centroid_decomposition.cpp index 6cace6113f3fab3a6e40e5a528eb61365de90459..7cb5041607054ed0bbdde6894d67df1533c188dc 100644 --- a/algorithms/graph/centroid_decomposition.cpp +++ b/algorithms/graph/centroid_decomposition.cpp @@ -1,13 +1,13 @@ /// Centroid Decomposition /// /// Description: -/// The Centroid Decomposition of a tree is a tree where its root is the -/// centroid of the original tree, and its children are the centroid of each -/// tree resulting from the removal of the root from the original tree. -/// The result is a tree with $lg(n)$ height, where the path from $a$ to $b$ -/// in the original tree can be decomposed into the path from a to lca($a$,$b$) -/// and from lca($a$,$b$) to $b$. -/// This is useful because each one of the $n^2$ paths of the original tree +/// The Centroid Decomposition of a tree is a tree where its root is the +/// centroid of the original tree, and its children are the centroid of each +/// tree resulting from the removal of the root from the original tree. \par +/// The result is a tree with $lg(n)$ height, where the path from $a$ to $b$ +/// in the original tree can be decomposed into the path from a to lca($a$,$b$) +/// and from lca($a$,$b$) to $b$. \par +/// This is useful because each one of the $n^2$ paths of the original tree /// is the concatenation of two paths in a set of $O(n lg(n))$ paths from a /// node to all its ancestors in the centroid decomposition. /// diff --git a/algorithms/graph/tarjan.cpp b/algorithms/graph/tarjan.cpp index 0232ee946f81690da7be745cf45b22e024ab2bdf..ecd8f88f953323c0e764ef0cea221e65deaae637 100644 --- a/algorithms/graph/tarjan.cpp +++ b/algorithms/graph/tarjan.cpp @@ -1,4 +1,4 @@ -/// Tarjan - Strongly Connected Components (SCC) +/// Tarjan /// /// Time: O(V + E) /// Space: O(V + E) @@ -48,7 +48,6 @@ struct Tarjan { } } - /// Returns number of SCCs. int run() { init(); ncomp = ind = 0; diff --git a/algorithms/structure/disjoint_set.cpp b/algorithms/structure/disjoint_set.cpp index 176136ec93f344aa5b104dfbcf27c3b832113ef1..b40765aeb1cd66c1aae8553cd93e0673276f1c70 100644 --- a/algorithms/structure/disjoint_set.cpp +++ b/algorithms/structure/disjoint_set.cpp @@ -1,6 +1,6 @@ /// Disjoint-set /// -/// Time: O(1) +/// Time: /// - make_set: O(1) /// - find_set: O(a(n)) /// - union_set: O(a(n)) diff --git a/caderno.pdf b/caderno.pdf index 745b2a84ac3c4bd0096dca4b93bf69495e665084..970826445bf0225f4bacd14f6373a284c0903289 100644 Binary files a/caderno.pdf and b/caderno.pdf differ diff --git a/gen_notebook b/gen_notebook index 6f639f7a2dd4f169912174101d2fb00793c66383..394a48cad6c4558f62a4b2a0fee5b92fa32ba76f 100755 --- a/gen_notebook +++ b/gen_notebook @@ -4,13 +4,13 @@ if [ "$1" = "DEBUG" ]; then tex_file=result.tex python3 notebook/gen_latex.py --header=notebook/header.tex --output=$tex_file else - tex_file=$(mktemp) + tex_file=bft_notebook python3 notebook/gen_latex.py --header=notebook/header.tex --output=$tex_file # Lualatex must be used in order to work with the correct font lualatex $tex_file -halt-on-error -output-directory . && lualatex $tex_file -halt-on-error -output-directory . - mv tmp.pdf caderno.pdf - rm tmp* + mv $tex_file.pdf caderno.pdf + rm $tex_file* fi diff --git a/notebook/gen_latex.py b/notebook/gen_latex.py index 6b8bf33b6acd4c41d73938d6ed2a9e2c04226b79..264a5f00d721be46901e02a399563de884cd2f42 100644 --- a/notebook/gen_latex.py +++ b/notebook/gen_latex.py @@ -38,12 +38,116 @@ class Tree: class LatexGenerator: + class SourceFile: def __init__(self, path): - pass - - def _parse(): - pass + source = open(path, 'r') + + self.type = path.split('.')[-1] + self.comment = '///' if self.type == 'cpp' else '"""' + + self.header = {} + self.code, self.raw_header = [], [] + self.sections = ['Description', 'Time', 'Space', 'Include'] + + self._parse_source(source) + self._parse_header() + + # Splits content of the file between header and code. + def _parse_source(self, source): + lines = source.readlines() + in_header = True + + for i, line in enumerate(lines): + if line[0:3] != self.comment: + in_header = False + + if in_header: + self.raw_header.append(line[4:-1]) + else: + self.code = lines[(i+1):] + break + + # Returns section name of line or None if nothing is found. + def _get_section(self, line): + comm = line.split(':')[0] + return comm if comm in self.sections else None + + # Builds header dict by separating the header on the + # found sections. + def _parse_header(self): + self.name = self.raw_header[0] + + curr = None + for i in self.raw_header[1:]: + section = self._get_section(i) + + if section != None: + curr = section + self.header[curr] = [] + + # Add rest of line (right side of section name) + rest = ':'.join(i.split(':')[1:]).strip() + if len(rest) > 0: + self.header[curr].append(rest) + else: + if curr != None: + line = i.strip() + if len(line) > 0: + self.header[curr].append(line) + + # Make description a single line + if 'Description' in self.header: + text = self.header['Description'] + self.header['Description'] = ' '.join(text) + + # Writes own code to LaTeX output. + def output_code(self, write): + write('\\begin{lstlisting}[style=custom%s]\n' % self.type) + for i in self.code: + write(i) + write('\\end{lstlisting}\n') + write('\n') + + # Writes own header to LaTeX output. + def output_header(self, write): + write('\\begin{adjustwidth}{5pt}{5pt}\n') + + if 'Description' in self.header: + write('\\textbf{\\footnotesize Description: }\n') + write('\\footnotesize{\\par %s}' % self.header['Description']) + write('\\\\\n') + write('~\\\\\n') + + if 'Time' in self.header: + write('\\textbf{\\footnotesize Time: }') + if len(self.header['Time']) > 1: + write('\n') + write('\\begin{compactitem}\n') + for i in self.header['Time']: + line = i[1:].split(':') + write('\\item{\\footnotesize{%s: $%s$}}\n' % + (line[0].strip().replace('_', '\\_'), + line[1].strip())) + write('\\end{compactitem}\n') + else: + write('\\footnotesize{$%s$}\\\\\n' % self.header['Time'][0]) + + if 'Space' in self.header: + write('\\textbf{\\footnotesize Space: }') + if len(self.header['Space']) > 1: + write('\n') + write('\\begin{compactitem}\n') + for i in self.header['Space']: + line = i[1:].split(':') + write('\\item{\\footnotesize{%s: $%s$}}\n' % + (line[0].strip().replace('_', '\\_'), + line[1].strip())) + write('\\end{compactitem}\n') + else: + write('\\footnotesize{$%s$}\n' % self.header['Space'][0]) + + write('\\end{adjustwidth}\n') def __init__(self, tree, output, header): self.output = open(output, 'w') @@ -53,11 +157,21 @@ class LatexGenerator: self.files = {} self.hierarchy = [i*'sub' + 'section' for i in range(3)] + self._gen_latex() + + # Generates full LaTeX. + def _gen_latex(self): self._add_header() - self._gen_latex(tree) + + self._write('\\begin{document}\n') + self._write('\\tableofcontents\n') + self._write('\\newpage\n\n') + + self._gen_tree_latex(self.tree) + self._write('\\end{document}\n') - # Print text to output file + # Print text to output file. def _write(self, text): self.output.write(text) @@ -67,59 +181,40 @@ class LatexGenerator: for i in lines: self._write(i) - self._write('\\begin{document}\n') - self._write('\\tableofcontents\n') - self._write('\\newpage\n') - self._write('\n') - - # Prints section title in Latex format. + # Prints section title in LaTeX format. def _gen_title_latex(self, content, depth): self._write('\\%s{%s}\n' % (self.hierarchy[depth], content)) - # Prints code in Latex format. - def gen_code_latex(self, path): - suffix = path.split('.')[-1] - self._write('\\begin{lstlisting}[style=custom%s]\n' % suffix) - - # TODO: Add code parsing funcion to extract text from comments - with open(path) as f: - lines = f.readlines() - for i in lines: - self._write(i) - - self._write('\\end{lstlisting}\n') - self._write('\n') + # Prints code in LaTeX format. + def gen_code_latex(self, source): + source.output_header(self._write) + source.output_code(self._write) + self._write('\\hrule\n') - # Generates Latex for entire tree recursively - def _gen_latex(self, sub, path = '', depth = 0): + # Generates LaTeX for entire tree recursively. + def _gen_tree_latex(self, sub, path = '', depth = 0): if type(sub) == list: for i in sub: - self._gen_title_latex(self._parse_file_name(path + i), depth) - self.gen_code_latex(path + i) + source = self.SourceFile(path + i) + self._gen_title_latex(source.name, depth) + self.gen_code_latex(source) else: if depth == 1: self._write('\\begin{multicols}{3}\n') - for i in sub: self._gen_title_latex(self._parse_dir_name(i), depth) - self._gen_latex(sub[i], path + i + '/', depth + 1) - + self._gen_tree_latex(sub[i], path + i + '/', depth + 1) if depth == 1: self._write('\\end{multicols}\n') self._write('\n') - # Parses name of the section (capitalize) + # Parses name of the section (capitalize). def _parse_dir_name(self, name): return ' '.join(list(map(lambda x : x.capitalize(), name.split('_')))) - # Parses name of file by getting the first line of the source code. - def _parse_file_name(self, name): - with open(name) as f: - result = f.readline() - return result[4:-1] - +# Parses command line arguments and returns them. def get_args(): parser = argparse.ArgumentParser() diff --git a/notebook/header.tex b/notebook/header.tex index e03cfb0f3aaa5ca6eb93b80808364072c916e733..871d53e4afcd5d2db54528eb2bf9f4710ffa2ee2 100644 --- a/notebook/header.tex +++ b/notebook/header.tex @@ -7,6 +7,9 @@ \usepackage{multicol} \usepackage{titlesec} \usepackage{fancyhdr} +\usepackage{xcolor} +\usepackage{changepage} +\usepackage{paralist} % 'Fancy pages' adds header with page number and subsection title \pagestyle{fancy} @@ -32,20 +35,24 @@ left=5mm, right=5mm, top=20mm, - bottom=10mm, + bottom=5mm, } % Set sizes for *[sub]section -\titleformat*{\subsubsection}{\normalsize\bfseries} -\titleformat*{\subsection}{\large\bfseries} -\titleformat*{\section}{\Large\bfseries} +\titleformat*{\subsubsection}{\large\bfseries} +\titleformat*{\subsection}{\Large\bfseries} +\titleformat*{\section}{\LARGE\bfseries} + +% Set background color used in listings +\definecolor{light-gray}{gray}{0.95} % Set style for C++ code \lstdefinestyle{customcpp}{ language=C++, basicstyle=\scriptsize\ttfamily, tabsize=2, - frame=b, + backgroundcolor=\color{light-gray}, +% frame=t, breaklines=true, morekeywords={int32\_t, ll} } @@ -54,7 +61,7 @@ \lstdefinestyle{customvim}{ basicstyle=\scriptsize\ttfamily, tabsize=2, - frame=b, +% frame=t, breaklines=true, morekeywords={set} }