diff --git a/src/stats.cpp b/src/stats.cpp
index 90ec6e4a443f50adfd90cf2956f8889e00ae298e..4455455e9c15e16e56339e10e776e43594c70f9f 100644
--- a/src/stats.cpp
+++ b/src/stats.cpp
@@ -1,5 +1,7 @@
 #include <mealy.hpp>
 #include <read_mealy.hpp>
+#include <reachability.hpp>
+#include <transfer_sequences.hpp>
 
 #include <algorithm>
 #include <fstream>
@@ -8,8 +10,47 @@
 
 using namespace std;
 
-static void print_stats_for_machine(string filename){
-	const auto machine = [&]{
+template <typename C, typename S>
+void print_quantiles(C const & container, S && selector, ostream & out) {
+	const auto index_weight = [&](double p) -> pair<size_t, double> {
+		auto index = (p * (container.size() - 1));
+		return {floor(index), 1 - fmod(index, 1)};
+	};
+
+	auto sorted_container = container;
+	sort(sorted_container.begin(), sorted_container.end(),
+	     [&](auto const & l, auto const & r) { return selector(l) < selector(r); });
+	out << "min/Q1/Q2/Q3/max ";
+	out << selector(sorted_container.front()) << '/';
+
+	const auto i25 = index_weight(0.25);
+	out << i25.second * selector(sorted_container[i25.first])
+	           + (1 - i25.second) * selector(sorted_container[i25.first + 1])
+	    << '/';
+
+	const auto i50 = index_weight(0.50);
+	out << i50.second * selector(sorted_container[i50.first])
+	           + (1 - i50.second) * selector(sorted_container[i50.first + 1])
+	    << '/';
+
+	const auto i75 = index_weight(0.75);
+	out << i75.second * selector(sorted_container[i75.first])
+	           + (1 - i75.second) * selector(sorted_container[i75.first + 1])
+	    << '/';
+
+	out << selector(sorted_container.back());
+}
+
+static auto count_self_loops(mealy const & m) {
+	vector<long> ret(m.graph_size);
+	for(state s = 0; s < m.graph_size; ++s){
+		ret[s] = count_if(m.graph[s].begin(), m.graph[s].end(), [=](auto e){ return e.to == s; });
+	}
+	return ret;
+}
+
+static void print_stats_for_machine(string filename) {
+	const auto machine = [&] {
 		if (filename.find(".txt") != string::npos) {
 			return read_mealy_from_txt(filename);
 		} else if (filename.find(".dot") != string::npos) {
@@ -23,11 +64,24 @@ static void print_stats_for_machine(string filename){
 	cout << "machine " << filename << " has\n";
 	cout << '\t' << machine.graph_size << " states\n";
 	cout << '\t' << machine.input_size << " inputs\n";
-	cout << '\t' << machine.output_size << " outputs\n";
+	cout << '\t' << machine.output_size << " outputs" << endl;
+
+	const auto reachable_machine = reachable_submachine(machine, 0);
+	cout << '\t' << reachable_machine.graph_size << " reachable states" << endl;
+
+	auto prefixes = create_transfer_sequences(reachable_machine, 0);
+	cout << "prefixes ";
+	print_quantiles(prefixes, [](auto const & l){ return l.size(); }, cout);
+	cout << endl;
+
+	auto self_loop_counts = count_self_loops(reachable_machine);
+	cout << "self loops ";
+	print_quantiles(self_loop_counts, [](auto const & l){ return l; }, cout);
+	cout << endl;
 }
 
-int main(int argc, char *argv[]){
-	if(argc != 2) {
+int main(int argc, char * argv[]) {
+	if (argc != 2) {
 		cerr << "usages: stats <filename>" << endl;
 		return 1;
 	}