Hello!
After seeing the recent hype towards debugging utils and code snippets usage and what not, and due to the fact that I had 30 minutes of free time to spend this afternoon, I decided to write a small Python script that pre-compiles multiple files into one big file for Codeforces submission.
The tool is here: https://pastebin.com/c4dS4Pik (Python 3 required)
Basically the tool does these steps:
- remove the
#include <bla>
lines from the code - run the GCC preprocessor on the code
- add the
#include <bla>
lines back - run some cleanup routine (optional)
In order to use this script, copy it somewhere (preferably in your PATH directory), and run it using: /path/to/scr.py file.cpp [ARGS]
The ARGS
are similar to the ones you would give to your g++
command.
For example, let's say we have three files:
FILE: debug.hpp#pragma once
#ifdef DEBUG
int recur_depth = 0;
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
template<typename Ostream, typename Cont>
typename std::enable_if<std::is_same<Ostream,std::ostream>::value, Ostream&>::type
operator<<(Ostream& os, const Cont& v){
os<<"[";
bool first = true;
for(auto& x:v){
if (!first)
os << ", ";
os << x;
first = false;
}
return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os, const std::pair<Ts...>& p){
return os<<"{"<<p.first<<", "<<p.second<<"}";
}
#else
#define dbg(x)
#endif
FILE: dsu.hpp#pragma once
using namespace std;
struct DSU {
vector<int> link;
DSU(int n) : link(n, -1) {}
int Find(int x) {
if (link[x] == -1) return x;
return link[x] = Find(link[x]);
}
void Union(int a, int b) {
a = Find(a); b = Find(b);
if (a != b) link[a] = b;
}
};
FILE: sol.cpp#include <bits/stdc++.h>
#include "debug.hpp"
#include "dsu.hpp"
using namespace std;
int main() {
int n; cin >> n;
DSU dsu(n);
dbg(dsu.link);
return 0;
}
Output of /path/to/scr.py sol.cpp
:
OUTPUT#include <bits/stdc++.h>
using namespace std;
struct DSU {
vector<int> link;
DSU(int n) : link(n, -1) {}
int Find(int x) {
if (link[x] == -1) return x;
return link[x] = Find(link[x]);
}
void Union(int a, int b) {
a = Find(a); b = Find(b);
if (a != b) link[a] = b;
}
};
int main() {
int n; cin >> n;
DSU dsu(n);
return 0;
}
Output of /path/to/scr.py sol.cpp -DDEBUG
:
OUTPUT#include <bits/stdc++.h>
int recur_depth = 0;
template<typename Ostream, typename Cont>
typename std::enable_if<std::is_same<Ostream,std::ostream>::value, Ostream&>::type
operator<<(Ostream& os, const Cont& v){
os<<"[";
bool first = true;
for(auto& x:v){
if (!first)
os << ", ";
os << x;
first = false;
}
return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os, const std::pair<Ts...>& p){
return os<<"{"<<p.first<<", "<<p.second<<"}";
}
using namespace std;
struct DSU {
vector<int> link;
DSU(int n) : link(n, -1) {}
int Find(int x) {
if (link[x] == -1) return x;
return link[x] = Find(link[x]);
}
void Union(int a, int b) {
a = Find(a); b = Find(b);
if (a != b) link[a] = b;
}
};
int main() {
int n; cin >> n;
DSU dsu(n);
{++recur_depth; auto x_=dsu.link; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<9<<"\t"<<"dsu.link"<<" = "<<x_<<"\e[39m"<<endl;};
return 0;
}
The main idea is that it merges all your #include "bla"
files (not the #include <bla>
ones, though), and replaces all the #define
s and other preprocessor instructions.
Let me know what you think! The tool should work fine in UNIX-based systems (Mac OS X, Linux). I would be happy if someone could test/port this tool for Windows. I think one cool thing about this tool is that it pre-compiles all the #define
s, so that most of the output code would look more standardized (C++-ish).
I would personally probably not use this tool too much, as my general approach is to copy-paste implementations and tweak them to the specific problem, but I know a lot of people prefer to use them as black boxes, so this might be useful.