From 5526472285fc6cb6a6d6a7285e4999195d0cbb0f Mon Sep 17 00:00:00 2001
From: Bruno Freitas Tissei <bft15@inf.ufpr.br>
Date: Mon, 13 May 2019 18:32:40 -0300
Subject: [PATCH] [WIP] Add better Latex generator

Signed-off-by: Bruno Freitas Tissei <bft15@inf.ufpr.br>
---
 algorithms/geometry/convex_hull.cpp           |  12 +-
 algorithms/graph/centroid_decomposition.cpp   |  31 ++--
 .../2018/Round 1A/{A/solve.cpp => A.cpp}      |   0
 contests/CodeJam/2018/Round 1A/A/in           |  28 ---
 contests/CodeJam/2018/Round 2/a.out           | Bin 39160 -> 0 bytes
 gen_notebook                                  |  10 ++
 notebook/gen_latex.py                         | 168 ++++++++----------
 run                                           |  10 --
 testing.py                                    |  65 -------
 9 files changed, 103 insertions(+), 221 deletions(-)
 rename contests/CodeJam/2018/Round 1A/{A/solve.cpp => A.cpp} (100%)
 delete mode 100644 contests/CodeJam/2018/Round 1A/A/in
 delete mode 100755 contests/CodeJam/2018/Round 2/a.out
 create mode 100755 gen_notebook
 delete mode 100755 run
 delete mode 100644 testing.py

