Automatic pre-compiler for submitting tasks on Codeforces
Difference between en4 and en5, changed 16 character(s)
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/
CR0mJXbRc4dS4Pik (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:↵

<spoiler summary="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↵
```↵
</spoiler>↵

<spoiler summary="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;↵
  }↵
};↵
```↵
</spoiler>↵

<spoiler summary="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;↵
}↵
```↵
</spoiler>↵

Output of ``/path/to/scr.py sol.cpp``:↵

<spoiler summary="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;↵
}↵
```↵
</spoiler>↵

Output of ``/path/to/scr.py sol.cpp -DDEBUG``:↵

<spoiler summary="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;↵
}↵
```↵
</spoiler>↵

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.↵


History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en5 English bicsi 2020-06-29 17:26:03 16 Script now shouldn't discard comments.
en4 English bicsi 2020-06-29 16:59:46 27 Tiny change: 'e code\n- precompile the code\' -> 'e code\n- run the GCC preprocessor on the code\'
en3 English bicsi 2020-06-29 16:59:04 2 Tiny change: 'e steps:\n- remove' -> 'e steps:\n\n- remove'
en2 English bicsi 2020-06-29 16:58:34 18 Tiny change: 'tebin.com/4icsFNWP (Python 3' -> 'tebin.com/CR0mJXbR (Python 3'
en1 English bicsi 2020-06-29 16:52:36 4693 Initial revision (published)