diff --git a/algorithms/geometry/convex_hull.cpp b/algorithms/geometry/convex_hull.cpp
index 3874670..33a0f2d 100644
--- a/algorithms/geometry/convex_hull.cpp
+++ b/algorithms/geometry/convex_hull.cpp
@@ -15,7 +15,7 @@ struct ConvexHull {
 
   /// Finds, among v, the points that form a convex hull
   /// @param v vector of points
-  int run(const vector<dd> &v) {
+  vector<int> run(const vector<dd> &v) {
     int k = 0;
     vector<int> ans(v.size() * 2);
 
@@ -39,13 +39,7 @@ struct ConvexHull {
 
     // The ans vector contains the indices (relative to the sorted vector!) 
     // of the points belonging to the convex hull
-    ans.resize(k);
-
-    // Remove duplicates
-    sort(all(ans));
-    ans.erase(unique(all(ans)), ans.end());
-
-    // Return number of points in the convex hull
-    return k - 1;
+    ans.resize(k - 1);
+    return ans;
   }
 };
diff --git a/algorithms/graph/centroid_decomposition.cpp b/algorithms/graph/centroid_decomposition.cpp
index d9a34c0..6952825 100644
--- a/algorithms/graph/centroid_decomposition.cpp
+++ b/algorithms/graph/centroid_decomposition.cpp
@@ -2,21 +2,24 @@
 ///
 /// Complexity (Time): O(V log V)
 /// Complexity (Space): O(V + E)
-
-// Must be a tree
-vector<int> graph[MAX];
-
+///
 /// The Centroid Decomposition of a tree is a tree where:
 ///     - Its root is the centroid of the original tree.
 ///     - 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, where lca(a,b) is the lowest common ancestor of a and b
 /// in the centroid decomposition.
+///
 ///   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.
+
+// Must be a tree
+vector<int> graph[MAX];
+
 struct CentroidDecomposition {
   vector<int> par, size, marked;
 
@@ -24,23 +27,21 @@ struct CentroidDecomposition {
   /// @param N number of vertices
   CentroidDecomposition(int N) :
     par(N), size(N), marked(N) 
-  {
-    init();
-  }
+  { init(); }
 
   void init() {
     fill(all(marked), 0);
 
     // Assuming vertices are 0-indexed
-    build(0, -1);
+    build(0);
   }
 
   /// Builds the centroid decomposition of the tree recursively.
-  /// @param x initial node
+  /// @param x initial node (root)
   /// @param p parent node
-  void build(int x, int p) {
-    int n = dfs(x, -1);
-    int centroid = get_centroid(x, -1, n);
+  void build(int x, int p = -1) {
+    int n = dfs(x);
+    int centroid = get_centroid(x, n);
 
     marked[centroid] = 1;
     par[centroid] = p;
@@ -53,7 +54,7 @@ struct CentroidDecomposition {
   /// Calculates size of every subtree (in the original tree).
   /// @param x initial node
   /// @param p parent node
-  int dfs(int x, int p) {
+  int dfs(int x, int p = -1) {
     size[x] = 1;
     for (auto i : graph[x])
       if (i != p && !marked[i])
@@ -65,9 +66,9 @@ struct CentroidDecomposition {
   /// Finds centroid by recursively searching for it in the subtree 
   /// with more than n / 2 nodes in it.
   /// @param x initial node
-  /// @param p parent node
   /// @param n size of initial subtree
-  int get_centroid(int x, int p, int n) {
+  /// @param p parent node
+  int get_centroid(int x, int n, int p = -1) {
     for (auto i : graph[x])
       if (i != p && size[i] > n / 2 && !marked[i])
         return get_centroid(i, x, n);
diff --git a/contests/CodeJam/2018/Round 1A/A/solve.cpp b/contests/CodeJam/2018/Round 1A/A.cpp
similarity index 100%
rename from contests/CodeJam/2018/Round 1A/A/solve.cpp
rename to contests/CodeJam/2018/Round 1A/A.cpp
diff --git a/contests/CodeJam/2018/Round 1A/A/in b/contests/CodeJam/2018/Round 1A/A/in
deleted file mode 100644
index 1d72390..0000000
--- a/contests/CodeJam/2018/Round 1A/A/in	
+++ /dev/null
@@ -1,28 +0,0 @@
-6
-3 6 1 1
-.@@..@
-.....@
-@.@.@@
-4 3 1 1
-@@@
-@.@
-@.@
-@@@
-4 5 1 1
-.....
-.....
-.....
-.....
-4 4 1 1
-..@@
-..@@
-@@..
-@@..
-3 4 2 2
-@.@@
-@@.@
-@.@@
-3 4 1 2
-.@.@
-@.@.
-.@.@
diff --git a/contests/CodeJam/2018/Round 2/a.out b/contests/CodeJam/2018/Round 2/a.out
deleted file mode 100755
index 0151de957bf717487cacbff8a43e59fcc27cff15..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 39160
zcmb<-^>JfjWMqH=W(GS35O0GZM8p9?F;q;1G8h;b92hJZxEUN6<QQZb*cccXSioWs
zd6;?_oxubVhtV7mE(0@E-wLQaIxPcL2cto50tta=kbNLFHeA665rxqV0uVk(A1jCn
z<-^2b^j&F?Bm)DChKYmpf$cMZ$TOhPHBj?lG_pQW*xc}e=(`bvN;`l8fPsOb1MDaU
z2ADojaDeoEfa?1I)d!;mKng(0p)@Q!L2d-$BT#X4+67`g1B?c#1qlT_ElB~fPeA>J
zPCtQ~2cto1LHYupmZX5(31Sn2p~1uu1ho%WxM)Db1xACyA7s9MPG*vsiGEIsZcb)i
zX@zcug_*9IiC%HOo)I|xi7+sL)0DekD8m)4H`AYPG<Y7DQ1RvN3fUKn+@5BG+zoOA
z$UKl5keMK>pxy)Pm1AH4r+tXOCNeQHurPqcKx!2j7#J?3p35zs#?B-<gU1;ph7IR1
zGB5~Xk!ZysJ`abu5)*cFx*4#GgW?;Ty^nC1{||@xwanPfzktKu={U?!z+wIj9O8C3
z%*nywo=_a_*@naXc{s#PahQJqhkHzLh|4oDFo4nsdejHwF#jqJb7taD4@$e(%(up2
z?=&3Y6N1CuE@lP>C3MF#Ffe#CGB5}-NHRDiLL?<X8Hj;_L7N#Ou8;r`7l4X0<YXol
zm!u?XYlHHp8AE)0dTxGRd~r!)QAvC}L%e5*Z+uE>QEGZ-aY<@Xh_7=_eqL%wVp2{j
zL=L-5RB%a7v1f3Jp<!}HVo`iaQDSCEv1hWYYfx~Bp>a}Tab|LSesM`rYGSTua!9;u
zuxWfULwuB9aAr}lYfvVbSz;a^pIlL4XlQ5z(NJ7cl$n?AnT%;{a3aX;%nH|BhIok8
zI2B=WKuCOuLA-0Qd3=z!Uob9PgH7UtP2)oh<6T|BuFKCUc7?bTWVef<YZ=&T<K)ad
zuzZO{W`1#eQettciDzDB30#4pd3=0HMp1rwd{Sacd}2;cesUQD$fJqzNvY|XdGX1K
zCCM2K@lh!`0U#s&f)OSenif~)CC8U%mSn^im!xFoyC#9+tD+*lAhoDCKQA#Sv!pV<
z%mC~Fkh7d2&cf|0oWbO5=$e}x<Q;4r4>k-}sNmBd<Q;4R(oK3&2=E3ahP-l6Y$E#~
z9Fh<}#V1!J#uuf6Ly|lfLSw`)xWp2YyfX8Pv863n<C4r&*MQ)BaQvDi=a-g1<0~~U
z1sYp9nMvu%$??UYEM&+KADUO5nU@kDlv-Sxn+nQc$sh?(-YPChOwNu^&d82WOU%rH
znv+<PT9FAeG%XVpja8`(@$osCNy*TRn46fH$KdYl9B-^=z~JuV>Es-5q-O$W8R?lq
z*bx!&#(E}tMurT|5fP3~p7Dly#>g_DywAkI%)rFJ3dSIk1<Yn*06{heh%7T$4Fdx^
z0~5HmW&o>U0jmL-0jhTy8C;nm%^*-Y7ob+j4N|`vR7r#DWhRCss642tB9fWO%fP_K
zuo)^=DwW9zYKiWJt7it+<)CsCWJBSP=}aJ7PeRpSUZ2ehYBAh^@=G))aWF72F+7Iq
zhqc#W?W+mU%Jl)XJq8n(f;LcJpos@S)pJ10N0@pT|3W;-RUjWQz}pxgksC<jVjux1
zet;w{2^9lTFObBgKmt(w0ZAO%v<1ujKoXY)i$Dkgs5?Q$IH)ZJ5oKV2mG7WtDkxrH
z;;{MvBo3<kVB!)`^Vz|11`}mqP(TugwYfmD8c5>Mpa%&v7$Av*+HPP$1_lNTByo`4
zFmVSYaY*|OBIAK14ssJjlz|}tNgNh8Ah`%6aZZo`6el2wb3w&GR0fhbH%I`A3y{Ql
zpkg4Z0!f?~Bml(?NaD~g3|OWENt_=n0wE?KiNn%3NM;6-IJ64~5@uL{Bo0lQVDS}5
z;=*7N2(bZ4TofV%CU+o-i-ScV!~rC635XDwJb@$*%_?B=QDSg}fJgHi4v%iuyZ#Ie
z9<2vTnEqezXg<Pm81A_LrjPs>82+n1@nc}%mv><JuL|O4faG63`2YX^f7M%l3=A2d
zV&mlnF#i&W56a>%4}kfnKzvZvez^h6KLp}~vh>RZVE!%;AC#3}P5|>af%u>-{IUVe
zUj^cWvhK?QFn<w<56ZGH6TtjgAU-Ioz6=2KCxQ5&Ec(&`%<ls6L0R*q0hr$e;)Al}
zO9e2$3d9Fx#g_tLei4Wd%7QN$!2B!_AC&c8e)tFSZxV<P%5pCsfca4%J}9fbya470
zf%u>-_VNIj?*-z6vewHDV7?QG4=Q3`E&%hbKzvXZdpQBjHv;iNMgPkNFkj1$fgx=I
zD8ND3@U3U(#W;`7M;^^jJ_LmL^s;hEF)(=a@-CJHQMLye7#RMGviUJEeBqaO0Sg)W
zfhbmxIUbfjN<=-nS?~EmqMP&o1Ah4ikhzDUv`4QkBUruZFOV9|e;x<_F?)1=@HqIw
z-h=U&$HjjoA|BnWTS1bo2TC~pKS%@H1JmDN%NW4Gz)-3m>d|bQ=gYvr;L-WCgvX=X
zc9t&#!wcR2|Np<p`2YX^G1i;@3=E91FnuukW%d96|3f`Gp9Xt0z5#VMQarj@R5ifn
zxV|tvupi{u7t{X!|Gy8!^60e%#qW!&fB*mY=xu%R@Be>~&SM_EwkduL3@`fs{{Mfx
z^~=Bi|3T@q8!T-J=JWU8W(S2z>l?TZP`JN{1)Jl#z@zi{3qwu@hHi+0<P#pfp$j~E
zTR}<6qw^d{+KUrp07R)0Cj-OrR#5tYI0~w+RpbBv{~p~Cs`L1Zy&x@}t_?^+pCCdD
zAm+O^cywL^8LrO7z|eA_B*LQ?By{{mF&8KxTR|z<qZ>kjy;%zi)D?d~woC;}_JUmj
zHN}sMfuWnB6CwmPiIa<g;q^q1Ueir7Aotr!`!F!PxCSzz^H4W9Y&ws5bY6eq3=Rp?
z$skpo$6ss#set$&67ZeJUr2zBZ#__=0tu$(7mOas7vP};_Q)4dATqQbC}rOPii6jz
zJ3t}Sa-c-Zqu10DWO%Rb3~vU87r}r2|KA77wjl4f{rUfYH%Q@2F*cAZA)&m09Wz2e
zWdJlnc7kIRqI4oVC_;Yx`~M$g3fy^}t$+T3k_0GcgCrXFf>_U)85sEcdl^BdgS1$K
zRq^*$!9_5<B@6Wy|NH|j2l!k17(mvs{D)ZwG6h4=OAb(MShj+c@y|KXa-hV#dn!m}
zH&}@A0z?PIN8rHQ&H;+`L*1<)Rh>-D5OuHTLj)koAt@59yaQ|jBUp7e*bf*=Qo%}E
z4?x}B19mqD+})ti!O&v})??WUQU-CiDa3Sbun<H&lB*eEt_GO~ay3XJ<LiYGO%UZs
zuD%3{RR&G4dz)K9@xk~q<=_AR6Fhn$ad{COudSfc8k9Cp{rdkO5}_W+A3S=eg2j7X
z4|sH5+@%LDCyu|^_7kKAlpn!rd_mdk04y&-)5!slVYNTO<p$V{&f_oMfw>TC%TTRV
zW(6e=aB%@D4Pe$TfF?d0R!};HJ5mtLg&4#SO2VCoVcyxn%D}J-l=wV4?}40f1DsTO
z;Bf$QwPh=a&)-|i2ufF=dI_Wf;%m!R5TCy{6r4IiY;cf*>;k8PCN>6!Zi#NNDzHo|
zQrx71BpECZgX6y>9Z3~jzY|!ANAitsup_`mfC?e7;q{<Efw(*9=l}o581%6j@gEdc
z0?n@&I|W`YVgQ93rZaDY)ZlXFK9D5Hnc!@agw2lGU?n)5c>^5e;NV^T1LVvYY(_+Y
zj1Xu(#Mmj&3=S^FmoxwU|KAMuH{;8~fB*j<Ykdx?J&w1Ez~cv$1T4Y)+JJ5_4GE$J
z&_b69WU2&`408BCWdWA~hxw<1@;^Joc!p-MF^sPlHS7gh$H3om860Y$qyR4F%iI_k
zUTpl1R6?eF2PIrkytG<CDj6`<dHls6P}1vcl|U8M1BVDCeZuk#L=B|EiDCm+ICUPq
zP|@Qr7K61M@&M;8aO~@U16z6kQpG-WWng$w^9{*S=i&0lUnqmwaKp^l7#Lo+di0vQ
zih(kU?GljYcx26!z#2fw@c4@WCXgbK?~cDHVF9tBfq49dDH8+3ZctSMuV;?GP-J3Y
zX#UOE46eQyUkd;D{~uh<cy#-|NbxY{0k<FcTdp%OFuXhqE+XK$5!7<^=)3{Sh>0Kv
zAo8gnBLl<BR=8?#apCv%|Nqy_9w0@KpzJ*UV%Jx2pn#hUPRtApuN_e3*%%oZUMqmb
zK!w!t7n}$~Aihmv1o;r++cstp8}3_okY=cbkTUc53uBOSh?CcS{r~@kC&&SfM?j6G
z=-9)cwv$Km8-dQ+Kb@sNnrr_smKrtI{s7fXrJA6I5hy9Sfwc6BvV$9lrh#q@3?ALA
zFP%ZP&G8pAzx@9{;Uw6geIRZ7L81L($^ZZVp{94%{_yB5{ov8<`T<pB0+ieQM!*B4
zsN3}iC}49~7#Jp;JUjvBG-SCLB)MRZ<~JH1owYAKI!hmTbcWvW=yrYK(G8+~A3)35
z5KwC94t)TYf+XFyEDQ{<r9c4;Qr>y|MIT5FB!GIq{QvLKd_)5&V32M923C2<1LV+d
z4-N>;0JZ8lND?H|dHjVn#F<bZD1aP^+%WxNc)+7O^o2*S>j!8la0R0IgGaaT4|ozR
zVSO>@^Z);lu=QwugWVk07aqL<97tw$;4muyZWbuyBtVV=ha5B*^1<39Ji1*UfMOv5
z%w_Pf1Qk9W%||3)VFHV(ZU&Fu02Xi<bP9kdXlx?nkpv*||DzkE@IyC)<)K<OP<nU`
z)*lOvYmiQ;LXU0+kM7V99tR&Wc`#mp8ibZk&M@OnCwq|OK)yvyC!M|*zzL!|^nyn>
zJgsa1<t1410S5}W;qHo_UY>!}LDEa?C%ow;2o#2$IMRzVND`V}CPSQylwQDDrZe=7
zM{no{k6uv502irt|Nj4PIZ&bo5jy^&3)~+$)b0AFld0MD4I@lE=->bUuMfj>5!R4p
zMGjf)X$vKdg2EIOY3OP6#|P5WXaOh;yInET`x>}epjg95qv2p}@HFZH<`PPy3ZTU4
zfisOl%9+mE9}|$$A)Jkt<}!YR3p=nLkPA`M6)4ew5)h=I*#WARP|Ke8OlW1#3{bTT
zNlStsaHpm208qyH0m>DchdeqjcpUt}<N-@qka7sp%X|U06O>$zzp(j_a4V>Y2bW~9
z{MC8<1*De@O`QxL-M$~7CD{#-AyCsh12|ApQMc<4cy0ux8E`uF=nMrFyr3ff2ed%j
z%ftXG#K9>Vk@`M(fJ=ZM9-RX45C+L2OeHcNIQ}5~MkpR4K;A)(hkiWq(D{y}cwogE
z4;^4TvBm>hs6o^~;^H7UrGksT7arZEA3)`BF~}s8$bg3_BGe#t1FpD8Br`5xX&;<s
zLXl$^)T#oz^*E@b!2n@8fJWJ1Y|w}oC;@<T3To;@F-Z{Fd(cD<p*jN~2^$<7(3${}
zSUUp*;As-w=gqYr7)r#!4g%G%h(vvx5s@I#HGygxa7hd<WA8IEFu?0vNXrB>1RkRp
zhfCF2P}>V+GR5Jv5@ZrA89)LEmX*-MiPeLVf^aHE@fd1i?eu*BZnuC!733>OnUhaU
zcy*!}iz~cl<4^^TRZ(cH!rDxr-Y#^22p(Oi?uDfQgj-8cEC8tnw;qqV{%7<+Eh2Ie
zz5<m{ouwb(B^K^{0U8v7wuMpBJXZIE!i`k-r=hst0N#e{47~yM!wqnY22>M4VkaEc
zAIN0}QY^Us@UV9MP$CTu;?CnQ&VcKs<1dzjl3law4~5saVg5pd2Dl(X2@GFwApsq(
z0JokR!Pdh{0Z@P=l~SPQ@9`HEFTiCv)HIM1aGanun2)=D0hKi#y`f*we3$?V6ZA$&
z@(WO-1Y$2~F7_ns;$zR@E(TRT79O3oH#|B^FL-o@p77{)z2VX6`og2R_5wqR7Py_+
zdHh8+q@m`~?Ro;#9qzpT!Vny^xfd8cnq6Ngygm<7`Pvv%<X?XV8lVMLsUV}kWzxJq
z|Np;O{~R=2efY(3Fb(d6-T^V2k66GO=djoSr}*P9&OU=X6xx444t;QMO9bQ$OV<zl
z(?LTFtS`L4mb-rNIQW1G<d|R2KmmyqIT$8919y54LP`culpgcwJpbYz15zmpic}1J
zpb2*mB%3ch1$i56Gb_mE287L^7=))>$56)*P_Tnqhmc_JcD(@7aPj~D|DK&kJ-TCW
zcy!*|51M~|QS}idcEqRiolocU7jvKf|NmMNq^9#8h@bcI|9_v(7a+}(K>h}Ga~xwF
zW06{d9y>tOI{*Lww}-ZSP~3u?0YNd}&Cu!k1=59b{o&DE`-1^Af#Uk2JM>GZfJbxg
z4{&U=ynX_TZEUu%#~x18<Ckv%rFDk1369~Oo!1@1JUhQRhB|isbqw+8RShs?U<mc-
z)r~M@U<mfnd<vSAdy)L)|9_8zf0;|94R7<yGx&7=^6C8M()r%;zsMbr=EIC0mUl~E
zf#&L>V?iEtjB|`X%rDOXnz;k%2g!igU~5N-(GVC7fzc4a5(112ps9L@1dIh5?*p+x
zlk}i20I2B?Dtkd|`oWXM$O@qAeDJCV8IMB`Xkh@z9?${+(4;?Tq90@@XhI(}8wi@X
z2Tj&P%k2NoiN&c3$_!Qt44%FL{=vbXPCl++<E5FcL2J~b85kHM?*IR9z|6pK<H7&`
z5zGt>FCP5=4_e@T_Tm5k7nm6sIA8z&AH&DM5cK;0{~A69hV<9}|AWRaDqsKqKY^Kn
zq2u-c|38=+7?!;L|6hWIf#JaG|Nkvm7#Nh^{QnOcMN510|9=Y$1H-yE|Nk#xVPN?6
z=KudAEDQ{0Z~y;)!ot81_V)jO7FGs^^tb>2tFSUKOnCeMzY8k^!-lv2|EI7rFr0b&
z|9=ZB1H+5A|Nk#xWnc(;_y7MHRtAP?@BaV)z{<ez>fQhU0&ENnT<`z?H(+C62zvkj
ze*hZ;!@T$Z{}-?^Fx-0o|NjIw28Lhn|Nq~>#=yYy;s5^&Yzzz%AO8RUz{bF!^5Oq~
z0d@ukhY$b%8?ZAl%=_^Fe*`-N!<!HP|JSfHFc^IN|9=iU1B2bi|Nr-}GcaU){Qv(B
zI|D=8$N&HTurn}B`S}083<m?lf{*|I+i);2toiu=e+&l$!-<do|JQIZFsOa{|9=Sw
z14GHD|Nl>LFfi=-^#A`04hDu(pZ@>n;ACL<^6CG74Ne9Iq0j&SdvG!^D183^KZBEj
zA?x%1{~eqR3`aiy|G$Ehf#K)p|Nl>LGB7B8`Tzd~Xde8_|Nk6Z3=EUL{Qs}P#lY|e
zG<eI!z@Yf`|Njgw28N)o|NnPzF)&no{r`Uj7X!n*umAs_;9_972pR?FVqp0H_5Xhk
zZUzR8Z~y;ma5FGifClur85rWe{r{iA&A>46+yDO^+zbr+zy1Hef}4Ti!?*wcPjE9Z
z{QLI*{|jyg2D9(~|8wv#Ft~pI|6hZLfuR62$HK$FF!}rc{~0_C3@^U_|KGvG!0`S1
z|Nkp^7#Ng({QrLfr2fbM|1WqL7%u<#|6hQYf#Kbc|Njkm85j(H{{J7q%fOKF^Z)+>
zUIvC$KmY%qz{|j}<LCeX8+aKQlz#pHe}|WW!R*)n|9^NH7+ik+|1ZPGz|isQ|9=}k
z28I>C{{LUV$H2hx`~UwJpcN?$3=E)!BjEI26~w?;A;2ij!_F~*kzD{J4q9LJ;O_tb
z+8_l`3=#)18Bx?TFsLvvFo4u6-1+~%0hBlS1l;%}y!g4xIT{%3rL47#Rlv)^LHa>^
zMk?<9{}0NSAhSRiq!+a0@%{7v|3Qmg7##To+L)Yq*?f7}LFz#AH4F?451;@44_Z6}
zm-j-*gUn&93h)8@gnf3aHUon+#6J-Cf!z4@?*IQbpp~8S+zfCtJerxA^*O-?f$Vt#
z+DG&J|9|j0N0>Xpz|vqpvM@3*wBV2j*#VjbZ+QOye-da<(qArwJ+95nOc4-sK;_>S
z1_p**&;S1ig$K)1Bz5%=H6XVXFfuUQ0=3~mo`boC$r-EwBtL<Xfr078|Nr3aJ#cw<
zxcml21_r$s|Nq+{>vwHtF5+S50O`NL$iU$B;{Sh;d*I;_4b~3!>j$VjXh9NO-UlHM
z+COCd;{Sip_!L||86j`L#K7Q!$9&Mt97rBlSQjucFgU!x9v7gn{=vw=VDsYt|13~g
zFXcoH>ja29Kz>tTVqmCy0S)V3By~t(eTRvGVcv`X|AUdkipdXb2q>)nFflM(!s8bi
zW{A88ihe{~*)TIO{K6AgG0Y4MYA<oeRSh!(gVRggaWw}jk1MV~<MSpj|NjTof$+F;
z1A7k~*LRp17!>fx|6yie;CYEVE?Srw7&u=3{~rg63tbM>xCnvR1B#0^%nS^6FaQ4s
zt>$78L{i7(0agSG>kJkKhK!g0|ARM1!P0ddSQ_kB&>U9J%m4qu#TZQ96CuBXg@K{!
z<^TU$$Z?U1kUzn~z|ivY|9|kBWte_w-UQkIf`x&h36J?4tPBhVc*079m4P7!kGuzH
zRvk}RUSMHhaDj#8M>d>c`2*@ta9CbNQil|lTUZ$wmc0D`A6L4(0%}9x@#`1R3KKkG
zDZ<9Ua0E|Sny@i29KvIM2pa>#hL`{Udm_gblM6VqKygt5YNNdT|34B%9+IFy@>AFt
z7(`zE|8I&cUjWt)PAgm37#K8P{r|6tET4jqzrx1AVD#$$e>G(JM1=eoHU<WZSGe6L
z!p^{u^a{88OxPJ1=HPK(2s;DA##jIU8zS4EgRsAZoq^#H9`{XQXJ9yiM}7-C1H-vj
z|Nk2!o1cd;{|Y+;!^2nq|LY;kXCmakurn~c#}j@c91ILUUg55nO*j}BUf^+G2nPeh
zJ3Q_y;b353e2v?EQ#cqH_+R4=zbzaL3<|Gtmlany7#R3KZE|G)7bE!})JA=c+kYaQ
z3=E>LahEkFpf>C4|NoVd&5uKvAHvDNp#1v({}5z(CV#L3Q2H+6WMGKEWB(LR1_pOL
z_HW^Y^i8nY52`~!?V-@u|Nnzl9kPJ7wZO_l*Jfs>7O*qG`RETP1H<mu*vo&AJ7u^S
z7`DCs|KADOAGHYmHe3u0H}HgW3>O2#2R!;~xEL6O-e8YMQ2T=g)WLi6|9>W^{&~)b
zC^J2KnR{58S(%X9HK2CB-JAdaLG4j^T?h$suwP$rF)$e6unXi@P`^Oo4et60)L(GH
zW4;GB1H;lg*vk}99SQ1RoV)Y?KWHI0+<gI%umlA!sLj{|s>t8`{~rqyaN-l_XL99}
z=wo)}Q|M)J<<sb4_24sTWAos%Xl8fkbI9VeaO5*^<kN8CQ*h#waN-ki;^P2s6TiaE
zz##DkvZxtk6bS$S&*-EO$H1_Jk@bN9!#bwxj1z<ywz9DP5@0yM!8%`%;VuVjpCH2~
zPS*W`3`@9wFh3DwSj8`NS&-p5zt9swhOYvk^|}B5GxDgjGB8-NIx>W@GBAMb0Eua{
zGB7x?dNRZz#5l}YZ5e`a@EI8X&lY9mwPg)q%;G9xXkugq?eK!Slf#bHl_3(;;Rgwf
z;?WQo4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@RpfChr=QY62XMml@0GjFm8I4YZ&YnOP
z2c0zm;)CWMK{UAI#lXM-+9(X-Ux7}tz|LZTofiQf7YCis1yaPozyLdw0d_tFs4ohV
z0?m<t=&%3&=Ywbt&_pN$=!6OokAVR+-v?rW=0riX1yml?Wd`xzL;0XCC5R8(a}Vx+
zf&`!#s*HgFx(^>TPYaULfHJ`SX$H_q8z4~z2H2kd0I0`7^RXZq38+OdcUwRM5HwE<
zmIo0Gh_ftU>VE%+_>Yl+0W9<n$_LHkfwcUG@?q}$0OdPCJ^B;M2h9<K)KeS7&Q(J<
z*9<i2&A`Cm2BpKGbQ+W{gVJqKdK#2o2Bo(_>0?m(8kBwprN2RGHt^s-1A`cpR)f-J
zP}&Vjhe7EyC|w4n+o1F`D2?t9V)?LhNnq;Tot>=|G(wX~^GZq;EcA@^40O#(!8}7v
z2p^^rHw`+01$M3<vMSJdF`)Cxki|f3&?zyX_3j`xGG=CAVSwciRB=`YSiV3NXM^V-
zRB?6&Sh_+L=U{-PM^tf623WdB73X4r<quSGZpZ;P$b#T=>3A3vpz)0?#mvCVumDTE
zF*EQnz|LPpRnN}=D|b-E1sLGx5+X@3GYB%k&htYOW?*IzV%Pv4Tt*gUU|?ntW;kJw
zDhA>)Gl($2$~O=nhM5^e8DQlaObkRbGl(%@%U8^x(gj)$fz-h;GlK*J1N8hEm>7s=
zW{`xRKLg^!Ff+VVg^55$msl7+g137kL>U-B#TXL<AHxH*a0bmofy4#Clh+6xiVUDr
zfcO|-^#x4E9K6m&k|6>#NepH~WZb}P%y7tsnggqcAgUP{D#7Y8!*d2`3>1s|=YiD=
zFmQklJp!{KChY{X1sFKd#Lq#+xzNOKgT*BoBGKIc3M?+bzynneD`y26L18MuAOIDI
z7WWLwP;o&taWkm65Sq9LR9plq4l_R;DlUO0-VPO)K@$fpmuF-UU{F94KLu5<f+qeR
zDz1Sh&c_7tmkydZXx<xSz5$xJFI2q=ns_!;+yYI!3o34dCcY6W?tmtK6Dsb4CeFwV
zai<5GxF%HG2TeQ>Djt9)UI`TsK@$hfJ%jukfhK+wsy+ry`~y@x0Zm+*1>(*WG;tTG
zcm|qyCR98JO?(nmyZ}vnA5^>qP5c>DyaG*}2Rza&z)*uGZVVM~KogIKinpMNH$ufb
z(8QNR#e2}i&qBo~poxEjicdikmtlj1+YB^u(C&Lsyv#up&w;96fF?d2D!v3wd@odd
z1ymf|_+nsSc+3VV-!4KMs^B?X1_lOUc8EBvy$owdg7Q7Ka#fuj<bENBBUtJSZ0b$H
z4N1)UXt6xVUd(#a18hEKJrW2uM+BqZNrH-_*HfinbHw58Ur6c6z|hSOI`5K?;RSe-
zje!9c4tt^EZ$Ohe3=9m=U}AU;6;A_CIx{f9s!uTvh&kK9lhq6i;JGvg1_l?Xc%(YS
zM(|uM0|UbvsQ5pqICyOo0|NtSPE(12k0A%zL4eu&5UTzG)IHE<I0Gwa-5diS!!f8i
z77%L~(xKu4st^H~zs^C$ub`O&I)4Ua?+2*AVD3@mg7|9+^Z;C#dlI4I6=>oMxj;=H
z2?hzYdK|P)4`e<Ycr_UV19*K0XeR;G90sWSq1H3-azpHW1q}z#ycx(RYEbbGs5rD5
zV{n0r8$b<)g}<dN=sZ@;cEwVt`aRHi2d^gq_0xDj=b0kfQLuVS6SU5cfsdgC>V8-_
z^zdLmCwCK6{Vk~Zpmqkx{p!5f)w_b$0W$D0=s_I<Uh~1gz>tJP{Y0>Okcp^xEe`d+
z!Rq-KBB1dFjeZ6ZK1etRK*JN}FC})6JNX!<Lfb{4xn__}ict0F=~E9Xo(5_-F)%QI
z*0q4t`$5Ig<12@cfkBW-f&sn1Q3+K)8=8+`?l}k*e+8N_W?*1|1}lRaKg9j$>AV*z
zjvl{E0uc2)(0)63oe~2BLxupzzaST*;szYzr=aE-K+^*>+88(lv6~Yi$iSe;B*6eX
zUlCRgmk2`KgI>-of{Oouh65~LAB2kAKm!1lPSk`T=14&gVT9$EugVMzLQI(bg%YUx
zGN{AB>kt_j82W{<yZ<CqeGh2i0RsaAc+Cz21H%uf_&=yQuykc43~>*7{`H26H$d|#
zXwDxL;)|i;=;h2~sQ3<O`2fpDMj{aN(aY@=sQ3nGItQ&U1ew1FD!v7pK4J0x3M$?X
zH6Of|2b6wAA?6>1`WG4v46UNr!)HDYabYotIq#t91ePx{#IT!VD+>}w^!uR6l%WQP
z`hz&cuR!gc0JRsiwht5zdg2iG?1$zfXf!bNi-YV1sX)amq3UCx=D_M5P*)99o}-tC
z$r9Mjsh5D*y9k;<pcKOgs5pB0^H%~=KA_hloRSc8(90Q3s5l2SeqsLggNmcqFOwv(
zyYnhky%99t!E4tT7#P^3Aoi+3(+RBJPlJlbLGvAW4Jrcz!v?7MOKANIOIJ$L5Oa#4
z0S`;h-B9r@Q1!6<^-&sBA0hg`u=BM+i-1AlKM7h6K#gOFlYy9@1`S~F`e6nJhWk))
z^zdPkg{c1l4L6v3%w-|<IC_6PmK`K6$&di6c%jL~1!@j@`7;SB{t6nNu=;%!RNN1m
zu3+}QfQr9@dI&ZyDIy1P=LTrHg|$!eq2hAT{0{5huad(azek|z(aUWnd5HP?P;;Qx
zFi6Nl{EMCrRiNt8+dnB#aR;bJp%g=jJa+fY1dH=A6hJdNcuf!k1H($FInhvufY+EY
zFfe?9it9t`YiRY%@CPdX4;pT;@RU%1`0F^-A+U1H6)G+T6^Bv`6BMw!a}5shvruy`
zLDN61K9X02*eeB1hp_r3A1aRC?wt-5KLo8uVCnXuB6jzH(km$aqo;>pC5XKl&~ybW
zuU096+JVr-ibNfQst<sMKP<heg6d5qbugwa4)Jhhh`mwJ{0l2L_Cm#Zq45Zf9){Oo
zbNCo8K<x$fuRwPEhN?%eF9K8`=A)Ox%c0`v<vgP*q}+g=&kQ;h3S_>xD#V;k(D;Hz
z4?`+c+yd%OXtBaD6)KM2U)Tv1N3UlE)v(8xff~f#Lr@E0`E-#Q_ITL{Rga#J4noBp
zq3Iu14xGYa&J(D5UTDGxt(63YLy|hgJu{&RAJ#9M3Kd81XYEwS?k{Eyh&e6L0E6Yb
zY^XSTIy|I--5iGGqLSj0(zG<aWCp~&2=OJk@yVc@5sDe&<5TkE({u8Z5_95HO7e?}
z;}c6O7?SgI3vyCRQd9KIEzOLvD~eCc%*%{VEGkN@j8DxgDXL^hD@x2wjZZ1f&8=jJ
zk4NIgXXa&=peS|JOD-q?A5rgPXjzb%nw(mmS)3Z5oS#=*QdF8;0+lib-#Cz1l3x^`
zSd<PCG|NoS%P&fWa4h2EGxI^FgHF}AjE_&xD+S%c;A3PMAD@z%mROoo5}%WwoE=|~
zpOcwf=?c+hXpoYcmRbasfr=QG6jjET<Rc3iB&OsSK(vEQ4=yn@ElN#Kt$?^PF|VZ9
z$22oJu{afEsvkCKv%LJ`(xhUX@)r38C7HRIRk%$sPtMQDNi4ywz|g?e+1D{RxhS)s
z1gAZw;41@gN?W8>l%(dRq^96hVVqc=jZ@Mjy(qN+r>tozUTH(4cu?F_=H=&RCg$KY
z#n3nxbkPJXP6?{Z%P)yf$|r0dNL?zC>XP!yiLy5pk2*_;Hxl!}NfB$JF*Jdw0XZ$N
zGzX6#%peMr^YcnF^GfqeaVIoGsM3O>)Ux=*vcyb0rkbSX7v(0F5DsbssKR1A3C9p-
zT3&v9a()3GUz<ZsOUo=OE{V_2%fX}8IJKxKzbKwy-Y|r!E2%8NlY@*Ps#1%S6Y(j7
zTAGxYoL!WfhC3xdElny)OvasO456wD5{pvvh%yV02TULyNJ>lrS&By?)Y78FymZ2<
ziVG5x@u)I|TUwM_keZ0Q@G&%lsD#uh6`3V?A{OdE@Vz6@P_Y0N<RyujIX;G#@xk$#
zd1Z+?nJJ))MoLoSGr>iciD5jLpP3A<XfhLXGOH3xGV}A|6Z2ByQ&J&S3W#rznaL3E
z?&I&|=o24bT$&W`84tdzBtG6P$kEp|-qp_qbc;~DyI*L$s|Qrj!zG9z-X+q{(bv<N
zAs%c6ye>;Y6#(Bu1h>K8%`Mn9BtFE^$;TCRwG1e`8^wpECWGoT&|N#8nZb#knXaye
zaM8@%f*fZf*C6j;0}^z&7=iEe!EL@_yf5VP9#B;RzNZFJR~j1UrIy2F^NTz)T`i!s
zZmMf;fH(A3A44;!U_ShQq~JtPGOp@zb#(<*zfjXsU4w$n;sb(B;|aP75-f(0U;zai
z%-8t50#g%QVrUfa0!j(_m7o@mr%#fBtE(j_Z55Xk<yU$Jkmr@MkoaIrh?77zAjd5^
z1_md32AjrXBnU%Lf-nPHgU_>&yN045$pF=}hNzy+bae%}9C}?6nehk@TQc=KgHvs4
zN@7VOxDjRniy+T{%uKNR4C8}>6FouKU4a{5<l7VE9c&5?zTgtGGI0KbWj(~bN@x<!
zMy|Q=Y=}G5$%$nw84Sq+^Z58YPz{_DpIMSx1Zw+|mpBn#4K|AhB`mXeS65eOa9T14
zU6tk!zLhI4zO*<s1suM#OTo}k4lcoVpO}LK_=+gVWl$i8c+)L3OhBbDsO$t^(1moP
znS%q;jZ~nU-q6#HDOfQ`D=5FgZ%@N==NX#!z&52pug!wW#T)5??!*GyL+UkhkO(!2
zhZ+S5MbMR6VAIeNHT2FoKXA1J$$wE04m5@!We0LG2CbqH@@Pgn8^ZHRd`fYCd`4nk
z3h1`IsNfPrh9)bQlm&!<^DI(oK&z_AG8U!w2?#cW)I8t{0@>f>m<`HhSc-3OeU4Fl
z(>R}lEd}NCsNfPqgZTKg%$%I~y!b@VfXv)XS3jgcHH?o>%>!ML7@wKu8BtsWy09=l
zKC?K!I5{yVvB(p2i=cUYd|6^nX{u{TysKG!Jh(v}YzDfC5O!}K>@q}@bO_4LIPWOL
zc^e-nt)UnLP0mPe#uj*)h!PK)XkAg-4CLGj2)$Jh!!<79dPS*edhzk;*sn80FG`^f
zLT%`Q{0Xl4%pj2iiJFl3U_(g2hCmxT@Un-ZG-(m<3rPf^;Sz8gITf69(JMwuEP*!(
z;7*2m+&DEa1y)!Rd4VBHm_rg0BKSb%HmnLaG>!*d`U!7Q24teQC5cQe1qCoCqLpz_
zZ-FzCGi->8tj4bwxFzE13M$)N3j9N$t$Z?DHt+;wXc!-#n37VIT3no;MwY`|1480K
zO>w*djoM8Cw<Mq*fX6o_sRvq>n8pWr2SbWWj2vwQ>dC+c_K*`YI3F1ql;$A>Qy|Gb
zkG$qnE~p_M5+7`ioEL*jjLhTXQ7wVF241$pGcc&_Y8dZ|a&IOyRl{q1@O7g&OF}AK
z{|dDbtzCeYlPHNbXyyQ20E=Q5I7UdlRyV*q8QqY)@?3Nw%vK5|9)Py=VJVK9JzYdk
z8kD!d#ZoZnrdv?P#qbnT^+t_$4!n7XUKddkR)};18mWLpJ!tGD8F5W4)L-BmU*n^Y
z8yeV(VX_<pFKv)}Ht^CLG&TU~3de`|I>W|vK+SZ7>yhgZh%a!<L(>Peq$9JahBVW`
zbuBo{gBn@HUp5U5Q%EMpTSS}3`^G01r6!i7#uu057bT{rf^V6oZjLbomBR4)7L=@m
zOH4BJOA<W^MK_i<nk%HQ4=!iHWrmRndJzk09)a4f<RlkRNsdvNg9jFjK!tNua0zJa
zxjeBb#S`C^+BgeoS6Ba#_#jXSn-!(z=9i_$7lCG%QuC5iJ%cUcT}{BPWvsDAj(6al
z3}dur4|EVMxCDIbGkTIi?v9Z)*aZqg(4dhy%AgFQ(8^0CucAfN@yNN^H3<|K@u2Yn
z^wAK=1?aB9?%>`bM#l}>;)FIPpt%;k41_8&w2b$SPfsn04=F&5fPxx<@t{#DP{CFN
znu_#8xRH_=1C{#V6prW^2S5@(q@hn}+yhJIfe&Cr`625@t3NVbEpihp;)_8ujo|TI
zM698Y{*vQAq(LQAXJ9Mvv3MdS6&&P9cch~azaY7nNHZbjEjV0*ON?_9D?Bq@gS<oH
zgN;ClAwE8-xELvZ$uHHx;RzW}0XK-Di4r~{1iu9yEknkG?@LcEE(K30KuQOEjY~sM
zpCm(9S3?U};Ru_ci_Zh~8(m#P;)9JrZB>T&sJ!yr0Fb-Dc_Tg#G>#Y#uJHmgLCT<^
zVq^+43ep<{O_e}q%poSi+Og<KmaHTKDLJ4`Vfa<_sPT-YGmWYMR7b<QX5_d6R&=5c
z-ciFuME@2ksbb_pq(q5SQGyCiEV+V+63`Kn*z$9VT{F>=7fQnm%^~Cj9dsxKJfMW+
zcB&K~kaE#81k{T!N=?r!E=es4@pT3*PzeEzOMx;6p3;ph@1PWjp?T$*c`5Nhsl}za
zsSXbA&d%}1dIlhC!L4;rV-h2H!Fh{n1BQ5-ZCEGXGF_1-5rTpZK!ccw5(Ts}2kd(E
zYLA?tf@K;=EKxsQ8G;IbP|ikcom1jgXyp&?(gl|oCuinii9c%Od)R<FzFdzw;EXXi
zg_b!pK{*XncvGp-;S8C_f)A=dQVDpX8a($64H)=<1WG#sTV+dDykPCILF@hW-26O9
zRScSYht5YpMs7jn8)#r57&KoM;v0{vbO<gnGD5G+Ae{!tM6V&ds-tjB$UGig(OQBk
z+8}TE04?@01JKOAK}ssTqXf#Qn1hoT@ej*rqz{~fQX@1zAzel2z&UlxDqL-5suvB2
zjyY;;3KT#n-eh3VE3V8fNlaqUD=sO5&>1jRW?o5ZQ2~QqUVcfcUV2`sUQ%ghPKs`3
z3RK9^$y2u^F`WS{myuYU!JwB?nO9ty3!zJjATnjCMa7x<c_^ItA_l#p)SN_+1}Li_
zr-VTdGzQ6_SCCVpm!4n3pjVPwQNo}HE|m3(@<BZd2EEh_=mN=%lp+L=K`%WyIX<-_
zIkli9z64zNfenMKH-VS|W2aQ+CFW)(Gw4AKOe!vB&`ZwG%}vcK0j)%(41@MZfz}Q~
zkMUrDowER=q0409mVng4InaGnpe>Uy{jl>GU^H~uK3ofIKO9WJ40>h=Oh4@01{e)p
z?h8}SfUY03PwCtL|M@Weu=5>YG<4f41MHYc*uE*4fqo1O44^gMF#WJ|AYilv^gt2N
z`6(d3!}P<>NeKg=%K+MY3NaCO-U^I{ov#9s1?_c(u^=>Pp9$#f5}5t4b0uIjY#$=b
z{V;VfI-7xk0dy7$j1N110!B}OSi=BvKgcUE_d|sls=((3Alwf-rvgU9&S!zy57Q6x
zKj=OpP@KTr2|LdMM#IjB0qF;w34^X5w4NFit|0e;-2^+|0!oAQfW@H%$Sx=oOm%|K
z9bf?a4<rCP9|J~%?<4?8Krz%<*fBf|Q_%Fo&e4F;F!w^WLk^!|fF44_z`!sUO+W0s
z4H&HmJGcjG0L*?UmtirQe%QGjFq#vl5K5!_e<f5uEdJr=cR&;VQK&u`h3=n?X!>F2
ze86bXT_`ZUAR68N{b>4O=Yhaz3DChAAdOIrZvRO%{jhUGU^M8i1gKUpg>FCSJPOd7
zc~II0DS++Uz5(4Zf*#&5`(gBR1_lPu9srnr*f}IGp!#9zKxTt5j1QwfGeFWFOh4?r
zk`GY*pnDQP`e5lBrVr*W(0Lu8^bgYyJ70;xAEXN!I8Y{tg6W6Rf1pa>`eFN~13;=7
zK-=sf3@8cH2jwy_K@U`d=~sa2mw@VbfF~@74)pSv9eh3p=CLs_{m^X<5Y14xf;b>Q
z!)P=sK*9_TF#Dke0H_`U?QMd&A6EW=@(0ZAV2x0sAsxba4&9Fe;bE4)pnW9R^ru4$
KPS}1qT>1e)Rr2!y

diff --git a/gen_notebook b/gen_notebook
new file mode 100755
index 0000000..7f12fa6
--- /dev/null
+++ b/gen_notebook
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+#tex_file=$(mktemp)
+python3 notebook/gen_latex.py # --header=notebook/header.tex --output=$tex_file
+
+#pdflatex $tex_file -output-directory . && 
+#pdflatex $tex_file -output-directory .
+
+#mv tmp.pdf caderno.pdf
+#rm tmp*
diff --git a/notebook/gen_latex.py b/notebook/gen_latex.py
index ef9134f..1bdd850 100644
--- a/notebook/gen_latex.py
+++ b/notebook/gen_latex.py
@@ -1,96 +1,76 @@
-import os
-import sys
-import subprocess
-import argparse
-
 from pathlib import Path
 
-dirs = [
-    'algorithms',
-    'misc',
-    'contests',
-    'problems'
-]
-
-parser = argparse.ArgumentParser()
-parser.add_argument('--header', action='store', type=str, help='The text to parse.')
-parser.add_argument('--output', action='store', type=str, help='The text to parse.')
-args = parser.parse_args()
-
-output = open(args.output, 'w')
-
-# Read Latex header
-with open(args.header) as f:
-    data = f.readlines()
-
-# Print header to output
-for i in data:
-    output.write(i)
-
-last_sections = [None] * 2
-
-for di in dirs: 
-    path_list = Path(di).glob('**/*.cpp')
-
-    for path in path_list:
-        file_name = str(path)
-        sections = file_name.replace('_', '\_').split('/')
-
-        # Sections[0] is [algorithms, contests, problems, misc] (sections)
-        if sections[0] != last_sections[0]:
-            output.write('\\newpage\n')
-            output.write('\\section{' + sections[0].capitalize() + '}\n')
-
-        # Sections[1] is name of constest or category of algorithm (subsections)
-        if sections[1] != last_sections[1]:
-            output.write('\\subsection{' + sections[1].capitalize() + '}\n')
-
-        # Parse source code
-        with open(file_name) as f:
-            source = f.readlines()
-
-        # Separate into comment and code, and define title
-        title = ""
-        in_comment = False
-        code, comment = [], []
-        for line in source:
-            if '/**' == line[0:3]:
-                in_comment = True
-
-            if in_comment:
-                if len(title) == 0 and len(comment) == 1:
-                    title = line[3:]
-                comment.append(line)
-            else:
-                code.append(line)
-
-            if '*/' in line:
-                in_comment = False
-
-        if len(sections) > 2:
-            output.write('\\subsubsection{' + title + '}\n')
-
-        in_complexity = 0
-        ctime, cspace = [], []
-        for line in comment:
-            if 'Complexity (time)' in line:
-                in_complexity = 1
-            if 'Complexity (space)' in line:
-                in_complexity = 2
-
-            if in_complexity:
-                ctime.append(line)
-
-
-        # Remove first \n after header comment
-        code = code[1:]
-
-        #output.write('\\lstinputlisting[style=customcpp]{' + file_name + '}\n')
-        output.write('\\begin{lstlisting}[style=customcpp]\n')
-        for i in code:
-            output.write(i)
-        output.write('\\end{lstlisting}\n')
-        output.write('\\\n')
-        last_sections = sections
-
-output.write('\\end{document}')
+class Tree:
+
+    # Constructor.
+    # @param dirs list of directories to build Latex over
+    def __init__(self, dirs):
+        self.dirs = dirs;
+        self.tree = {}
+        self.build()
+
+    # Sorts the lists on tree leaves.
+    def sort(self, sub):
+        if type(sub) == list:
+            return sorted(sub)
+        else:
+            for i in sub:
+                sub[i] = self.sort(sub[i])
+            return sub
+
+    # Builds a tree represented as dict, with structure of files
+    # and directories.
+    def build(self):
+        for di in self.dirs:
+            path_list = Path(di).glob('**/*.cpp')
+
+            for path in path_list:
+                branch = str(path).split('/')
+                curr = self.tree
+
+                for i in branch[:-2]:
+                    if not i in curr:
+                        curr[i] = {}
+                    curr = curr[i]
+
+                if not branch[-2] in curr:
+                    curr[branch[-2]] = []
+                curr[branch[-2]].append(str(branch[-1]))
+
+        self.tree = self.sort(self.tree)
+
+    def __getitem__(self, arg):
+        return self.tree[arg]
+
+    def __iter__(self):
+        return iter(self.tree)
+
+
+class LatexGenerator:
+    def __init__(self, tree):
+        self.tree = tree
+        self.hierarchy = ['chapter'] + [i*'sub' + 'section' for i in range(3)]
+        self.gen_latex(tree, 0)
+
+    # Prints elements in arr in Latex format.
+    def gen_code_latex(self, content, depth):
+        print('\\' + self.hierarchy[depth] + '{' + content + '}')
+
+    # Generates Latex for entire tree recursively
+    def gen_latex(self, sub, depth):
+        if type(sub) == list:
+            for i in sub:
+                self.gen_code_latex(i, depth)
+        else:
+            for i in sub:
+                self.gen_code_latex(i, depth)
+                self.gen_latex(sub[i], depth + 1)
+
+
+def main():
+    dirs = [ 'algorithms', 'misc' ]
+    tree = Tree(dirs)
+    tex = LatexGenerator(tree)
+
+if __name__ == "__main__":
+    main()
diff --git a/run b/run
deleted file mode 100755
index 99c4c76..0000000
--- a/run
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-tex_file=$(mktemp)
-python3 notebook/gen_latex.py --header=notebook/header.tex --output=$tex_file
-
-pdflatex $tex_file -output-directory . && 
-pdflatex $tex_file -output-directory .
-
-mv tmp.pdf caderno.pdf
-rm tmp*
diff --git a/testing.py b/testing.py
deleted file mode 100644
index 1280b7f..0000000
--- a/testing.py
+++ /dev/null
@@ -1,65 +0,0 @@
-from pathlib import Path
-
-dirs = [
-    'algorithms',
-    'misc',
-    'contests',
-    'problems'
-]
-
-# Returns a tree represented as dict, with structure of files
-# and directories
-def get_file_tree():
-    tree = {}
-    for di in dirs:
-        path_list = Path(di).glob('**/*.cpp')
-
-        for path in path_list:
-            branch = str(path).split('/')
-
-            curr = tree
-            for i in branch[:-2]:
-                if not i in curr:
-                    curr[i] = {}
-                curr = curr[i]
-
-            if not branch[-2] in curr:
-                curr[branch[-2]] = []
-            curr[branch[-2]].append(str(branch[-1]))
-
-    return tree
-
-# Print elements in arr in Latex format
-def gen_code_latex(arr, depth):
-    for i in arr:
-        print('\\' + depth + '{' + i + '}')
-
-# Generate Latex from tree
-def gen_latex(tree):
-    stack = [ (tree, 0) ]
-    depth = ['chapter', 'section', 'subsection']
-
-    while len(stack) != 0:
-        x, h = stack.pop()
-        print(x)
-        #if type(x) == list:
-        #    gen_code_latex(x, depth[h])
-
-        #print('\\' + depth[h] + '{' + i + '}')
-        for i in x:
-            stack.append((x[i], h + 1))
-    
-
-
-tree = get_file_tree()
-for i in tree:
-    print(i)
-    for j in tree[i]:
-        print('\t' + j)
-        if type(tree[i]) != list:
-            for k in tree[i][j]:
-                print('\t\t' + k)
-            print()
-    print()
-#print(tree)
-#gen_latex(tree)
-- 
GitLab