2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
29#include <initializer_list>
43#include <unordered_map>
44#include <unordered_set>
51
52
53
54
59using u128 =
unsigned __int128;
63
64
66inline void throw_assertion_error(
const std::string &condition,
67 const std::string &msg,
const char *file,
69 throw std::runtime_error(
"tgen: " + msg +
" (assertion `" + condition +
70 "` failed at " + file +
":" +
71 std::to_string(line) +
")");
73inline void throw_assertion_error(
const std::string &condition,
74 const char *file,
int line) {
75 throw std::runtime_error(
"tgen: assertion `" + condition +
"` failed at " +
76 std::string(file) +
":" + std::to_string(line));
78inline std::runtime_error error(
const std::string &msg) {
79 return std::runtime_error(
"tgen: " + msg);
81inline std::runtime_error contradiction_error(
const std::string &type,
82 const std::string &msg =
"") {
84 std::string error_msg =
85 type +
": invalid " + type +
" (contradictory restrictions)";
87 error_msg +=
": " + msg;
88 return error(error_msg);
90inline std::runtime_error
91complex_restrictions_error(
const std::string &type,
92 const std::string &msg =
"") {
94 std::string error_msg =
95 type +
": cannot represent " + type +
" (complex restrictions)";
97 error_msg +=
": " + msg;
98 return error(error_msg);
100inline void tgen_ensure_against_bug(
bool cond,
const std::string &msg =
"") {
102 std::string error_msg;
104 error_msg =
"tgen: " + msg +
"\n";
105 error_msg +=
"tgen: THERE IS A BUG IN TGEN; PLEASE CONTACT MAINTAINERS";
106 throw std::runtime_error(error_msg);
111#define tgen_ensure(cond, ...)
113 tgen::detail::throw_assertion_error(#cond, ##__VA_ARGS__, __FILE__,
117inline bool registered =
false;
118inline void ensure_registered() {
120 "tgen was not registered! You should call "
121 "tgen::register_gen(argc, argv) before running tgen functions");
127template <
typename T,
typename =
void>
struct is_container : std::false_type {};
129struct is_container<T,
130 std::void_t<
typename std::remove_reference_t<T>::value_type,
131 decltype(std::begin(std::declval<T>())),
132 decltype(std::end(std::declval<T>()))>>
135template <
typename Char,
typename Traits,
typename Alloc>
136struct is_container<std::basic_string<Char, Traits, Alloc>> : std::false_type {
138template <
typename Char,
typename Traits,
typename Alloc>
139struct is_container<
const std::basic_string<Char, Traits, Alloc>>
140 : std::false_type {};
141template <
typename Char,
typename Traits,
typename Alloc>
142struct is_container<std::basic_string<Char, Traits, Alloc> &>
143 : std::false_type {};
144template <
typename Char,
typename Traits,
typename Alloc>
145struct is_container<
const std::basic_string<Char, Traits, Alloc> &>
146 : std::false_type {};
149template <
typename T>
struct is_pair : std::false_type {};
150template <
typename A,
typename B>
151struct is_pair<std::pair<A, B>> : std::true_type {};
153template <
typename T>
struct is_tuple : std::false_type {};
154template <
typename... Ts>
155struct is_tuple<std::tuple<Ts...>> : std::true_type {};
159 : std::bool_constant<!is_container<T>::value
and !is_tuple<T>::value
and
160 !is_pair<T>::value> {};
163struct is_container_multiline
164 : std::bool_constant<is_container<T>::value
and
165 !is_scalar<
typename std::remove_cv_t<
166 std::remove_reference_t<T>>::value_type>::value> {
169template <
typename T>
struct is_pair_multiline : std::false_type {};
170template <
typename A,
typename B>
171struct is_pair_multiline<std::pair<A, B>>
172 : std::bool_constant<!is_scalar<A>::value
or !is_scalar<B>::value> {};
174template <
typename Tuple>
struct is_tuple_multiline : std::false_type {};
175template <
typename... Ts>
176struct is_tuple_multiline<std::tuple<Ts...>>
177 : std::bool_constant<(!is_scalar<Ts>::value
or ...)> {};
180template <
typename>
inline constexpr bool dependent_false_v =
false;
183
184
187using is_sequential_tag =
void;
190template <
typename T,
typename =
void>
191struct is_associative_container : std::false_type {};
193struct is_associative_container<
194 T, std::void_t<
typename T::key_type,
typename T::key_compare>>
198template <
typename T,
typename =
void>
199struct is_sequential : std::false_type {};
202 T, std::void_t<
typename std::decay_t<T>::tgen_is_sequential_tag>>
206
207
210inline std::mt19937 rng;
213
214
219 bool IsCont = detail::is_container<std::decay_t<T>>::value>
220struct print_cols_view;
223template <
typename T>
struct print_cols_view<T,
true> {
225 decltype(std::begin(std::declval<
const T &>())) it;
227 print_cols_view(
const T &v) : value(v), it(v.begin()) {}
229 std::size_t size()
const {
return value.size(); }
230 decltype(
auto) get(std::size_t)
const {
return *it; }
231 void advance() { ++it; }
235template <
typename T>
struct print_cols_view<T,
false> {
238 print_cols_view(
const T &v) : value(v) {}
240 std::size_t size()
const {
return value.size(); }
241 decltype(
auto) get(std::size_t i)
const {
return value[i]; }
246
247
251constexpr int distinct_attempt_multiplier = 84;
256template <
typename Seen,
typename Fn>
257auto try_generate_distinct(Seen &seen, Fn &&next,
bool insert =
true)
258 -> std::optional<std::invoke_result_t<Fn &>> {
259 using T = std::invoke_result_t<Fn &>;
261 distinct_attempt_multiplier * std::max<size_t>(1, seen.size());
262 for (size_t i = 0; i < attempts; ++i) {
265 if (seen.insert(val).second)
267 }
else if (seen.count(val) == 0)
276
277
280enum class compiler_kind { gcc, clang, unknown };
288 compiler_value(compiler_kind kind = compiler_kind::unknown,
int major = 0,
290 : kind_(kind), major_(major), minor_(minor) {}
299 cpp_value(std::optional<
int> version = std::nullopt)
300 : version_(version ? *version : 0) {
302 tgen_ensure(*version == 17
or *version == 20
or *version == 23,
303 "unsupported C++ version (use 17, 20, 23)");
314
315
318template <
typename T>
struct list;
321template <
typename Func,
typename... Args>
struct distinct {
323 std::tuple<Args...> args_;
328 : func_(std::move(func)), args_(std::move(args)...) {}
350 auto val = generate_distinct(
true);
354 throw detail::error(
"distinct: no more distinct values");
356 template <
typename U>
auto gen(std::initializer_list<U> il) {
357 return gen(std::vector<U>(il));
363 for (
int i = 0; i < size; ++i)
364 res.push_back(gen());
366 return typename list<T>::value(res);
372 bool empty() {
return generate_distinct(
false) == std::nullopt; }
378 auto val = generate_distinct(
true);
384 return typename list<T>::value(res);
388 friend std::ostream &operator<<(std::ostream &out,
const distinct &) {
390 detail::dependent_false_v<
distinct>,
391 "distinct: cannot print a distinct generator. Maybe you forgot to "
399 auto generate_distinct(
bool insert) {
400 return detail::try_generate_distinct(
401 seen_, [&] {
return std::apply(func_, args_); }, insert);
404template <
typename Func,
typename... Args>
405distinct(Func, Args...) ->
distinct<Func, Args...>;
409 const Gen &self()
const {
return *
static_cast<
const Gen *>(
this); }
411 template <
typename... Args>
auto gen_list(
int size, Args &&...args)
const {
412 std::vector<
typename Gen::value> res;
414 for (
int i = 0; i < size; ++i)
415 res.push_back(
static_cast<
const Gen *>(
this)->gen(
416 std::forward<Args>(args)...));
418 return typename list<
typename Gen::value>::value(res);
422 template <
typename Pred,
typename... Args>
423 auto gen_until(Pred predicate,
int max_tries, Args &&...args)
const {
424 for (
int i = 0; i < max_tries; ++i) {
425 typename Gen::value val =
static_cast<
const Gen *>(
this)->gen(
426 std::forward<Args>(args)...);
432 throw detail::error(
"could not generate value matching predicate");
434 template <
typename Pred,
typename T,
typename... Args>
435 auto gen_until(Pred predicate,
int max_tries, std::initializer_list<T> il,
436 Args &&...args)
const {
437 return gen_until(predicate, max_tries, std::vector<T>(il),
438 std::forward<Args>(args)...);
442 template <
typename... Args>
auto distinct(Args &&...args)
const {
444 [self = self()](
auto &&...inner_args)
mutable ->
decltype(
auto) {
446 std::forward<
decltype(inner_args)>(inner_args)...);
448 std::forward<Args>(args)...);
450 template <
typename T,
typename... Args>
451 auto distinct(std::initializer_list<T> il, Args &&...args)
const {
452 return distinct(std::vector<T>(il), std::forward<Args>(args)...);
456 friend std::ostream &operator<<(std::ostream &out,
const gen_base &) {
457 static_assert(detail::dependent_false_v<
gen_base>,
458 "gen_base: cannot print a generator. Maybe you forgot to "
466 const Val &self()
const {
return *
static_cast<
const Val *>(
this); }
469 return self().to_std() < rhs.to_std();
477struct is_generator_value
478 : std::is_base_of<gen_value_base<std::decay_t<T>>, std::decay_t<T>> {};
483
484
490 template <
typename T>
print(
const T &val,
char sep =
' ') {
491 std::ostringstream oss;
492 write(oss, val, sep);
495 template <
typename T>
496 print(
const std::initializer_list<T> &il,
char sep =
' ') {
497 std::ostringstream oss;
498 write(oss, std::vector<T>(il), sep);
501 template <
typename T>
502 print(
const std::initializer_list<std::initializer_list<T>> &il,
504 std::ostringstream oss;
505 std::vector<std::vector<T>> mat;
506 for (
const auto &i : il)
508 write(oss, mat, sep);
512 template <
typename T>
void write(std::ostream &os,
const T &val,
char sep) {
513 if constexpr (detail::is_pair<T>::value) {
514 if constexpr (detail::is_pair_multiline<T>::value) {
515 write(os, val.first, sep);
517 write(os, val.second, sep);
520 write(os, val.first,
' ');
522 write(os, val.second,
' ');
524 }
else if constexpr (detail::is_tuple<T>::value)
525 write_tuple(os, val, sep);
526 else if constexpr (detail::is_container<T>::value)
527 write_container(os, val, sep);
528 else if constexpr (std::is_same_v<T, detail::i128>
or
529 std::is_same_v<T, detail::u128>)
530 write_128_number(os, val);
536 template <
typename T>
void write_128_number(std::ostream &os, T num) {
537 static const long long BASE = 1e18;
545 write_128_number(os, num / BASE);
546 os << std::setw(18) << std::setfill(
'0')
547 <<
static_cast<
long long>(num % BASE);
549 os <<
static_cast<
long long>(num);
552 template <
typename C>
553 void write_container(std::ostream &os,
const C &container,
char sep) {
556 for (
const auto &e : container) {
558 os << (detail::is_container_multiline<C>::value ?
'\n' : sep);
560 write(os, e, detail::is_container_multiline<C>::value ? sep :
' ');
565 template <
typename Tuple, size_t... I>
566 void write_tuple_impl(std::ostream &os,
const Tuple &tp,
char sep,
567 std::index_sequence<I...>) {
569 ((os << (first ? (first =
false,
"")
570 : (detail::is_tuple_multiline<Tuple>::value
572 : std::string(1, sep))),
573 write(os, std::get<I>(tp),
574 detail::is_tuple_multiline<Tuple>::value ? sep :
' ')),
577 template <
typename T>
578 void write_tuple(std::ostream &os,
const T &tp,
char sep) {
579 write_tuple_impl(os, tp, sep,
580 std::make_index_sequence<std::tuple_size<T>::value>{});
583 friend std::ostream &operator<<(std::ostream &out,
const print &pr) {
590 template <
typename T>
592 template <
typename T>
593 println(
const std::initializer_list<T> &il,
char sep =
' ')
595 template <
typename T>
596 println(
const std::initializer_list<std::initializer_list<T>> &il,
600 friend std::ostream &operator<<(std::ostream &out,
const println &pr) {
601 return out << pr.s_ <<
'\n';
619 ((detail::is_container<std::decay_t<Args>>::value
or
620 detail::is_sequential<std::decay_t<Args>>::value)
and
622 "print_cols: arguments must be containers or sequential generator "
624 std::ostringstream oss;
629 void write(std::ostream &os,
const Args &...args) {
630 auto views = std::apply(
631 [](
const Args &...inner_args) {
632 return std::make_tuple(
633 detail::print_cols_view<
decltype(inner_args)>{
636 std::forward_as_tuple(args...));
638 const std::size_t n = std::get<0>(views).size();
640 auto check = [&](
const auto &v) {
641 tgen_ensure(v.size() == n,
"print_cols: sizes should be the same");
643 std::apply([&](
const auto &...v) { (check(v), ...); }, views);
645 for (std::size_t i = 0; i < n; ++i) {
649 [&](
const auto &...v) {
650 ((os << (first ?
"" :
" ") <<
print(v.get(i)),
658 std::apply([](
auto &...v) { (v.advance(), ...); }, views);
662 friend std::ostream &operator<<(std::ostream &out,
const print_cols &pr) {
668
669
679using uniform_int_t = std::conditional_t<
680 (
sizeof(T) >=
sizeof(
short)), T,
681 std::conditional_t<std::is_signed_v<T>,
int,
unsigned int>>;
687template <
typename T> T
next(T right) {
688 detail::ensure_registered();
689 if constexpr (std::is_integral_v<T>) {
690 tgen_ensure(right >= 1,
"value for `next` must be valid");
691 return static_cast<T>(
692 std::uniform_int_distribution<detail::uniform_int_t<T>>(
694 static_cast<detail::uniform_int_t<T>>(right) - 1)(detail::rng));
695 }
else if constexpr (std::is_floating_point_v<T>) {
696 tgen_ensure(right >= 0,
"value for `next` must be valid");
697 return std::uniform_real_distribution<T>(0, right)(detail::rng);
699 throw detail::error(
"invalid type for next (" +
700 std::string(
typeid(T).name()) +
")");
708template <
typename T> T
next(T left, T right) {
709 detail::ensure_registered();
710 tgen_ensure(left <= right,
"range for `next` must be valid");
711 if constexpr (std::is_integral_v<T>)
712 return static_cast<T>(
713 std::uniform_int_distribution<detail::uniform_int_t<T>>(
714 static_cast<detail::uniform_int_t<T>>(left),
715 static_cast<detail::uniform_int_t<T>>(right))(detail::rng));
716 else if constexpr (std::is_floating_point_v<T>)
717 return std::uniform_real_distribution<T>(left, right)(detail::rng);
719 throw detail::error(
"invalid type for next (" +
720 std::string(
typeid(T).name()) +
")");
745template <
typename T> T
wnext(T right,
int w) {
748 T val = next<T>(right);
749 for (
int i = 0; i < w; ++i)
750 val = std::max(val, next<T>(right));
751 for (
int i = 0; i < -w; ++i)
752 val = std::min(val, next<T>(right));
757 double x, r = next<
double>(0, 1);
760 x = std::pow(r, 1.0 / (w + 1));
762 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
770template <
typename T> T
wnext(T left, T right,
int w) {
773 T val = next<T>(left, right);
774 for (
int i = 0; i < w; ++i)
775 val = std::max(val, next<T>(left, right));
776 for (
int i = 0; i < -w; ++i)
777 val = std::min(val, next<T>(left, right));
782 double x, r = next<
double>(0, 1);
785 x = std::pow(r, 1.0 / (w + 1));
787 x = 1.0 - std::pow(r, 1.0 / (-w + 1));
790 return left + T(x * (right - left));
797inline u128 next128(u128 total) {
798 tgen_ensure(total > 0,
"next128: total must be positive");
801 u128 limit = (u128(-1) / total) * total;
805 u128 r = (u128(next<uint64_t>(0, std::numeric_limits<uint64_t>::max()))
807 next<uint64_t>(0, std::numeric_limits<uint64_t>::max());
825 static_assert(std::is_arithmetic_v<T>,
826 "weighted_sampler requires an arithmetic weight type");
834 std::vector<storage_t> weight_;
835 std::vector<
int> alias_;
842 : n_(distribution.size()),
alias_(
n_) {
844 "weighted_sampler: distribution must be non-empty");
845 for (
const auto &w : distribution)
847 "weighted_sampler: distribution must be non-negative");
849 total_ = std::accumulate(distribution.begin(), distribution.end(),
852 std::queue<
int> big, small;
853 for (
int i = 0; i < n_; ++i) {
854 weight_.push_back(storage_t(n_) * storage_t(distribution[i]));
855 if (weight_[i] < total_)
861 while (!small.empty()
and !big.empty()) {
862 int s = small.front();
869 weight_[b] -= total_ - weight_[s];
870 if (weight_[b] < total_)
876 detail::tgen_ensure_against_bug(
877 small.empty(),
"weighted_sampler: small must be empty");
881 while (!big.empty()) {
884 if constexpr (std::is_integral_v<T>) {
885 detail::tgen_ensure_against_bug(
886 weight_[b] == total_,
887 "weighted_sampler: weight of big element must be total");
892 weighted_sampler(
const std::initializer_list<T> &distribution)
893 : weighted_sampler(std::vector<T>(distribution)) {}
897 static detail::u128 sample_below(detail::u128 total) {
898 return detail::next128(total);
900 static double sample_below(
double total) {
901 return tgen::next<
double>(0, total);
908 int i = tgen::next<
int>(0, n_ - 1);
909 return sample_below(total_) < weight_[i] ? i : alias_[i];
924size_t next_by_distribution(
const std::initializer_list<T> &distribution) {
925 return next_by_distribution(std::vector<T>(distribution));
933 const std::vector<T> &distribution) {
934 tgen_ensure(distribution.size() > 0,
"distribution must be non-empty");
935 tgen_ensure(k >= 0,
"number of elements to choose must be non-negative");
938 std::vector<
int> res;
939 for (
int i = 0; i < k; ++i)
940 res.push_back(am.next());
945many_by_distribution(
int k,
const std::initializer_list<T> &distribution) {
946 return many_by_distribution(k, std::vector<T>(distribution));
951template <
typename It>
void shuffle(It first, It last) {
955 for (It i = first + 1; i != last; ++i)
956 std::iter_swap(i, first + next(0,
static_cast<
int>(i - first)));
961template <
typename C> [[nodiscard]]
auto shuffled(
const C &container) {
962 if constexpr (detail::is_associative_container<C>::value) {
963 std::vector<
typename C::value_type> vec(container.begin(),
965 shuffle(vec.begin(), vec.end());
968 auto new_container = container;
969 shuffle(new_container.begin(), new_container.end());
970 return new_container;
974[[nodiscard]] std::vector<T> shuffled(
const std::initializer_list<T> &il) {
975 return shuffled(std::vector<T>(il));
981 int size = std::distance(first, last);
982 tgen_ensure(size > 0,
"cannot pick from empty range");
984 std::advance(it, next(0, size - 1));
991 return pick(container.begin(), container.end());
993template <
typename T> T pick(
const std::initializer_list<T> &il) {
994 return pick(std::vector<T>(il));
999template <
typename C,
typename T>
1001 std::vector<T> distribution) {
1002 tgen_ensure(container.size() == distribution.size(),
1003 "container and distribution must have the same size");
1004 auto it = container.begin();
1005 std::advance(it, next_by_distribution(distribution));
1008template <
typename C,
typename T>
1009typename C::value_type
1010pick_by_distribution(
const C &container,
1011 const std::initializer_list<T> &distribution) {
1012 return pick_by_distribution(container, std::vector<T>(distribution));
1014template <
typename T,
typename U>
1015T pick_by_distribution(
const std::initializer_list<T> &il,
1016 const std::vector<U> &distribution) {
1017 return pick_by_distribution(std::vector<T>(il), distribution);
1019template <
typename T,
typename U>
1020T pick_by_distribution(
const std::initializer_list<T> &il,
1021 const std::initializer_list<U> &distribution) {
1022 return pick_by_distribution(std::vector<T>(il),
1023 std::vector<U>(distribution));
1028template <
typename C> C
choose(
const C &container,
int k) {
1029 tgen_ensure(0 < k
and k <=
static_cast<
int>(container.size()),
1030 "number of elements to choose must be valid");
1031 std::vector<
typename C::value_type> new_vec;
1033 int need = k, left = container.size();
1034 for (
auto cur_it = container.begin(); cur_it != container.end(); ++cur_it) {
1035 if (next(1, left--) <= need) {
1036 new_container.insert(new_container.end(), *cur_it);
1040 return new_container;
1042template <
typename T>
1043std::vector<T> choose(
const std::initializer_list<T> &il,
int k) {
1044 return choose(std::vector<T>(il), k);
1053 std::unordered_map<T, T> virtual_list_;
1056 static constexpr size_t array_pool_max =
size_t{1} << 23;
1060 : left_(left), right_(right), num_available_(right - left + 1) {}
1063 T
size()
const {
return num_available_; }
1072 T i = next<T>(0,
size() - 1);
1075 auto vi_it = virtual_list_.find(i);
1076 T vi = vi_it == virtual_list_.end() ? i : vi_it->second;
1077 auto vj_it = virtual_list_.find(j);
1078 T vj = vj_it == virtual_list_.end() ? j : vj_it->second;
1079 virtual_list_[i] = vj;
1090 tgen_ensure(count >= 0,
"distinct_range: size must be nonnegative");
1092 "distinct_range: no more values to generate");
1094 size_t range_size = right_ - left_ + 1;
1095 size_t sample_count = count;
1098 if (sample_count > 0) {
1099 if (range_size <= array_pool_max)
1100 res = sample_from_pool(sample_count, range_size);
1101 else if (sample_count * 2 > range_size)
1102 res = sample_complement(sample_count, range_size);
1104 res = sample_sparse(sample_count);
1107 num_available_ -= count;
1108 virtual_list_.clear();
1109 return typename list<T>::value(res);
1119 std::vector<T> sample_from_pool(size_t count, size_t range_size) {
1120 std::vector<T> pool(range_size);
1121 std::iota(pool.begin(), pool.end(), left_);
1122 for (size_t i = 0; i < count; ++i) {
1123 size_t j = next<size_t>(i, range_size - 1);
1124 std::swap(pool[i], pool[j]);
1132 std::vector<T> sample_complement(size_t count, size_t range_size) {
1133 size_t exclude_count = range_size - count;
1134 std::unordered_set<T> excluded;
1135 excluded.reserve(exclude_count * 2);
1137 if (exclude_count <= array_pool_max) {
1138 for (T value : sample_from_pool(exclude_count, range_size))
1139 excluded.insert(value);
1141 for (T value : sample_sparse(exclude_count))
1142 excluded.insert(value);
1147 for (T value = left_; value <= right_; ++value) {
1148 if (!excluded.count(value))
1149 res.push_back(value);
1151 detail::tgen_ensure_against_bug(
1152 res.size() == count,
"distinct_range: complement sampling failed");
1158 std::vector<T> sample_sparse(size_t count) {
1159 std::unordered_map<T, T> local_virtual;
1160 local_virtual.reserve(count * 2);
1161 T remaining = range_span();
1164 for (size_t step = 0; step < count; ++step) {
1165 T i = next<T>(0, remaining - 1);
1166 T j = remaining - 1;
1168 auto vi_it = local_virtual.find(i);
1169 T vi = vi_it == local_virtual.end() ? i : vi_it->second;
1170 auto vj_it = local_virtual.find(j);
1171 T vj = vj_it == local_virtual.end() ? j : vj_it->second;
1172 local_virtual[i] = vj;
1174 res.push_back(vi + left_);
1182 T range_span() {
return right_ - left_ + 1; }
1187 std::vector<T> list_;
1188 distinct_range<size_t> idx_;
1191 template <
typename C>
1195 distinct_container(
const std::initializer_list<T> &il)
1196 : distinct_container(std::vector<T>(il)) {}
1203 T
gen() {
return list_[idx_.gen()]; }
1209 for (
int i = 0; i < size; ++i)
1210 res.push_back(
gen());
1211 return typename list<T>::value(res);
1219 res.push_back(
gen());
1220 return typename list<T>::value(res);
1223template <
typename C>
1227
1228
1229
1230
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1248
1249
1253 detail::cpp = detail::cpp_value(version);
1257
1258
1262 return {compiler_kind::gcc, major, minor};
1267 return {compiler_kind::clang, major, minor};
1272 detail::compiler.kind_ = compiler.kind_;
1273 detail::compiler.major_ = compiler.major_;
1274 detail::compiler.minor_ = compiler.minor_;
1281inline bool process_special_opt_flags(std::string &key) {
1283 if (key.find(
"tgen::CPP:") == 0) {
1284 int prefix_len = std::string(
"tgen::CPP:").size();
1285 tgen_ensure(
static_cast<
int>(key.size()) == prefix_len + 2
and
1286 std::isdigit(key[prefix_len])
and
1287 std::isdigit(key[prefix_len + 1]),
1288 "invalid CPP format");
1289 int version = std::stoi(key.substr(prefix_len, 2));
1297 size_t prefix_len = 0;
1299 if (key.find(
"tgen::GCC") == 0) {
1300 kind = compiler_kind::gcc;
1301 prefix_len = std::string(
"tgen::GCC").size();
1302 }
else if (key.find(
"tgen::CLANG") == 0) {
1303 kind = compiler_kind::clang;
1304 prefix_len = std::string(
"tgen::CLANG").size();
1309 if (key.size() == prefix_len) {
1314 tgen_ensure(key[prefix_len] ==
':',
"invalid compiler format");
1317 std::string inside = key.substr(prefix_len, key.size() - prefix_len);
1318 int major = 0, minor = 0;
1320 size_t dot = inside.find(
'.');
1321 if (dot == std::string::npos) {
1323 std::all_of(inside.begin(), inside.end(), ::isdigit),
1324 "invalid compiler version");
1325 major = std::stoi(inside);
1327 std::string maj = inside.substr(0, dot);
1328 std::string min = inside.substr(dot + 1);
1331 std::all_of(maj.begin(), maj.end(), ::isdigit)
and
1333 "invalid compiler major version");
1335 std::all_of(min.begin(), min.end(), ::isdigit)
and
1337 "invalid compiler minor version");
1339 major = std::stoi(maj);
1340 minor = std::stoi(min);
1348inline std::vector<std::string>
1350inline std::map<std::string, std::string>
1353template <
typename T> T get_opt(
const std::string &value) {
1355 if constexpr (std::is_same_v<T,
bool>) {
1356 if (value ==
"true" or value ==
"1")
1358 if (value ==
"false" or value ==
"0")
1360 }
else if constexpr (std::is_integral_v<T>) {
1361 if constexpr (std::is_unsigned_v<T>)
1362 return static_cast<T>(std::stoull(value));
1364 return static_cast<T>(std::stoll(value));
1365 }
else if constexpr (std::is_floating_point_v<T>)
1366 return static_cast<T>(std::stold(value));
1372 throw error(
"invalid value `" + value +
"` for type " +
typeid(T).name());
1375inline void parse_opts(
int argc,
char **argv) {
1378 for (
int i = 1; i < argc; ++i) {
1379 std::string key(argv[i]);
1381 if (process_special_opt_flags(key))
1384 if (key[0] ==
'-') {
1386 "invalid opt (" + std::string(argv[i]) +
")");
1387 if (
'0' <= key[1]
and key[1] <=
'9') {
1389 pos_opts.push_back(key);
1394 key = key.substr(1);
1397 pos_opts.push_back(key);
1402 if (key[0] ==
'-') {
1404 "invalid opt (" + std::string(argv[i]) +
")");
1407 key = key.substr(1);
1414 std::size_t eq = key.find(
'=');
1415 if (eq != std::string::npos) {
1417 std::string value = key.substr(eq + 1);
1418 key = key.substr(0, eq);
1420 "expected non-empty key/value in opt (" +
1421 std::string(argv[i]) +
")");
1423 "cannot have repeated keys");
1424 named_opts[key] = value;
1428 "cannot have repeated keys");
1429 tgen_ensure(argv[i + 1],
"value cannot be empty");
1430 named_opts[key] = std::string(argv[i + 1]);
1436inline void set_seed(
int argc,
char **argv) {
1437 std::vector<uint32_t> seed;
1440 for (
int i = 1; i < argc; ++i) {
1442 int size_pos = seed.size();
1444 for (
char *s = argv[i]; *s !=
'\0'; ++s) {
1449 std::seed_seq seq(seed.begin(), seed.end());
1457 detail::ensure_registered();
1458 return index < detail::pos_opts.size();
1463 detail::ensure_registered();
1464 return detail::named_opts.count(key) != 0;
1466template <
typename K>
1467std::enable_if_t<std::is_same_v<K,
char>,
bool> has_opt(K key) {
1473template <
typename T>
1474T
opt(size_t index, std::optional<T> default_value = std::nullopt) {
1475 detail::ensure_registered();
1476 if (!has_opt(index)) {
1478 return *default_value;
1479 throw detail::error(
"cannot find opt at index " +
1480 std::to_string(index));
1482 return detail::get_opt<T>(detail::pos_opts[index]);
1487template <
typename T>
1488T
opt(
const std::string &key, std::optional<T> default_value = std::nullopt) {
1489 detail::ensure_registered();
1492 return *default_value;
1493 throw detail::error(
"cannot find opt with key " + key);
1495 return detail::get_opt<T>(detail::named_opts[key]);
1497template <
typename T,
typename K>
1498std::enable_if_t<std::is_same_v<K,
char>, T>
1499opt(K key, std::optional<T> default_value = std::nullopt) {
1500 return opt<T>(std::string(1, key), default_value);
1505 detail::set_seed(argc, argv);
1507 detail::pos_opts.clear();
1508 detail::named_opts.clear();
1509 detail::parse_opts(argc, argv);
1511 detail::registered =
true;
1517 detail::rng.seed(*seed);
1521 detail::pos_opts.clear();
1522 detail::named_opts.clear();
1524 detail::registered =
true;
1528
1529
1530
1531
1534
1535
1536
1537
1541 T value_l_, value_r_;
1542 std::set<T> values_;
1547 mutable std::vector<std::pair<T, T>>
1549 mutable std::vector<std::vector<
int>> neigh_;
1550 std::vector<std::set<
int>>
1552 bool index_constraints_{
1554 mutable bool uses_full_range_{
1559 list(
int size, T value_left, T value_right)
1560 : size_(size), value_l_(value_left), value_r_(value_right),
1561 uses_full_range_(
true) {
1562 tgen_ensure(size_ > 0,
"list: size must be positive");
1563 tgen_ensure(value_l_ <= value_r_,
"list: value range must be valid");
1569 tgen_ensure(size_ > 0,
"list: size must be positive");
1570 tgen_ensure(!values.empty(),
"list: value set must be non-empty");
1571 value_l_ = 0, value_r_ = values.size() - 1;
1572 val_range_.assign(size_, {value_l_, value_r_});
1574 for (T val : values_)
1575 value_idx_in_set_[val] = idx++;
1580 tgen_ensure(0 <= idx
and idx < size_,
"list: index must be valid");
1581 ensure_val_range_materialized();
1582 if (values_.size() == 0) {
1583 auto &[left, right] = val_range_[idx];
1584 if (left == right
and value_l_ != value_r_) {
1586 "list: must not set to two different values");
1589 "list: value must be in the defined range");
1594 "list: value must be in the set of values");
1595 auto &[left, right] = val_range_[idx];
1596 int new_val = value_idx_in_set_[val];
1598 "list: must not set to two different values");
1599 left = right = new_val;
1601 index_constraints_ =
true;
1608 std::max(idx_1, idx_2) < size_,
1609 "list: indices must be valid");
1613 ensure_val_range_materialized();
1614 ensure_neigh_allocated();
1615 index_constraints_ =
true;
1616 neigh_[idx_1].push_back(idx_2);
1617 neigh_[idx_2].push_back(idx_1);
1623 if (!indices.empty()) {
1624 std::set<
int>::iterator beg = indices.begin();
1625 for (
auto it = std::next(beg); it != indices.end(); ++it)
1633 tgen_ensure(0 <= left
and left <= right
and right < size_,
1634 "list: range indices must be valid");
1635 for (
int i = left; i < right; ++i)
1647 if (!indices.empty())
1648 diff_restrictions_.push_back(indices);
1654 std::set<
int> indices = {idx_1, idx_2};
1660 tgen_ensure(0 <= left
and left <= right
and right < size_,
1661 "list: range indices must be valid");
1662 std::vector<
int> indices(right - left + 1);
1663 std::iota(indices.begin(), indices.end(), left);
1664 return different(std::set<
int>(indices.begin(), indices.end()));
1669 std::vector<
int> indices(size_);
1670 std::iota(indices.begin(), indices.end(), 0);
1671 return different(std::set<
int>(indices.begin(), indices.end()));
1676 for (
int i = 1; i < size_; ++i)
1684 using tgen_is_sequential_tag = detail::is_sequential_tag;
1686 using value_type = T;
1689 std::vector<T> vec_;
1693 value(
const std::initializer_list<T> &il) : value(std::vector<T>(il)) {}
1696 int size()
const {
return vec_.size(); }
1701 "list: value: index out of bounds");
1704 const T &operator[](
int idx)
const {
1706 "list: value: index out of bounds");
1713 std::sort(vec_.begin(), vec_.end());
1720 std::reverse(vec_.begin(), vec_.end());
1734 std::vector<T> new_vec = vec_;
1735 for (
int i = 0; i < rhs
.size(); ++i)
1736 new_vec.push_back(rhs[i]);
1737 return value(new_vec);
1743 for (
int i = 0; i < size(); ++i)
1744 std::swap(vec_[i], vec_[next(0, size() - 1)]);
1750 T
pick()
const {
return vec_[next<
int>(0, size() - 1)]; }
1754 template <
typename Dist>
1757 "value and distribution must have the same size");
1758 return vec_[next_by_distribution(distribution)];
1760 template <
typename Dist>
1761 T pick_by_distribution(
1762 const std::initializer_list<Dist> &distribution)
const {
1763 return pick_by_distribution(std::vector<Dist>(distribution));
1770 "number of elements to choose must be valid");
1771 std::vector<T> new_vec;
1773 for (
int i = 0; need > 0; ++i) {
1775 if (next(1, left) <= need) {
1776 new_vec.push_back(vec_[i]);
1780 return value(new_vec);
1784 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
1785 for (
int i = 0; i < val.size(); ++i) {
1795 if constexpr (!detail::is_generator_value<T>::value) {
1798 std::vector<
typename T::std_type> vec;
1799 for (
const auto &i : vec_)
1800 vec.push_back(i.to_std());
1810 if (diff_restrictions_.empty()) {
1811 if (
auto unconstrained = try_gen_unconstrained())
1812 return *unconstrained;
1814 if (
auto all_different = try_gen_all_different())
1815 return *all_different;
1817 ensure_neigh_allocated();
1818 std::vector<T> vec(size_);
1819 std::vector<
bool> defined_idx(
1822 std::vector<
int> comp_id(size_, -1);
1823 std::vector<std::vector<
int>> comp(size_);
1827 auto define_comp = [&](
int cur_comp, T val) {
1828 for (
int idx : comp[cur_comp]) {
1831 defined_idx[idx] =
true;
1837 std::vector<
bool> vis(size_,
false);
1838 for (
int idx = 0; idx < size_; ++idx)
1841 bool value_defined =
false;
1845 std::queue<
int> q({idx});
1847 std::vector<
int> component;
1848 while (!q.empty()) {
1849 int cur_idx = q.front();
1852 component.push_back(cur_idx);
1855 auto [l, r] = val_range_at(cur_idx);
1857 if (!value_defined) {
1859 value_defined =
true;
1861 }
else if (new_value != l) {
1863 throw detail::contradiction_error(
1865 "tried to set value to `" +
1866 std::to_string(new_value) +
1867 "`, but it was already set as `" +
1868 std::to_string(l) +
"`");
1872 for (
int nxt_idx : neigh_[cur_idx]) {
1873 if (!vis[nxt_idx]) {
1874 vis[nxt_idx] =
true;
1881 for (
int cur_idx : component) {
1882 comp_id[cur_idx] = comp_count;
1883 comp[comp_id[cur_idx]].push_back(cur_idx);
1888 define_comp(comp_count, new_value);
1895 std::vector<std::set<
int>> diff_containing_comp_idx(comp_count);
1898 for (
const std::set<
int> &diff : diff_restrictions_) {
1900 if (
static_cast<uint64_t>(diff.size() - 1) +
1901 static_cast<uint64_t>(value_l_) >
1902 static_cast<uint64_t>(value_r_))
1903 throw detail::contradiction_error(
1904 "list",
"tried to generate " +
1905 std::to_string(diff.size()) +
1906 " different values, but the maximum is " +
1907 std::to_string(value_r_ - value_l_ + 1));
1911 std::set<
int> comp_ids;
1912 for (
int idx : diff) {
1913 if (comp_ids.count(comp_id[idx]))
1914 throw detail::contradiction_error(
1915 "list",
"tried to set two indices as equal and "
1917 comp_ids.insert(comp_id[idx]);
1919 diff_containing_comp_idx[comp_id[idx]].insert(dist_id);
1926 for (
auto &diff_containing : diff_containing_comp_idx)
1927 if (diff_containing.size() >= 3)
1928 throw detail::complex_restrictions_error(
1930 "one index cannot be in >= 3 'different' restrictions");
1932 std::vector<
bool> vis_diff(diff_restrictions_.size(),
false);
1933 std::vector<
bool> initially_defined_comp_idx(comp_count,
false);
1936 auto define_tree = [&](
int diff_id) {
1941 std::set<T> defined_values;
1942 for (
int idx : diff_restrictions_[diff_id])
1943 if (defined_idx[idx]) {
1946 if (defined_values.count(vec[idx]))
1947 throw detail::contradiction_error(
1949 "tried to set two indices as equal and different");
1951 defined_values.insert(vec[idx]);
1956 int new_value_count = diff_restrictions_[diff_id].size() -
1957 static_cast<
int>(defined_values.size());
1958 std::vector<T> generated_values =
1959 generate_distinct_values(new_value_count, defined_values);
1960 auto val_it = generated_values.begin();
1961 for (
int idx : diff_restrictions_[diff_id])
1962 if (defined_idx[idx]) {
1965 initially_defined_comp_idx[comp_id[idx]] =
false;
1967 define_comp(comp_id[idx], *val_it);
1973 std::queue<std::pair<
int,
int>> q;
1974 q.emplace(diff_id, -1);
1975 vis_diff[diff_id] =
true;
1976 while (!q.empty()) {
1977 auto [cur_diff, parent] = q.front();
1980 std::set<
int> neigh_diff;
1981 for (
int idx : diff_restrictions_[cur_diff])
1983 diff_containing_comp_idx[comp_id[idx]]) {
1984 if (nxt_diff == cur_diff
or nxt_diff == parent)
1988 if (vis_diff[nxt_diff])
1989 throw detail::complex_restrictions_error(
1991 "cycle found in 'different' restrictions");
1993 neigh_diff.insert(nxt_diff);
1996 for (
int nxt_diff : neigh_diff) {
1997 vis_diff[nxt_diff] =
true;
1998 q.emplace(nxt_diff, cur_diff);
2001 std::set<T> nxt_defined_values;
2002 for (
int idx2 : diff_restrictions_[nxt_diff])
2003 if (defined_idx[idx2]) {
2007 if (initially_defined_comp_idx[comp_id[idx2]])
2008 throw detail::complex_restrictions_error(
2011 nxt_defined_values.insert(vec[idx2]);
2013 int new_value_count =
2014 diff_restrictions_[nxt_diff].size() -
2015 static_cast<
int>(nxt_defined_values.size());
2016 std::vector<T> generated_values = generate_distinct_values(
2017 new_value_count, nxt_defined_values);
2018 auto val_it = generated_values.begin();
2019 for (
int idx2 : diff_restrictions_[nxt_diff])
2020 if (!defined_idx[idx2]) {
2021 define_comp(comp_id[idx2], *val_it);
2033 std::vector<std::pair<
int,
int>> defined_cnt_and_diff_idx;
2035 for (
const std::set<
int> &diff : diff_restrictions_) {
2036 int defined_cnt = 0;
2037 for (
int idx : diff)
2038 if (defined_idx[idx]) {
2040 initially_defined_comp_idx[comp_id[idx]] =
true;
2042 defined_cnt_and_diff_idx.emplace_back(defined_cnt, dist_id);
2046 std::sort(defined_cnt_and_diff_idx.rbegin(),
2047 defined_cnt_and_diff_idx.rend());
2048 for (
auto [defined_cnt, diff_idx] : defined_cnt_and_diff_idx)
2049 if (!vis_diff[diff_idx])
2050 define_tree(diff_idx);
2054 for (std::size_t dist_id = 0; dist_id < diff_restrictions_.size();
2056 if (!vis_diff[dist_id])
2057 define_tree(dist_id);
2063 for (
int idx = 0; idx < size_; ++idx)
2064 if (!defined_idx[idx])
2065 define_comp(comp_id[idx], next<T>(value_l_, value_r_));
2067 if (!values_.empty()) {
2069 std::vector<T> value_vec(values_.begin(), values_.end());
2071 val = value_vec[val];
2079 void ensure_neigh_allocated()
const {
2080 if (neigh_.size() ==
static_cast<size_t>(size_))
2082 neigh_.assign(size_, {});
2086 void ensure_val_range_materialized()
const {
2087 if (!uses_full_range_)
2089 val_range_.assign(size_, {value_l_, value_r_});
2090 uses_full_range_ =
false;
2094 std::pair<T, T> val_range_at(
int idx)
const {
2095 if (uses_full_range_)
2096 return {value_l_, value_r_};
2097 return val_range_[idx];
2103 generate_distinct_values(
int k,
const std::set<T> &forbidden_values)
const {
2104 for (
auto forbidden : forbidden_values)
2105 tgen_ensure(value_l_ <= forbidden
and forbidden <= value_r_);
2106 const T num_available =
2107 (value_r_ - value_l_ + 1) - forbidden_values.size();
2108 if (num_available < k)
2109 throw detail::complex_restrictions_error(
2110 "list",
"not enough distinct values");
2111 if (forbidden_values.empty())
2112 return distinct_range<T>(value_l_, value_r_).gen_list(k).to_std();
2114 std::map<T, T> virtual_list;
2115 std::vector<T> gen_list;
2116 for (
int i = 0; i < k; ++i) {
2117 T j = next<T>(i, num_available - 1);
2118 T vj = virtual_list.count(j) ? virtual_list[j] : j;
2119 T vi = virtual_list.count(i) ? virtual_list[i] : i;
2121 virtual_list[j] = vi, virtual_list[i] = vj;
2123 gen_list.push_back(virtual_list[i]);
2126 for (T &val : gen_list)
2129 std::vector<std::pair<T,
int>> values_sorted;
2130 for (std::size_t i = 0; i < gen_list.size(); ++i)
2131 values_sorted.emplace_back(gen_list[i], i);
2132 std::sort(values_sorted.begin(), values_sorted.end());
2133 auto cur_it = forbidden_values.begin();
2134 int smaller_forbidden_count = 0;
2135 for (
auto [val, idx] : values_sorted) {
2136 while (cur_it != forbidden_values.end()
and
2137 *cur_it <= val + smaller_forbidden_count)
2138 ++cur_it, ++smaller_forbidden_count;
2139 gen_list[idx] += smaller_forbidden_count;
2148 std::optional<
value> try_gen_unconstrained()
const {
2149 if (!values_.empty()
or index_constraints_)
2150 return std::nullopt;
2152 std::vector<T> vec(size_);
2153 for (
int i = 0; i < size_; ++i)
2154 vec[i] = next<T>(value_l_, value_r_);
2162 std::optional<
value> try_gen_all_different()
const {
2163 if (!values_.empty()
or diff_restrictions_.size() != 1)
2164 return std::nullopt;
2166 const std::set<
int> &diff = diff_restrictions_[0];
2167 if (
static_cast<
int>(diff.size()) != size_
or *diff.begin() != 0
or
2168 *diff.rbegin() != size_ - 1)
2169 return std::nullopt;
2171 if (!neigh_.empty()) {
2172 for (
const auto &adj : neigh_) {
2174 return std::nullopt;
2178 if (index_constraints_)
2179 return std::nullopt;
2181 if (
static_cast<
long long>(size_) >
2182 static_cast<
long long>(value_r_) - value_l_ + 1)
2183 throw detail::contradiction_error(
2184 "list",
"tried to generate " + std::to_string(size_) +
2185 " different values, but the maximum is " +
2186 std::to_string(value_r_ - value_l_ + 1));
2193
2194
2195
2196
2199
2200
2201
2202
2206 std::vector<std::pair<
int,
int>> defs_;
2207 std::optional<std::vector<
int>> cycle_sizes_;
2211 tgen_ensure(size_ > 0,
"permutation: size must be positive");
2217 "permutation: index must be valid");
2218 defs_.emplace_back(idx, val);
2225 size_ == std::accumulate(cycle_sizes.begin(), cycle_sizes.end(), 0),
2226 "permutation: cycle sizes must add up to size of permutation");
2227 cycle_sizes_ = cycle_sizes;
2230 permutation &cycles(
const std::initializer_list<
int> &cycle_sizes) {
2231 return cycles(std::vector<
int>(cycle_sizes));
2237 using tgen_is_sequential_tag = detail::is_sequential_tag;
2240 std::vector<
int> vec_;
2242 bool print_1_based_;
2245 :
vec_(
vec), sep_(
' '), print_1_based_(
false) {
2246 tgen_ensure(!vec_.empty(),
"permutation: value: cannot be empty");
2247 std::vector<
bool> vis(vec_.size(),
false);
2248 for (
int i = 0; i <
size(); ++i) {
2250 vec_[i] <
static_cast<
int>(vec_.size()),
2251 "permutation: value: values must be from `0` to "
2254 "permutation: value: cannot have repeated values");
2255 vis[vec_[i]] =
true;
2258 value(
const std::initializer_list<
int> &il)
2259 : value(std::vector<
int>(il)) {}
2262 int size()
const {
return vec_.size(); }
2267 "permutation: value: index out of bounds");
2274 std::vector<
bool> vis(
size(),
false);
2277 for (
int i = 0; i <
size(); ++i)
2280 for (
int j = i; !vis[j]; j = vec_[j])
2284 return ((
size() - cycles) % 2 == 0) ? +1 : -1;
2290 for (
int i = 0; i < size(); ++i)
2298 std::reverse(vec_.begin(), vec_.end());
2305 std::vector<
int> inv(
size());
2306 for (
int i = 0; i < size(); ++i)
2323 print_1_based_ =
true;
2330 for (
int i = 0; i < size(); ++i)
2331 std::swap(vec_[i], vec_[next(0, size() - 1)]);
2337 int pick()
const {
return vec_[next<
int>(0, size() - 1)]; }
2341 template <
typename Dist>
2344 "value and distribution must have the same size");
2345 return vec_[next_by_distribution(distribution)];
2347 template <
typename Dist>
2348 int pick_by_distribution(
2349 const std::initializer_list<Dist> &distribution)
const {
2350 return pick_by_distribution(std::vector<Dist>(distribution));
2354 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
2355 for (
int i = 0; i < val
.size(); ++i) {
2358 out << val
[i
] + val.print_1_based_;
2370 std::vector<
int> out = vec_;
2380 if (!cycle_sizes_) {
2382 std::vector<
int> idx_to_val(size_, -1), val_to_idx(size_, -1);
2383 for (
auto [idx, val] : defs_) {
2385 0 <= val
and val < size_,
2386 "permutation: value in permutation must be in [0, " +
2387 std::to_string(size_) +
")");
2389 if (idx_to_val[idx] != -1) {
2391 "permutation: cannot set an index to two "
2392 "different values");
2394 idx_to_val[idx] = val;
2396 if (val_to_idx[val] != -1) {
2398 "permutation: cannot set two indices to the "
2401 val_to_idx[val] = idx;
2404 std::vector<
int> perm(size_);
2405 std::iota(perm.begin(), perm.end(), 0);
2406 shuffle(perm.begin(), perm.end());
2408 for (
int &i : idx_to_val)
2411 while (val_to_idx[perm[cur_idx]] != -1)
2413 i = perm[cur_idx++];
2419 std::vector<
int> order(size_);
2420 std::iota(order.begin(), order.end(), 0);
2421 shuffle(order.begin(), order.end());
2423 std::vector<std::vector<
int>> cycles;
2424 for (
int cycle_size : *cycle_sizes_) {
2425 cycles.emplace_back();
2426 for (
int i = 0; i < cycle_size; ++i)
2427 cycles.back().push_back(order[idx++]);
2431 std::vector<
int> perm(size_, -1);
2432 for (
const std::vector<
int> &cycle : cycles) {
2433 int cur_size = cycle.size();
2434 for (
int i = 0; i < cur_size; ++i)
2435 perm[cycle[i]] = cycle[(i + 1) % cur_size];
2443
2444
2445
2446
2452using namespace tgen::detail;
2454inline int popcount(uint64_t x) {
return __builtin_popcountll(x); }
2456inline int ctzll(uint64_t x) {
2459 static const unsigned char index64[64] = {
2460 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
2461 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
2462 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
2463 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12};
2464 return index64[((x & -x) * 0x022FDD63CC95386D) >> 58];
2467inline uint64_t mul_mod(uint64_t a, uint64_t b, uint64_t m) {
2468 return static_cast<u128>(a) * b % m;
2473inline uint64_t expo_mod(uint64_t x, uint64_t y, uint64_t m) {
2476 uint64_t ans = expo_mod(mul_mod(x, x, m), y / 2, m);
2477 return y % 2 ? mul_mod(x, ans, m) : ans;
2486 if (n == 2
or n == 3)
2491 uint64_t r = detail::ctzll(n - 1), d = n >> r;
2493 for (
int a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
2494 uint64_t x = detail::expo_mod(a, d, n);
2495 if (x == 1
or x == n - 1
or a % n == 0)
2498 for (uint64_t j = 0; j < r - 1; ++j) {
2499 x = detail::mul_mod(x, x, n);
2511inline uint64_t pollard_rho(uint64_t n) {
2514 auto f = [n](uint64_t x) {
return mul_mod(x, x, n) + 1; };
2516 uint64_t x = 0, y = 0, t = 30, prd = 2, x0 = 1, q;
2517 while (t % 40 != 0
or std::gcd(prd, n) == 1) {
2520 q = mul_mod(prd, x > y ? x - y : y - x, n);
2523 x = f(x), y = f(f(y)), ++t;
2525 return std::gcd(prd, n);
2528inline std::vector<uint64_t> factor(uint64_t n) {
2533 uint64_t d = pollard_rho(n);
2534 std::vector<uint64_t> l = factor(d), r = factor(n / d);
2535 l.insert(l.end(), r.begin(), r.end());
2540template <
typename T>
2541std::runtime_error there_is_no_in_range_error(
const std::string &type, T l,
2543 return error(
"math: there is no " + type +
" in range [" +
2544 std::to_string(l) +
", " + std::to_string(r) +
"]");
2546template <
typename T>
2547std::runtime_error there_is_no_from_error(
const std::string &type, T r) {
2548 return error(
"math: there is no " + type +
" from " + std::to_string(r));
2550template <
typename T>
2551std::runtime_error there_is_no_upto_error(
const std::string &type, T r) {
2552 return error(
"math: there is no " + type +
" up to " + std::to_string(r));
2558inline i128 modular_inverse_128(i128 a, i128 mod) {
2560 "math: modular inverse requires 0 < value < mod");
2562 i128 t = 0, new_t = 1;
2563 i128 r = mod, new_r = a;
2565 while (new_r != 0) {
2568 auto tmp_t = t - q * new_t;
2572 auto tmp_r = r - q * new_r;
2577 tgen_ensure(r == 1,
"math: remainder and mod must be coprime");
2585inline bool mul_leq(uint64_t a, uint64_t b, uint64_t limit) {
2586 if (a == 0
or b == 0)
2588 return a <= limit / b;
2592inline std::optional<uint64_t> expo(uint64_t base, uint64_t exp,
2594 uint64_t result = 1;
2598 if (!mul_leq(result, base, limit))
2599 return std::nullopt;
2608 if (!mul_leq(base, base, limit))
2609 return std::nullopt;
2617inline uint64_t kth_root_floor(uint64_t n, uint64_t k) {
2618 tgen_ensure_against_bug(k > 0,
"math: value must be valid");
2619 if (k == 1
or n <= 1)
2622 uint64_t lo = 1, hi = 1ULL << ((64 + k - 1) / k);
2625 uint64_t mid = lo + (hi - lo + 1) / 2;
2627 if (expo(mid, k, n)) {
2638inline i128 gcd128(i128 a, i128 b) {
2654inline i128 mul_saturate(i128 a, i128 b) {
2656 static const i128 LIMIT =
static_cast<i128>(1) << 64;
2657 if (a == 0
or b == 0)
2668 crt() : a(0), m(1) {}
2669 crt(T a_, T m_) : a(a_), m(m_) {}
2670 crt operator*(crt C) {
2671 if (m == 0
or C.m == 0)
2674 T g = gcd128(m, C.m);
2675 if ((C.a - a) % g != 0)
2684 T inv = modular_inverse_128(m1 % m2, m2);
2686 T k = ((C.a - a) / g) % m2;
2690 k =
static_cast<u128>(k) * inv % m2;
2692 T lcm = mul_saturate(m, m2);
2694 T res = (a +
static_cast<T>((
static_cast<u128>(k) * m) % lcm)) % lcm;
2704inline constexpr long double LOG_ZERO = -INFINITY;
2705inline constexpr long double LOG_ONE = 0.0;
2707inline long double log_space(
long double x) {
2708 return x == 0.0 ? LOG_ZERO : std::log(x);
2712inline long double add_log_space(
long double a,
long double b) {
2717 return a + log1p(exp(b - a));
2722inline long double sub_log_space(
long double a,
long double b) {
2727 return a + log1p(-exp(b - a));
2736 tgen_ensure(n > 0,
"math: number to factor must be positive");
2737 auto factors = detail::factor(n);
2738 std::sort(factors.begin(), factors.end());
2746 tgen_ensure(n > 0,
"math: number to factor must be positive");
2747 std::vector<std::pair<uint64_t,
int>> primes;
2748 for (uint64_t p : factor(n)) {
2749 if (!primes.empty()
and primes.back().first == p)
2750 ++primes.back().second;
2752 primes.emplace_back(p, 1);
2761 return detail::modular_inverse_128(a, mod);
2767 tgen_ensure(n > 0,
"math: totient(0) is undefined");
2770 for (
auto [p, e] : factor_by_prime(n))
2777inline const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> &
2780 static const std::pair<std::vector<uint64_t>, std::vector<uint64_t>> value{
2782 2, 3, 7, 23, 89, 113, 523, 887, 1129, 1327, 9551, 15683, 19609,
2783 31397, 155921, 360653, 370261, 492113, 1349533, 1357201, 2010733,
2784 4652353, 17051707, 20831323, 47326693, 122164747, 189695659,
2785 191912783, 387096133, 436273009, 1294268491, 1453168141,
2786 2300942549, 3842610773, 4302407359, 10726904659, 20678048297,
2787 22367084959, 25056082087, 42652618343, 127976334671, 182226896239,
2788 241160624143, 297501075799, 303371455241, 304599508537,
2789 416608695821, 461690510011, 614487453523, 738832927927,
2790 1346294310749, 1408695493609, 1968188556461, 2614941710599,
2791 7177162611713, 13829048559701, 19581334192423, 42842283925351,
2792 90874329411493, 171231342420521, 218209405436543, 1189459969825483,
2793 1686994940955803, 1693182318746371, 43841547845541059,
2794 55350776431903243, 80873624627234849, 203986478517455989,
2795 218034721194214273, 305405826521087869, 352521223451364323,
2796 401429925999153707, 418032645936712127, 804212830686677669,
2797 1425172824437699411, 5733241593241196731, 6787988999657777797
2799 {1, 2, 4, 6, 8, 14, 18, 20, 22, 34, 36,
2800 44, 52, 72, 86, 96, 112, 114, 118, 132, 148, 154,
2801 180, 210, 220, 222, 234, 248, 250, 282, 288, 292, 320,
2802 336, 354, 382, 384, 394, 456, 464, 468, 474, 486, 490,
2803 500, 514, 516, 532, 534, 540, 582, 588, 602, 652, 674,
2804 716, 766, 778, 804, 806, 906, 916, 924, 1132, 1184, 1198,
2805 1220, 1224, 1248, 1272, 1328, 1356, 1370, 1442, 1476, 1488, 1510}};
2814 throw detail::there_is_no_upto_error(
"prime gap", right);
2816 const auto &[P, G] = prime_gaps();
2817 for (
int i = P.size() - 1;; --i) {
2821 uint64_t real_right = std::min(right, P[i] + G[i] - 1);
2822 uint64_t prev = i > 0 ? G[i - 1] : 0;
2823 uint64_t curr = real_right - P[i];
2826 return {P[i] + 1, real_right};
2833 static const std::vector<uint64_t> highly_composites = {
2834 1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720, 840, 1260, 1680,
2835 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 45360, 50400, 55440,
2836 83160, 110880, 166320, 221760, 277200, 332640, 498960, 554400, 665280,
2837 720720, 1081080, 1441440, 2162160, 2882880, 3603600, 4324320, 6486480,
2838 7207200, 8648640, 10810800, 14414400, 17297280, 21621600, 32432400,
2839 36756720, 43243200, 61261200, 73513440, 110270160, 122522400, 147026880,
2840 183783600, 245044800, 294053760, 367567200, 551350800, 698377680, 735134400,
2841 1102701600, 1396755360, 2095133040, 2205403200, 2327925600, 2793510720,
2842 3491888400, 4655851200, 5587021440, 6983776800, 10475665200, 13967553600,
2843 20951330400, 27935107200, 41902660800, 48886437600, 64250746560,
2844 73329656400, 80313433200, 97772875200, 128501493120, 146659312800,
2845 160626866400, 240940299600, 293318625600, 321253732800, 481880599200,
2846 642507465600, 963761198400, 1124388064800, 1606268664000, 1686582097200,
2847 1927522396800, 2248776129600, 3212537328000, 3373164194400, 4497552259200,
2848 6746328388800, 8995104518400, 9316358251200, 13492656777600, 18632716502400,
2849 26985313555200, 27949074753600, 32607253879200, 46581791256000,
2850 48910880818800, 55898149507200, 65214507758400, 93163582512000,
2851 97821761637600, 130429015516800, 195643523275200, 260858031033600,
2852 288807105787200, 391287046550400, 577614211574400, 782574093100800,
2853 866421317361600, 1010824870255200, 1444035528936000, 1516237305382800,
2854 1732842634723200, 2021649740510400, 2888071057872000, 3032474610765600,
2855 4043299481020800, 6064949221531200, 8086598962041600, 10108248702552000,
2856 12129898443062400, 18194847664593600, 20216497405104000, 24259796886124800,
2857 30324746107656000, 36389695329187200, 48519593772249600, 60649492215312000,
2858 72779390658374400, 74801040398884800, 106858629141264000,
2859 112201560598327200, 149602080797769600, 224403121196654400,
2860 299204161595539200, 374005201994424000, 448806242393308800,
2861 673209363589963200, 748010403988848000, 897612484786617600,
2862 1122015605983272000, 1346418727179926400, 1795224969573235200,
2863 2244031211966544000, 2692837454359852800, 3066842656354276800,
2864 4381203794791824000, 4488062423933088000, 6133685312708553600,
2865 8976124847866176000, 9200527969062830400, 12267370625417107200ULL,
2866 15334213281771384000ULL, 18401055938125660800ULL};
2867 return highly_composites;
2872 for (
int i = highly_composites().size() - 1; i >= 0; --i)
2873 if (highly_composites()[i] <= right)
2874 return highly_composites()[i];
2876 throw detail::there_is_no_upto_error(
"highly composite number", right);
2882 if (right < left
or right < 2)
2883 throw detail::there_is_no_in_range_error(
"prime", left, right);
2884 left = std::max<uint64_t>(left, 2);
2885 auto [l_gap, r_gap] = prime_gap_upto(right);
2886 if (right - left + 1 <= r_gap - l_gap + 1) {
2888 std::vector<uint64_t> vals(right - left + 1);
2889 iota(vals.begin(), vals.end(), left);
2890 shuffle(vals.begin(), vals.end());
2891 for (uint64_t i : vals)
2894 throw detail::there_is_no_in_range_error(
"prime", left, right);
2899 n = next(left, right);
2907 tgen_ensure(left <= std::numeric_limits<uint64_t>::max() - 58,
2908 "math: invalid bound");
2909 for (uint64_t i = std::max<uint64_t>(2, left);; ++i)
2917 for (uint64_t i = right; i >= 2; --i)
2920 throw detail::there_is_no_upto_error(
"prime", right);
2927 for (
auto [p, e] : factor_by_prime(n))
2928 divisors *= (e + 1);
2936 int divisor_count) {
2938 "math: divisor count must be prime");
2939 int root = divisor_count - 1;
2940 uint64_t lo = detail::kth_root_floor(left, root);
2941 if (*detail::expo(lo, root, left) < left)
2943 uint64_t p =
gen_prime(lo
, detail::kth_root_floor(right, root)
);
2944 return *detail::expo(p, root, right);
2951 std::vector<uint64_t> rems,
2952 std::vector<uint64_t> mods) {
2954 throw detail::there_is_no_in_range_error(
"congruent number", left,
2957 "math: number of remainders and mods must be the same");
2958 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
2961 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
2963 "math: remainder must be smaller than the mod");
2964 crt = crt * detail::crt(rems[i], mods[i]);
2967 throw detail::there_is_no_in_range_error(
"congruent number", left,
2969 if (crt.m > right) {
2970 if (!(left <= crt.a
and crt.a <= right))
2971 throw detail::there_is_no_in_range_error(
"congruent number",
2974 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
2975 if (crt.a % mods[j] != rems[j])
2976 throw detail::there_is_no_in_range_error(
"congruent number",
2982 uint64_t k_min = crt.a >= left ? 0 : ((left - crt.a) + crt.m - 1) / crt.m;
2983 uint64_t k_max = (right - crt.a) / crt.m;
2986 throw detail::there_is_no_in_range_error(
"congruent number", left,
2989 return crt.a + next(k_min, k_max) * crt.m;
2996 return gen_congruent(left, right, std::vector<uint64_t>({rem}),
2997 std::vector<uint64_t>({mod}));
3005 std::vector<uint64_t> mods) {
3007 "math: number of remainders and mods must be the same");
3008 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
3011 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
3013 "math: remainder must be smaller than the mod");
3014 crt = crt * detail::crt(rems[i], mods[i]);
3017 throw detail::there_is_no_from_error(
"congruent number", left);
3018 if (crt.m > std::numeric_limits<uint64_t>::max()) {
3020 throw detail::error(
3021 "math: congruent number does not exist or is too large");
3023 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3024 if (crt.a % mods[j] != rems[j])
3025 throw detail::error(
"math: congruent number does "
3026 "not exist or is too large");
3033 k = ((left - crt.a) + crt.m - 1) / crt.m;
3034 detail::i128 result = crt.a + k * crt.m;
3036 if (result > std::numeric_limits<uint64_t>::max())
3037 throw detail::error(
"math: congruent number is too large");
3044 return congruent_from(left, std::vector<uint64_t>{rem},
3045 std::vector<uint64_t>{mod});
3053 std::vector<uint64_t> mods) {
3055 "math: number of remainders and mods must be the same");
3056 tgen_ensure(rems.size() > 0,
"math: must have at least one congruence");
3059 for (
int i = 0; i <
static_cast<
int>(rems.size()); ++i) {
3061 "math: remainder must be smaller than the mod");
3063 crt = crt * detail::crt(rems[i], mods[i]);
3066 throw detail::there_is_no_upto_error(
"congruent number", right);
3067 if (crt.m > right) {
3068 if (!(crt.a <= right))
3069 throw detail::there_is_no_upto_error(
"congruent number", right);
3071 for (
int j = 0; j <
static_cast<
int>(rems.size()); ++j)
3072 if (crt.a % mods[j] != rems[j])
3073 throw detail::there_is_no_upto_error(
"congruent number",
3080 throw detail::there_is_no_upto_error(
"congruent number", right);
3082 uint64_t k = (right - crt.a) / crt.m;
3083 detail::i128 result = crt.a + k * crt.m;
3086 throw detail::there_is_no_upto_error(
"congruent number", right);
3093 return congruent_upto(right, std::vector<uint64_t>{rem},
3094 std::vector<uint64_t>{mod});
3102 static const std::vector<uint64_t> fib = [] {
3103 std::vector<uint64_t> v = {0, 1};
3105 std::numeric_limits<uint64_t>::max() - v[v.size() - 2])
3106 v.push_back(v.back() + v[v.size() - 2]);
3118 std::optional<
int> part_right = std::nullopt) {
3119 if (!part_right.has_value())
3121 part_right = std::min(*part_right, n);
3123 "math: invalid parameters to gen_partition");
3124 tgen_ensure(part_left <= n
and *part_right > 0,
"math: no such partition");
3127 std::vector<
long double> dp(n + 1, detail::LOG_ZERO);
3128 dp[0] = detail::LOG_ONE;
3129 long double window = detail::LOG_ZERO;
3130 for (
int i = 1; i <= n; ++i) {
3132 window = detail::add_log_space(window, dp[i - part_left]);
3133 if (i >= *part_right + 1)
3134 window = detail::sub_log_space(window, dp[i - *part_right - 1]);
3137 tgen_ensure(dp[n] >= 0,
"math: no such partition");
3141 for (
int i = 1; i <= n; ++i)
3142 dp_pref[i] = detail::add_log_space(dp_pref[i - 1], dp[i]);
3144 std::vector<
int> part;
3148 int l = std::max(0, sum - *part_right), r = sum - part_left;
3149 detail::tgen_ensure_against_bug(r >= 0,
"math: r < 0 in gen_partition");
3151 int nxt_sum = std::min(sum, r);
3152 long double random = next<
long double>(0, 1);
3163 long double val_l = l ? dp_pref[l - 1] : detail::LOG_ZERO,
3165 while (nxt_sum > l
and
3166 dp_pref[nxt_sum - 1] >=
3167 val_r + detail::log_space(random +
3168 (1 - random) * exp(val_l - val_r)))
3171 part.push_back(sum - nxt_sum);
3184 std::optional<
int> part_right = std::nullopt) {
3185 if (!part_right.has_value())
3187 part_right = std::min(*part_right, n);
3189 "math: invalid parameters to gen_partition_fixed_size");
3190 tgen_ensure(
static_cast<
long long>(k) * part_left <= n
and
3191 n <=
static_cast<
long long>(k) * (*part_right),
3192 "math: no such partition");
3195 int s = n - k * part_left;
3197 std::vector<
int> part(k);
3198 if (*part_right == n) {
3200 std::vector<
int> cuts = {-1};
3202 int total = s + k - 1, bars = k - 1;
3203 for (
int i = 0; i < total
and bars > 0; ++i)
3204 if (next<
long double>(0, 1) <
3205 static_cast<
long double>(bars) / (total - i)) {
3209 cuts.push_back(total);
3212 for (
int i = 0; i < k; ++i)
3213 part[i] = cuts[i + 1] - cuts[i] - 1;
3216 int u = *part_right - part_left;
3219 std::vector<std::vector<
long double>> dp(
3220 k + 1, std::vector<
long double>(s + 1, detail::LOG_ZERO));
3221 dp[0][0] = detail::LOG_ONE;
3223 for (
int i = 1; i <= k; ++i) {
3224 std::vector<
long double> pref = dp[i - 1];
3225 for (
int j = 1; j <= s; ++j)
3226 pref[j] = detail::add_log_space(pref[j - 1], dp[i - 1][j]);
3228 for (
int j = 0; j <= s; ++j) {
3231 dp[i][j] = detail::sub_log_space(dp[i][j], pref[j - u - 1]);
3236 int left_to_distribute = s;
3237 for (
int i = k; i >= 1; --i) {
3238 long double log_total = detail::LOG_ZERO;
3239 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j)
3240 log_total = detail::add_log_space(
3241 log_total, dp[i - 1][left_to_distribute - j]);
3242 detail::tgen_ensure_against_bug(
3243 log_total != detail::LOG_ZERO,
3244 "math: total == 0 in gen_partition_fixed_size");
3250 long double random =
3251 detail::log_space(next<
long double>(0, 1)) + log_total;
3253 long double cur_prob = detail::LOG_ZERO;
3255 for (
int j = 0; j <= u
and j <= left_to_distribute; ++j) {
3256 cur_prob = detail::add_log_space(
3257 cur_prob, dp[i - 1][left_to_distribute - j]);
3258 if (random < cur_prob) {
3264 part[k - i] = chosen;
3265 left_to_distribute -= chosen;
3282 uint64_t n,
int k, uint64_t part_left = 0,
3283 std::optional<uint64_t> part_right = std::nullopt) {
3284 if (!part_right.has_value())
3286 part_right = std::min(*part_right, n);
3288 detail::u128 n128 = n;
3289 detail::u128 k128 = k;
3290 detail::u128 part_left128 = part_left;
3291 detail::u128 part_right128 = *part_right;
3294 "math: invalid parameters to gen_partition_fixed_size_fast");
3296 k128 * part_left128 <= n128
and
3297 k128 * part_right128 >= n128,
3298 "math: no such partition");
3300 uint64_t slack_total = n128 - k128 * part_left128;
3301 uint64_t slack_max = part_right128 - part_left128;
3303 std::vector<uint64_t> part(k);
3305 part[0] = slack_total;
3307 std::vector<uint64_t> cuts(k - 1);
3308 for (uint64_t &d : cuts)
3309 d = next<uint64_t>(0, slack_total);
3310 std::sort(cuts.begin(), cuts.end());
3313 for (
int i = 0; i + 1 < k; ++i) {
3314 part[i] = cuts[i] - prev;
3317 part[k - 1] = slack_total - prev;
3320 auto add_part_left = [part_left](uint64_t x) -> uint64_t {
3321 detail::u128 val = x + part_left;
3322 detail::tgen_ensure_against_bug(
3323 val <= std::numeric_limits<uint64_t>::max(),
3324 "math: part + part_left exceeds uint64_t in "
3325 "gen_partition_fixed_size_fast");
3329 if (slack_max >= slack_total) {
3330 for (uint64_t &x : part)
3331 x = add_part_left(x);
3335 detail::u128 remaining = 0;
3336 for (uint64_t &x : part) {
3337 if (x > slack_max) {
3338 remaining += x - slack_max;
3341 x = add_part_left(x);
3344 if (remaining > 0) {
3345 for (uint64_t &x : part) {
3346 if (x < *part_right && remaining > 0) {
3347 detail::u128 room = *part_right - x;
3348 detail::u128 add = std::min(remaining, room);
3349 detail::u128 val = x + add;
3350 detail::tgen_ensure_against_bug(
3352 "math: part exceeds part_right after redistribution in "
3353 "gen_partition_fixed_size_fast");
3358 detail::tgen_ensure_against_bug(
3359 remaining == 0,
"math: remaining mass after redistribution in "
3360 "gen_partition_fixed_size_fast");
3370template <
typename T>
3373 std::optional<uint64_t> max_size = std::nullopt) {
3374 size_t n = elements.size();
3375 tgen_ensure(k > 0,
"math: partition_elements: k must be positive");
3377 "math: partition_elements: min_size must be non-negative");
3379 std::vector<uint64_t> sizes;
3380 if (max_size.has_value()) {
3381 sizes = gen_partition_fixed_size_fast(n, k, min_size, max_size);
3383 for (
int sz : gen_partition_fixed_size(n, k, min_size))
3384 sizes.push_back(sz);
3387 std::vector<std::vector<T>> groups;
3390 for (uint64_t sz : sizes) {
3391 groups.emplace_back(elements.begin() + pos,
3392 elements.begin() + pos + sz);
3401
3402
3403
3404
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3447 std::vector<regex_node> children_;
3448 int left_bound_, right_bound_;
3451 log_space_num_ways_;
3456 regex_node(
const std::string &pattern)
3457 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3458 if (pattern.size() == 1) {
3459 log_space_num_ways_ = math::detail::LOG_ONE;
3462 tgen_ensure_against_bug(pattern[0] ==
'[' and pattern.back() ==
']',
3463 "str: invalid regex: expected character class");
3464 int size = pattern.size() - 2;
3465 log_space_num_ways_ = math::detail::log_space(size);
3466 distinct_ = distinct_container<
char>(pattern.substr(1, size));
3469 regex_node(
const std::string &pattern, std::vector<regex_node> &children)
3470 : pattern_(pattern), left_bound_(-1), right_bound_(-1) {
3471 if (pattern ==
"SEQ") {
3473 log_space_num_ways_ = math::detail::LOG_ONE;
3474 for (
const auto &child : children)
3475 log_space_num_ways_ += child.log_space_num_ways_;
3476 }
else if (pattern ==
"OR") {
3478 log_space_num_ways_ = math::detail::LOG_ZERO;
3479 for (
const auto &child : children)
3480 log_space_num_ways_ = math::detail::add_log_space(
3481 log_space_num_ways_, child.log_space_num_ways_);
3483 tgen_ensure_against_bug(
"str: invalid regex: expected SEQ or OR");
3485 children_ = std::move(children);
3489 regex_node(
int left_bound,
int right_bound, regex_node &child)
3490 : pattern_(
"REP"), left_bound_(left_bound), right_bound_(right_bound) {
3491 log_space_num_ways_ = math::detail::LOG_ZERO;
3492 for (
int i = left_bound; i <= right_bound; ++i)
3493 log_space_num_ways_ = math::detail::add_log_space(
3494 log_space_num_ways_, i * child.log_space_num_ways_);
3496 children_.push_back(std::move(child));
3502 std::vector<regex_node> cur;
3503 std::vector<regex_node> branches;
3507inline regex_node make_regex_seq(regex_state &st) {
3508 return regex_node(
"SEQ", st.cur);
3512inline regex_node finish_regex_state(regex_state &st) {
3514 if (st.branches.empty())
3515 return make_regex_seq(st);
3518 st.branches.push_back(make_regex_seq(st));
3519 return regex_node(
"OR", st.branches);
3524inline regex_node parse_regex(std::string regex) {
3525 std::string new_regex;
3526 for (
char c : regex)
3529 swap(regex, new_regex);
3531 std::vector<regex_state> stack;
3533 for (size_t i = 0; i < regex.size(); ++i) {
3538 stack.push_back(std::move(cur));
3539 cur = regex_state();
3540 }
else if (c ==
')') {
3542 regex_node node = finish_regex_state(cur);
3544 tgen_ensure(!stack.empty(),
"str: invalid regex: unmatched `)`");
3545 cur = std::move(stack.back());
3548 cur.cur.push_back(std::move(node));
3549 }
else if (c ==
'|') {
3551 regex_node node = make_regex_seq(cur);
3552 cur.branches.push_back(std::move(node));
3553 }
else if (c ==
'[') {
3557 for (++i; i < regex.size()
and regex[i] !=
']'; ++i) {
3558 if (i + 2 < regex.size()
and regex[i + 1] ==
'-') {
3559 char a = regex[i], b = regex[i + 2];
3562 for (
char x = a; x <= b; ++x)
3570 "str: invalid regex: unmatched `[`");
3571 cur.cur.emplace_back(
"[" + chars +
"]");
3572 }
else if (c ==
'{') {
3577 while (i < regex.size()
and
3578 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3582 "str: invalid regex: number too large inside `{}`");
3583 l = 10 * l + (regex[i] -
'0');
3587 if (i < regex.size()
and regex[i] ==
',') {
3589 while (i < regex.size()
and
3590 isdigit(
static_cast<
unsigned char>(regex[i]))) {
3594 r <=
static_cast<
int>(1e8),
3595 "str: invalid regex: number too large inside `{}`");
3596 r = 10 * r + (regex[i] -
'0');
3603 "str: invalid regex: unmatched `{`");
3605 "str: invalid regex: missing number inside `{}`");
3607 "str: invalid regex: invalid range inside `{}`");
3611 "str: invalid regex: expected expression before `{}`");
3613 regex_node rep(l, r, cur.cur.back());
3615 cur.cur.push_back(std::move(rep));
3618 cur.cur.emplace_back(std::string(1, c));
3622 tgen_ensure(stack.empty(),
"str: invalid regex: unmatched `(`");
3623 return finish_regex_state(cur);
3627inline void gen_regex(
const regex_node &node, std::string &str) {
3629 if (node.pattern_[0] ==
'[') {
3630 str += node.pattern_[1 + next<
int>(0, node.pattern_.size() - 3)];
3635 if (node.left_bound_ != -1) {
3639 double log_rand = math::detail::log_space(next<
double>(0, 1)) +
3640 node.log_space_num_ways_;
3641 double cur_prob = math::detail::LOG_ZERO;
3642 double child_num_ways = node.children_[0].log_space_num_ways_;
3644 for (
int i = node.left_bound_; i <= node.right_bound_; ++i) {
3646 math::detail::add_log_space(cur_prob, i * child_num_ways);
3647 if (log_rand <= cur_prob) {
3648 for (
int j = 0; j < i; ++j)
3649 gen_regex(node.children_[0], str);
3654 tgen_ensure_against_bug(
false,
3655 "str: log_rand > cur_prob in REP gen_regex");
3659 if (!node.children_.empty()
and node.pattern_ ==
"SEQ") {
3660 for (
const regex_node &child : node.children_)
3661 gen_regex(child, str);
3666 if (!node.children_.empty()
and node.pattern_ ==
"OR") {
3670 double log_rand = math::detail::log_space(next<
double>(0, 1)) +
3671 node.log_space_num_ways_;
3672 double cur_prob = math::detail::LOG_ZERO;
3674 for (
const regex_node &child : node.children_) {
3675 cur_prob = math::detail::add_log_space(cur_prob,
3676 child.log_space_num_ways_);
3677 if (log_rand <= cur_prob) {
3678 gen_regex(child, str);
3683 tgen_ensure_against_bug(
false,
3684 "str: log_rand > cur_prob in OR gen_regex");
3688 detail::tgen_ensure_against_bug(
3689 node.pattern_.size() == 1,
3690 "str: invalid regex: expected single character, but got `" +
3691 node.pattern_ +
"`");
3692 str += node.pattern_[0];
3696template <
typename... Args>
3697std::string regex_format(
const std::string &s, Args &&...args) {
3698 if constexpr (
sizeof...(Args) == 0) {
3701 int size = std::snprintf(
nullptr, 0, s.c_str(), args...) + 1;
3702 std::string buf(size,
'\0');
3703 std::snprintf(buf.data(), size, s.c_str(), args...);
3712
3713
3716 std::optional<
list<
char>> list_;
3717 std::optional<detail::regex_node>
3722 str(
int size,
char value_left =
'a',
char value_right =
'z') {
3723 tgen_ensure(size > 0,
"str: size must be positive");
3724 list_ = list<
char>(size, value_left, value_right);
3729 str(
int size, std::set<
char> chars) {
3730 tgen_ensure(size > 0,
"str: size must be positive");
3731 list_ = list<
char>(size, chars);
3735 template <
typename... Args>
str(
const std::string ®ex, Args &&...args) {
3736 tgen_ensure(regex.size() > 0,
"str: regex must be non-empty");
3738 root_ = detail::parse_regex(
3739 detail::regex_format(regex, std::forward<Args>(args)...));
3744 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3745 list_->fix(idx, character);
3751 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3752 list_->equal(indices);
3758 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3759 list_->equal(idx_1, idx_2);
3765 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3766 list_->equal_range(left, right);
3772 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3779 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3780 tgen_ensure(0 <= left
and left <= right
and right < list_->size_,
3781 "str: range indices must be valid");
3782 for (
int i = left; i < right - (i - left); ++i)
3789 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3790 return palindrome(0, list_->size_ - 1);
3796 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3797 list_->different(indices);
3803 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3804 list_->different(idx_1, idx_2);
3810 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3811 list_->different_range(left, right);
3817 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3818 list_->all_different();
3824 tgen_ensure(!root_,
"str: cannot add restriction for regex");
3825 list_->adjacent_different();
3831 using tgen_is_sequential_tag = detail::is_sequential_tag;
3833 using value_type =
char;
3834 using std_type = std::string;
3837 value(
const std::string &str) : str_(str) {
3838 tgen_ensure(!str_.empty(),
"str: value: cannot be empty");
3842 int size()
const {
return str_.size(); }
3847 "str: value: index out of bounds");
3850 const char &operator[](
int idx)
const {
3852 "str: value: index out of bounds");
3859 std::sort(str_.begin(), str_.end());
3866 std::reverse(str_.begin(), str_.end());
3873 for (
char &c : str_)
3874 c = std::tolower(c);
3881 for (
char &c : str_)
3882 c = std::toupper(c);
3889 return value(str_ + rhs.str_
);
3895 for (
int i = 0; i < size(); ++i)
3896 std::swap(str_[i], str_[next(0, size() - 1)]);
3906 template <
typename Dist>
3909 "value and distribution must have the same size");
3910 return str_[next_by_distribution(distribution)];
3912 template <
typename Dist>
3913 char pick_by_distribution(
3914 const std::initializer_list<Dist> &distribution)
const {
3915 return pick_by_distribution(std::vector<Dist>(distribution));
3922 "number of elements to choose must be valid");
3923 std::string new_str;
3925 for (
int i = 0; need > 0; ++i) {
3927 if (next(1, left) <= need) {
3928 new_str.push_back(str_[i]);
3936 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
3937 return out << val.str_;
3941 std::string
to_std()
const {
return std_type(str_); }
3950 std::string ret_str;
3951 gen_regex(*root_, ret_str);
3955 std::vector<
char> vec = list_->gen().to_std();
3956 return value(std::string(vec.begin(), vec.end()));
3962
3963
3964
3965
3971template <
typename T> std::pair<T, T> gen_eq(T L1, T R1, T L2, T R2) {
3972 T L = std::max(L1, L2);
3973 T R = std::min(R1, R2);
3975 tgen_ensure(L <= R,
"pair: no valid values to generate");
3976 T x = next<T>(L, R);
3981template <
typename T>
3982std::pair<u128, u128> get_n_and_m(T L1, T R1, T L2, T R2) {
3983 u128 n =
static_cast<i128>(R1) - L1 + 1;
3984 u128 m =
static_cast<i128>(R2) - L2 + 1;
3990static u128 pos_arith_sum(u128 first, u128 last, u128 num_terms) {
3991 u128 x = first + last, y = num_terms;
4004template <
typename T> std::pair<T, T> gen_neq(T L1, T R1, T L2, T R2) {
4005 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4007 T L_intersect = std::max(L1, L2);
4008 T R_intersect = std::min(R1, R2);
4009 u128 inter =
static_cast<i128>(R_intersect) - L_intersect + 1;
4011 u128 total = n * m - inter;
4012 tgen_ensure(total > 0,
"pair: no valid values to generate");
4017 a = next<T>(L1, R1);
4018 b = next<T>(L2, R2);
4029template <
typename T>
4030std::pair<u128, u128> count_lt_regions(T L1, T R1, T L2, T R2) {
4031 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4034 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4038 i128 split = std::min<i128>(R_second, R1);
4041 u128 len1 = std::max<i128>(0, split - L_second + 1);
4043 u128 count_region1 = 0;
4046 i128 first = L_second - L1;
4047 i128 last = split - L1;
4050 count_region1 = pos_arith_sum(first, last, len1);
4055 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4057 u128 len2 = std::max<i128>(0, R_second - L_second_region2 + 1);
4058 u128 count_region2 = len2 * n;
4060 return {count_region1, count_region2};
4065template <
typename T> std::pair<T, T> gen_lt(T L1, T R1, T L2, T R2) {
4066 auto [n, m] = get_n_and_m(L1, R1, L2, R2);
4070 i128 L_second = std::max<i128>(L2,
static_cast<i128>(L1) + 1);
4076 i128 split = std::min<i128>(R_second, R1);
4078 auto [count_region1, count_region2] = count_lt_regions(L1, R1, L2, R2);
4079 u128 total = count_region1 + count_region2;
4080 tgen_ensure(total > 0,
"pair: no valid values to generate");
4082 u128 k = detail::next128(total);
4083 if (k < count_region1) {
4087 u128 len1 = std::max<i128>(0, split - L_second + 1);
4094 i128 base = L_second - L1;
4095 i128 lo = 0, hi =
static_cast<i128>(len1) - 1;
4098 i128 mid = lo + (hi - lo) / 2;
4100 if (pos_arith_sum(base, base + mid, mid + 1) <= k)
4109 k -= pos_arith_sum(base, base + d - 1, d);
4111 return {L1 +
static_cast<T>(k), L_second + d};
4117 i128 L_second_region2 = std::max(L_second,
static_cast<i128>(R1) + 1);
4119 return {L1 +
static_cast<T>(k % n),
4120 L_second_region2 +
static_cast<T>(k / n)};
4126template <
typename T> std::pair<T, T> gen_gt(T L1, T R1, T L2, T R2) {
4127 auto [first, second] = gen_lt(L2, R2, L1, R1);
4128 return {second, first};
4133template <
typename T> std::pair<T, T> gen_leq(T L1, T R1, T L2, T R2) {
4135 i128 L_intersect = std::max(L1, L2);
4136 i128 R_intersect = std::min(R1, R2);
4137 u128 eq_count = std::max<i128>(0, R_intersect - L_intersect + 1);
4140 auto [lt_region1, lt_region2] = count_lt_regions(L1, R1, L2, R2);
4141 u128 lt_count = lt_region1 + lt_region2;
4143 u128 total = eq_count + lt_count;
4144 tgen_ensure(total > 0,
"pair: no valid values to generate");
4146 if (detail::next128(total) < eq_count)
4147 return gen_eq(L1, R1, L2, R2);
4148 return gen_lt(L1, R1, L2, R2);
4153template <
typename T> std::pair<T, T> gen_geq(T L1, T R1, T L2, T R2) {
4154 auto [first, second] = gen_leq(L2, R2, L1, R1);
4155 return {second, first};
4161
4162
4163
4164
4167 std::pair<T, T> first_, second_;
4169 enum class restriction_type { eq, neq, lt, gt, leq, geq, unspecified };
4170 restriction_type type_ = restriction_type::unspecified;
4174 pair(T first_left, T first_right, T second_left, T second_right)
4175 : first_(first_left, first_right), second_(second_left, second_right) {
4177 "pair: first range must be valid");
4179 "pair: second range must be valid");
4184 :
pair(both_left, both_right, both_left, both_right) {}
4188 type_ = restriction_type::eq;
4194 type_ = restriction_type::neq;
4200 type_ = restriction_type::lt;
4206 type_ = restriction_type::gt;
4212 type_ = restriction_type::leq;
4218 type_ = restriction_type::geq;
4224 using value_type = T;
4225 using std_type = std::pair<T, T>;
4227 std::pair<T, T> pair_;
4230 value(
const std::pair<T, T> &pair) : pair_(pair), sep_(
' ') {}
4232 : pair_(first, second), sep_(
' ') {}
4244 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4245 return out << val.pair_.first << val.sep_ << val.pair_.second;
4250 if constexpr (!detail::is_generator_value<T>::value) {
4253 std::pair<
typename T::std_type,
typename T::std_type> pair(
4254 pair_.first.to_std(), pair_.second.to_std());
4263 T L1 = first_.first, R1 = first_.second;
4264 T L2 = second_.first, R2 = second_.second;
4267 case restriction_type::unspecified:
4268 return {next<T>(L1, R1), next<T>(L2, R2)};
4269 case restriction_type::eq:
4270 return detail::gen_eq<T>(L1, R1, L2, R2);
4271 case restriction_type::neq:
4272 return detail::gen_neq<T>(L1, R1, L2, R2);
4273 case restriction_type::lt:
4274 return detail::gen_lt<T>(L1, R1, L2, R2);
4275 case restriction_type::gt:
4276 return detail::gen_gt<T>(L1, R1, L2, R2);
4277 case restriction_type::leq:
4278 return detail::gen_leq<T>(L1, R1, L2, R2);
4279 case restriction_type::geq:
4280 return detail::gen_geq<T>(L1, R1, L2, R2);
4282 throw detail::error(
"pair: unknown restriction type");
4287
4288
4289
4290
4296inline std::vector<std::pair<
int,
int>> edges_from_prufer(std::vector<
int> p) {
4297 int n = p.size() + 2;
4300 std::vector<
int> d(n, 1);
4309 idx = u = find(d.begin(), d.end(), 1) - d.begin();
4312 std::vector<std::pair<
int,
int>> edges;
4314 edges.emplace_back(u, v);
4315 if (--d[v] == 1
and v < idx)
4318 idx = u = find(d.begin() + idx + 1, d.end(), 1) - d.begin();
4325 std::vector<
int> parent_;
4326 std::vector<
unsigned char> rank_;
4331 dsu(
int n) : parent_(n), rank_(n, 0) {
4332 for (
int i = 0; i < n; ++i)
4338 void add_elements(
int k) {
4339 for (
int i = 0; i < k; ++i) {
4340 int new_id = parent_.size();
4341 parent_.push_back(new_id);
4349 return parent_[i] == i ? i : parent_[i] = find(parent_[i]);
4355 bool unite(
int a,
int b) {
4360 if (rank_[a] > rank_[b])
4363 if (rank_[a] == rank_[b])
4372template <
typename VWeight,
typename EWeight>
struct wgraph;
4375
4376
4377
4378
4379
4380
4381
4382
4384template <
typename VWeight,
typename EWeight>
4387 std::set<std::pair<
int,
int>> edges_;
4392 tgen_ensure(n > 0,
"wtree: number of vertices must be positive");
4398 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
4399 "wtree: vertices must be indexed in [0, n)");
4400 tgen_ensure(u != v,
"wtree: cannot add self loop to tree");
4404 edges_.emplace(u, v);
4416 std::vector<std::set<
int>> adj_;
4417 std::vector<std::pair<
int,
int>> edges_;
4418 bool print_1_based_;
4420 std::optional<
int> print_parents_;
4422 std::optional<std::vector<VWeight>> vertex_weights_;
4423 std::optional<std::vector<EWeight>>
4429 value(
const std::vector<std::set<
int>> &adj)
4430 : n_(
static_cast<
int>(adj.size())),
adj_(
adj),
4431 print_1_based_(
false), print_n_(
false),
dsu_(
n_) {
4432 for (
int u = 0; u < n_; ++u)
4433 for (
auto v : adj[u]) {
4436 "wtree: value: vertices must be indexed in [0, n)");
4439 edges_.emplace_back(u, v);
4442 "wtree: value: initial graph must form a tree");
4449 value(
int n,
const std::vector<std::pair<
int,
int>> &edges)
4450 : n_(n),
adj_(
n), print_1_based_(
false), print_n_(
false),
dsu_(
n) {
4451 edges_.reserve(edges.size());
4452 for (
auto [u, v] : edges) {
4453 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n,
4454 "wtree: value: vertices must be indexed in [0, n)");
4456 "wtree: value: initial graph must form a tree");
4459 edges_.emplace_back(u, v);
4464 value(
int n,
const std::set<std::pair<
int,
int>> &edges)
4467 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges)
4468 : value(n, std::vector<std::pair<
int,
int>>(edges)) {}
4473 value(
const typename wgraph<VWeight, EWeight>::value &g);
4477 template <
typename NewVWeight,
typename NewEWeight>
4478 typename wtree<NewVWeight, NewEWeight>::value
4479 convert_weight_types()
const {
4481 !edge_weights_.has_value(),
4482 "wtree: value: cannot convert weight type after "
4483 "assigning weights");
4485 typename wtree<NewVWeight, NewEWeight>::value new_tree(adj_);
4486 new_tree.print_1_based_ = print_1_based_;
4487 new_tree.print_n_ = print_n_;
4488 new_tree.print_parents_ = print_parents_;
4493 int n()
const {
return n_; }
4503 return vertex_weights_;
4508 return edge_weights_;
4513 template <
typename NewVWeight = VWeight>
4515 const std::vector<NewVWeight> &vertex_weights)
const {
4517 "wtree: value: must give `n` vertex weights");
4519 auto new_tree = convert_weight_types<NewVWeight, EWeight>();
4520 new_tree.vertex_weights_ = vertex_weights;
4526 template <
typename NewEWeight = EWeight>
4530 edge_weights.size() == edges().size(),
4531 "wtree: value: must give `edges().size()` edge weights");
4533 auto new_tree = convert_weight_types<VWeight, NewEWeight>();
4534 new_tree.edge_weights_ = edge_weights;
4542 "wtree: value: edge_weighted requires a tree with no "
4545 "wtree: value: tree is already edge-weighted");
4547 edge_weights_ = std::vector<EWeight>();
4555 print_1_based_ =
true;
4572 "wtree: value: root must be -1, `n`, or in [0, n)");
4573 print_parents_ = root;
4586 std::vector<
int> new_label(
n());
4587 std::vector<
int> shuffled;
4588 for (
int i = 0; i <
n(); ++i) {
4589 if (indices.count(i))
4592 shuffled.push_back(i);
4594 std::vector<
int> targets = shuffled;
4595 tgen::shuffle(targets.begin(), targets.end());
4596 for (size_t k = 0; k < shuffled.size(); ++k)
4597 new_label[shuffled[k]] = targets[k];
4600 std::vector<std::set<
int>> new_adj(
n());
4601 for (
int u = 0; u < n(); ++u)
4602 for (
int v : adj_[u])
4603 new_adj[new_label[u]].insert(new_label[v]);
4604 adj_ = std::move(new_adj);
4607 for (
auto &[u, v] : edges_) {
4615 if (vertex_weights_.has_value()) {
4616 std::vector<VWeight> new_vw(
n());
4617 for (
int i = 0; i < n(); ++i)
4618 new_vw[new_label[i]] = (*vertex_weights_)[i];
4619 vertex_weights_ = std::move(new_vw);
4623 dsu_ = detail::dsu(n());
4624 for (
auto [u, v] : edges_)
4629 std::vector<
int> perm(edges_.size());
4630 std::iota(perm.begin(), perm.end(), 0);
4631 tgen::shuffle(perm.begin(), perm.end());
4633 std::vector<std::pair<
int,
int>> new_edges;
4634 std::optional<std::vector<EWeight>> new_ew;
4635 if (edge_weights_.has_value())
4636 new_ew = std::vector<EWeight>();
4637 for (
int i : perm) {
4638 new_edges.push_back(edges_[i]);
4639 if (new_ew.has_value())
4640 new_ew->push_back((*edge_weights_)[i]);
4643 if (new_ew.has_value())
4644 edge_weights_ = new_ew;
4655 value &add_edge(
int u,
int v, std::optional<EWeight> w = std::nullopt) {
4657 "wtree: value: vertex ids must be valid");
4662 if (adj_[u].count(v))
4667 edges_.emplace_back(u, v);
4669 "wtree: value: added edge must not create a cycle");
4671 if (w.has_value()) {
4673 "wtree: value: cannot add weighted edge to "
4674 "edge-unweighted tree");
4676 edge_weights_->push_back(*w);
4679 "wtree: value: cannot add unweighted edge to "
4680 "edge-weighted tree");
4690 std::optional<EWeight> new_w = std::nullopt) {
4693 "wtree: value: vertex ids must be valid");
4697 add_vertices(rhs.n(), rhs.vertex_weights());
4698 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4699 auto [u, v] = rhs.edges()[i];
4700 add_edge(shift + u, shift + v,
4701 rhs.edge_weights().has_value()
4702 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4707 add_edge(new_u, shift + new_v, new_w);
4717 std::set<std::pair<
int,
int>> index_pairs) {
4719 std::set<
int> idx_left, idx_right;
4720 std::vector<
int> right_id_to_left(rhs
.n(), -1);
4721 for (
auto [l, r] : index_pairs) {
4723 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
4724 "wtree: value: vertex indices to glue must be valid");
4725 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
4726 "wtree: value: must not have repeated indices "
4727 "on the same side to glue");
4730 idx_right.insert(r);
4731 right_id_to_left[r] = l;
4735 std::vector<
int> new_right_id(rhs
.n(), -1);
4736 int intersection_lt = 0;
4737 std::optional<std::vector<VWeight>> rhs_vertex_weights;
4738 for (
int i = 0; i < rhs
.n(); ++i) {
4739 if (right_id_to_left[i] != -1) {
4742 new_right_id[i] = right_id_to_left[i];
4745 new_right_id[i] =
n() + i - intersection_lt;
4746 if (rhs.vertex_weights().has_value()) {
4747 if (!rhs_vertex_weights.has_value())
4748 rhs_vertex_weights = std::vector<VWeight>();
4749 rhs_vertex_weights->push_back(
4750 (*rhs.vertex_weights())[i]);
4756 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
4757 for (
int i = 0; i <
static_cast<
int>(rhs.edges().size()); ++i) {
4758 auto [u, v] = rhs.edges()[i];
4759 add_edge(new_right_id[u], new_right_id[v],
4760 rhs.edge_weights().has_value()
4761 ? std::optional<EWeight>((*rhs.edge_weights())[i])
4768 std::initializer_list<std::pair<
int,
int>> il) {
4769 return glue(rhs, std::set<std::pair<
int,
int>>(il));
4777 std::set<std::pair<
int,
int>> index_pairs;
4778 for (
auto i : indices)
4779 index_pairs.emplace(i, i);
4780 return glue(rhs, index_pairs);
4782 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
4783 return glue(rhs, std::set<
int>(il));
4788 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
4790 out << val.n() <<
'\n';
4793 if (val.vertex_weights()) {
4794 for (
int i = 0; i < val.n(); ++i) {
4797 out << (*val.vertex_weights())[i];
4802 tgen_ensure(
static_cast<
int>(val.edges().size()) == val.n() - 1,
4803 "wtree: value: invalid tree to print (number of edges "
4804 "must be `n` - 1)");
4807 if (val.print_parents_.has_value()) {
4809 "wtree: value: cannot print parent style if edges "
4812 int root = *val.print_parents_;
4813 bool skip_parent_0 = root == -1;
4816 if (root == val.n())
4817 root = next(0, val.n() - 1);
4819 std::vector<
int> parent(val.n(), -1);
4822 std::vector<
int> vis(val.n(),
false);
4829 for (
int v : val.adj()[u])
4837 if (skip_parent_0) {
4838 for (
int i = 1; i < val.n(); ++i) {
4841 "wtree: value: parent of i must be less than i for "
4842 "printing in parent style if root is -1");
4846 out << parent[i] + val.print_1_based_;
4849 for (
int i = 0; i < val.n(); ++i) {
4852 out << (parent[i] == -1 ? -1 : parent[i]) +
4862 for (
int i = 0; i <
static_cast<
int>(val.edges().size()); ++i) {
4863 auto [u, v] = val.edges()[i];
4864 out << (u + val.print_1_based_) <<
" "
4865 << (v + val.print_1_based_);
4868 if (val.edge_weights().has_value())
4869 out <<
" " << (*val.edge_weights())[i];
4880 return std_type(n_, adj_);
4886 std::vector<std::set<
int>> adj(n_ + 1);
4887 for (
int u = 0; u < n_; ++u)
4888 for (
int v : adj_[u])
4889 adj[u + 1].insert(v + 1);
4890 return std_type(n_, adj);
4897 value &add_vertices(
int k, std::optional<std::vector<VWeight>>
4898 new_vertex_weights = std::nullopt) {
4901 if (new_vertex_weights.has_value()) {
4903 "wtree: value: cannot add weighted vertices to "
4904 "vertex-unweighted tree");
4906 static_cast<
int>(new_vertex_weights->size()) == k,
4907 "wtree: value: number of vertex weights must be equal "
4908 "to number of added vertices");
4910 vertex_weights_->insert(vertex_weights_->end(),
4911 new_vertex_weights->begin(),
4912 new_vertex_weights->end());
4915 "wtree: value: cannot add unweighted vertices to "
4916 "vertex-weighted tree");
4918 dsu_.add_elements(k);
4928 std::vector<std::vector<
int>> adj(n_);
4929 for (
auto [u, v] : edges_) {
4930 adj[u].push_back(v);
4931 adj[v].push_back(u);
4934 std::vector<
int> comp_size;
4935 std::vector<std::vector<
int>> component_ids;
4936 std::vector<
bool> vis(n_,
false);
4939 for (
int i = 0; i < n_; ++i) {
4945 comp_size.push_back(0);
4946 component_ids.emplace_back();
4951 component_ids.back().push_back(u);
4952 for (
int v : adj[u]) {
4963 std::vector<std::pair<
int,
int>> new_edges(edges_.begin(),
4965 if (comp_size.size() > 1) {
4966 std::vector<
int> prufer_values =
4967 many_by_distribution(comp_size.size() - 2, comp_size);
4968 for (
auto [u, v] : detail::edges_from_prufer(prufer_values))
4969 new_edges.emplace_back(pick(component_ids[u]),
4970 pick(component_ids[v]));
4973 return value(n_, new_edges);
4984 std::vector<std::pair<
int,
int>> edges;
4985 for (
int i = 1; i < n; ++i)
4986 edges.emplace_back(i, wnext<
int>(i, elongation));
4987 return value(n, edges);
4994 tgen_ensure(n > 0,
"wtree: gen_kruskal: n must be positive");
4996 return value(1, {});
4998 detail::dsu components(n);
4999 std::vector<std::pair<
int,
int>> edges;
5000 edges.reserve(n - 1);
5001 while (edges.size() < size_t(n - 1)) {
5002 int u = next(0, n - 1);
5003 int v = next(0, n - 1);
5006 if (components.unite(u, v))
5007 edges.emplace_back(u, v);
5009 return value(n, edges);
5014
5015
5027
5028
5029
5030
5036inline uint64_t undirected_edge_key(
int u,
int v) {
5039 return (
static_cast<uint64_t>(u) << 32) |
5040 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5045inline uint64_t directed_edge_key(
int u,
int v) {
5046 return (
static_cast<uint64_t>(u) << 32) |
5047 static_cast<uint64_t>(
static_cast<uint32_t>(v));
5052inline long long max_graph_edges(
int n,
bool directed,
bool self_loops) {
5056 return self_loops ?
static_cast<
long long>(n) * n
5057 :
static_cast<
long long>(n) * (n - 1);
5058 return self_loops ?
static_cast<
long long>(n) * (n + 1) / 2
5059 :
static_cast<
long long>(n) * (n - 1) / 2;
5064inline std::pair<
int,
int> get_random_graph_edge(
int n,
bool directed,
5068 return {next<
int>(0, n - 1), next<
int>(0, n - 1)};
5069 int u = next<
int>(0, n - 1);
5070 int v = next<
int>(0, n - 1);
5072 v = next<
int>(0, n - 1);
5076 int u = next<
int>(0, n - 1);
5077 int v = next<
int>(0, n - 1);
5082 int u = next<
int>(0, n - 1);
5083 int v = next<
int>(0, n - 1);
5085 v = next<
int>(0, n - 1);
5094inline std::pair<
int,
int> decode_undirected_simple_edge(
int n,
long long idx) {
5095 auto base = [&](
int u) ->
long long {
5096 return static_cast<
long long>(u) * (n - 1) -
5097 static_cast<
long long>(u) * (u - 1) / 2;
5099 int lo = 0, hi = n - 2;
5101 int mid = (lo + hi + 1) / 2;
5102 if (base(mid) <= idx)
5107 return {lo, lo + 1 +
int(idx - base(lo))};
5113inline std::pair<
int,
int> decode_undirected_loops_edge(
int n,
long long idx) {
5114 auto base = [&](
int u) ->
long long {
5115 return static_cast<
long long>(u) * n -
5116 static_cast<
long long>(u) * (u - 1) / 2;
5118 int lo = 0, hi = n - 1;
5120 int mid = (lo + hi + 1) / 2;
5121 if (base(mid) <= idx)
5126 return {lo, lo +
int(idx - base(lo))};
5131inline std::pair<
int,
int> decode_directed_simple_edge(
int n,
long long idx) {
5132 int u = idx / (n - 1);
5133 int rem = idx % (n - 1);
5134 return {u, rem + (rem >= u)};
5139inline std::pair<
int,
int>
5140decode_graph_edge_index(
int n,
long long idx,
bool directed,
bool self_loops) {
5143 return {
int(idx / n),
int(idx % n)};
5144 return decode_directed_simple_edge(n, idx);
5147 return decode_undirected_loops_edge(n, idx);
5148 return decode_undirected_simple_edge(n, idx);
5154
5155
5156
5157
5158
5159
5160
5161
5163template <
typename VWeight,
typename EWeight>
5166 std::set<std::pair<
int,
int>> edges_;
5168 bool has_self_loops_;
5174 wgraph(
int n,
int m,
bool is_directed =
false,
bool has_self_loops =
false)
5175 : n_(n), m_(m), is_directed_(is_directed),
5176 has_self_loops_(has_self_loops) {
5177 tgen_ensure(n > 0,
"wgraph: number of vertices must be positive");
5183 tgen_ensure(0 <= std::min(u, v)
and std::max(u, v) < n_,
5184 "wgraph: vertices must be indexed in [0, n)");
5186 if (!is_directed_
and u > v)
5188 edges_.emplace(u, v);
5189 tgen_ensure(
static_cast<
int>(edges_.size()) <= m_,
5190 "wgraph: too many edges were added");
5204 std::vector<std::set<
int>> adj_;
5205 std::vector<std::pair<
int,
int>> edges_;
5207 bool print_1_based_;
5209 mutable bool adj_built_{
5212 std::optional<std::vector<VWeight>> vertex_weights_;
5213 std::optional<std::vector<EWeight>>
5219 value(
const std::vector<std::set<
int>> &adj,
bool is_directed =
false)
5220 : n_(
static_cast<
int>(adj.size())),
adj_(
adj),
5221 is_directed_(is_directed), print_1_based_(
false),
5222 print_nm_(
false), adj_built_(
true) {
5223 for (
int u = 0; u < n_; ++u)
5224 for (
auto v : adj[u]) {
5227 "wgraph: value: vertices must be indexed in [0, n)");
5231 if (is_directed_
or u <= v)
5232 edges_.emplace_back(u, v);
5240 value(
int n,
const std::vector<std::pair<
int,
int>> &edges = {},
5241 bool is_directed =
false)
5242 : n_(n),
edges_(), is_directed_(is_directed), print_1_based_(
false),
5243 print_nm_(
false), adj_built_(
false) {
5244 edges_.reserve(edges.size());
5245 std::unordered_set<uint64_t> seen;
5246 seen.reserve(edges.size() * 2 + 1);
5247 for (
auto [u, v] : edges) {
5249 0 <= std::min(u, v)
and std::max(u, v) < n,
5250 "wgraph: value: vertices must be indexed in [0, n)");
5251 if (!is_directed_
and u > v)
5253 uint64_t key = is_directed_ ? detail::directed_edge_key(u, v)
5254 : detail::undirected_edge_key(u, v);
5255 if (seen.insert(key).second)
5256 edges_.emplace_back(u, v);
5259 value(
int n,
const std::set<std::pair<
int,
int>> &edges,
5260 bool is_directed =
false)
5265 value(
int n,
const std::initializer_list<std::pair<
int,
int>> &edges,
5266 bool is_directed =
false)
5267 : value(n, std::vector<std::pair<
int,
int>>(edges), is_directed) {}
5272 :
value(t.n(), t.edges(),
false) {
5273 if (t.vertex_weights().has_value()) {
5274 vertex_weights_ = *t.vertex_weights();
5276 if (t.edge_weights().has_value()) {
5277 edge_weights_ = *t.edge_weights();
5283 template <
typename NewVWeight,
typename NewEWeight>
5284 typename wgraph<NewVWeight, NewEWeight>::value
5285 convert_weight_types()
const {
5287 !edge_weights_.has_value(),
5288 "wgraph: value: cannot convert weight type after "
5289 "assigning weights");
5292 typename wgraph<NewVWeight, NewEWeight>::value new_graph(
5293 adj_, is_directed_);
5294 new_graph.is_directed_ = is_directed_;
5295 new_graph.print_1_based_ = print_1_based_;
5296 new_graph.print_nm_ = print_nm_;
5301 int n()
const {
return n_; }
5304 int m()
const {
return edges_.size(); }
5320 return vertex_weights_;
5325 return edge_weights_;
5330 template <
typename NewVWeight = VWeight>
5332 const std::vector<NewVWeight> &vertex_weights)
const {
5334 "wgraph: value: must give `n` vertex weights");
5336 auto new_graph = convert_weight_types<NewVWeight, EWeight>();
5337 new_graph.vertex_weights_ = vertex_weights;
5343 template <
typename NewEWeight = EWeight>
5347 "wgraph: value: must give `m` edge weights");
5349 auto new_graph = convert_weight_types<VWeight, NewEWeight>();
5350 new_graph.edge_weights_ = edge_weights;
5358 "wgraph: value: edge_weighted requires a graph with no "
5361 "wgraph: value: graph is already edge-weighted");
5363 edge_weights_ = std::vector<EWeight>();
5371 print_1_based_ =
true;
5392 std::vector<
int> new_label(
n());
5393 std::vector<
int> shuffled;
5394 for (
int i = 0; i <
n(); ++i) {
5395 if (indices.count(i))
5398 shuffled.push_back(i);
5400 std::vector<
int> targets = shuffled;
5401 tgen::shuffle(targets.begin(), targets.end());
5402 for (size_t k = 0; k < shuffled.size(); ++k)
5403 new_label[shuffled[k]] = targets[k];
5406 std::vector<std::set<
int>> new_adj(
n());
5407 for (
int u = 0; u < n(); ++u)
5408 for (
int v : adj_[u])
5409 new_adj[new_label[u]].insert(new_label[v]);
5413 for (
auto &[u, v] : edges_) {
5416 if (!is_directed_
and u > v)
5421 if (vertex_weights_.has_value()) {
5422 std::vector<VWeight> new_vw(
n());
5423 for (
int i = 0; i < n(); ++i)
5424 new_vw[new_label[i]] = (*vertex_weights_)[i];
5425 vertex_weights_ = new_vw;
5430 std::vector<
int> perm(edges_.size());
5431 std::iota(perm.begin(), perm.end(), 0);
5432 tgen::shuffle(perm.begin(), perm.end());
5434 std::vector<std::pair<
int,
int>> new_edges;
5435 std::optional<std::vector<EWeight>> new_ew;
5436 if (edge_weights_.has_value())
5437 new_ew = std::vector<EWeight>();
5438 for (
int i : perm) {
5439 new_edges.push_back(edges_[i]);
5440 if (new_ew.has_value())
5441 new_ew->push_back((*edge_weights_)[i]);
5445 if (new_ew.has_value())
5446 edge_weights_ = new_ew;
5459 new_vertex_weights = std::nullopt) {
5463 if (new_vertex_weights.has_value()) {
5465 "wgraph: value: cannot add weighted vertices to "
5466 "vertex-unweighted graph");
5468 static_cast<
int>(new_vertex_weights->size()) == k,
5469 "wgraph: value: number of vertex weights must be equal "
5470 "to number of added vertices");
5472 vertex_weights_->insert(vertex_weights_->end(),
5473 new_vertex_weights->begin(),
5474 new_vertex_weights->end());
5477 "wgraph: value: cannot add unweighted vertices to "
5478 "vertex-weighted graph");
5488 "wgraph: value: vertex ids must be valid");
5493 if (adj_[u].count(v))
5499 edges_.emplace_back(u, v);
5501 if (w.has_value()) {
5503 "wgraph: value: cannot add weighted edge to "
5504 "edge-unweighted graph");
5506 edge_weights_->push_back(*w);
5509 "wgraph: value: cannot add unweighted edge to "
5510 "edge-weighted graph");
5520 std::optional<EWeight> new_w = std::nullopt) {
5523 "wgraph: value: vertex ids must be valid");
5527 add_vertices(rhs.n(), rhs.vertex_weights());
5528 for (
int i = 0; i < rhs
.m(); ++i) {
5529 auto [u, v] = rhs.edges()[i];
5531 rhs.edge_weights().has_value()
5532 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5547 std::set<std::pair<
int,
int>> index_pairs) {
5550 "wgraph: value: graphs must have the same is_directed value");
5553 std::set<
int> idx_left, idx_right;
5554 std::vector<
int> right_id_to_left(rhs
.n(), -1);
5555 for (
auto [l, r] : index_pairs) {
5557 0 <= l
and l < n()
and 0 <= r
and r < rhs.n(),
5558 "wgraph: value: vertex indices to glue must be valid");
5559 tgen_ensure(idx_left.count(l) == 0
and idx_right.count(r) == 0,
5560 "wgraph: value: must not have repeated indices "
5561 "on the same side to glue");
5564 idx_right.insert(r);
5565 right_id_to_left[r] = l;
5569 std::vector<
int> new_right_id(rhs
.n(), -1);
5570 int intersection_lt = 0;
5571 std::optional<std::vector<VWeight>> rhs_vertex_weights;
5572 for (
int i = 0; i < rhs
.n(); ++i) {
5573 if (right_id_to_left[i] != -1) {
5576 new_right_id[i] = right_id_to_left[i];
5579 new_right_id[i] =
n() + i - intersection_lt;
5580 if (rhs.vertex_weights().has_value()) {
5581 if (!rhs_vertex_weights.has_value())
5582 rhs_vertex_weights = std::vector<VWeight>();
5583 rhs_vertex_weights->push_back(
5584 (*rhs.vertex_weights())[i]);
5590 add_vertices(rhs.n() - intersection_lt, rhs_vertex_weights);
5591 for (
int i = 0; i < rhs
.m(); ++i) {
5592 auto [u, v] = rhs.edges()[i];
5594 rhs.edge_weights().has_value()
5595 ? std::optional<EWeight>((*rhs.edge_weights())[i])
5602 std::initializer_list<std::pair<
int,
int>> il) {
5603 return glue(rhs, std::set<std::pair<
int,
int>>(il));
5611 std::set<std::pair<
int,
int>> index_pairs;
5612 for (
auto i : indices)
5613 index_pairs.emplace(i, i);
5614 return glue(rhs, index_pairs);
5616 value &glue(
const value &rhs,
const std::initializer_list<
int> &il) {
5617 return glue(rhs, std::set<
int>(il));
5624 return glue(rhs, std::set<
int>());
5632 "wgraph: value: can choose at most `m` edges from graph");
5634 std::vector<std::pair<
int,
int>> new_edges;
5635 std::optional<std::vector<EWeight>> new_edge_weights;
5638 for (
int i = 0; i <
m(); ++i) {
5639 if (next(1, left--) <= num_edges) {
5640 new_edges.push_back(edges()[i]);
5641 if (edge_weights_.has_value()) {
5642 if (!new_edge_weights.has_value())
5643 new_edge_weights = std::vector<EWeight>();
5644 new_edge_weights->push_back((*edge_weights())[i]);
5651 edge_weights_ = new_edge_weights;
5652 rebuild_adj_from_edge_list();
5664 "wgraph: value: random_connected_subgraph is only for "
5665 "undirected graphs");
5668 "wgraph: value: can choose at most `m` edges from graph");
5672 std::vector<std::vector<std::pair<
int,
int>>> incident(
n());
5673 for (
int i = 0; i <
m(); ++i) {
5674 auto [u, v] = edges_[i];
5675 incident[u].emplace_back(v, i);
5676 incident[v].emplace_back(u, i);
5680 std::vector<
bool> vis(
n(),
false);
5681 std::vector<
int> queue;
5682 std::vector<
bool> in_tree(
m(),
false);
5683 int forest_edges = 0;
5685 for (
int start = 0; start <
n(); ++start) {
5689 queue.push_back(start);
5691 while (!queue.empty()) {
5692 int i = tgen::next<
int>(0, queue.size() - 1);
5694 std::swap(queue[i], queue.back());
5697 for (
auto [v, edge_idx] : incident[u]) {
5701 in_tree[edge_idx] =
true;
5708 num_edges >= forest_edges,
5709 "wgraph: value: random_connected_subgraph needs at least "
5710 "`n - c` edges, where `c` is the number of connected "
5714 std::vector<
int> tree_idx, rest_idx;
5715 for (
int i = 0; i <
m(); ++i) {
5717 tree_idx.push_back(i);
5719 rest_idx.push_back(i);
5722 tgen::shuffle(rest_idx.begin(), rest_idx.end());
5724 std::vector<
int> chosen_idx;
5725 chosen_idx.insert(chosen_idx.end(), tree_idx.begin(),
5727 chosen_idx.insert(chosen_idx.end(), rest_idx.begin(),
5728 rest_idx.begin() + num_edges - forest_edges);
5730 detail::tgen_ensure_against_bug(
5731 static_cast<
int>(chosen_idx.size()) == num_edges,
5732 "wgraph: value: chose a wrong number of edges");
5734 std::vector<std::pair<
int,
int>> new_edges;
5735 std::optional<std::vector<EWeight>> new_edge_weights;
5736 if (edge_weights_.has_value())
5737 new_edge_weights = std::vector<EWeight>();
5738 for (
int i : chosen_idx) {
5739 new_edges.push_back(edges_[i]);
5740 if (new_edge_weights.has_value())
5741 new_edge_weights->push_back((*edge_weights_)[i]);
5745 edge_weights_ = new_edge_weights;
5746 rebuild_adj_from_edge_list();
5754 "wgraph: value: cannot compute complement of "
5755 "edge-weighted graph");
5757 value complement = *
this;
5758 complement.ensure_adj_built();
5759 std::vector<std::pair<
int,
int>> compl_edges;
5760 for (
int i = 0; i < complement.n_; ++i) {
5761 std::set<
int> complement_adj;
5762 for (
int j = 0; j < complement.n_; ++j) {
5764 if (j == i
and complement.adj_[i].count(j))
5766 if (j != i
and !complement.adj_[i].count(j))
5770 complement_adj.insert(j);
5772 if (i <= j
or complement.is_directed_) {
5773 compl_edges.emplace_back(i, j);
5777 std::swap(complement.adj_[i], complement_adj);
5779 std::swap(complement.edges_, compl_edges);
5788 "wgraph: value: graphs must have the same "
5789 "is_directed value");
5792 rhs.vertex_weights().has_value(),
5793 "wgraph: value: cannot concatenate vertex-weighted "
5794 "wgraph to unweighted");
5796 rhs.edge_weights().has_value(),
5797 "wgraph: value: cannot concatenate edge-weighted "
5798 "wgraph to unweighted");
5800 value concat = *
this;
5801 concat.glue(rhs, std::set<std::pair<
int,
int>>());
5802 concat.print_1_based_ = print_1_based_ | rhs.print_1_based_;
5803 concat.print_nm_ = print_nm_ | rhs.print_nm_;
5810 friend std::ostream &operator<<(std::ostream &out,
const value &val) {
5813 out << val.n() <<
" " << val.m() <<
'\n';
5816 if (val.vertex_weights()) {
5817 for (
int i = 0; i < val.n(); ++i) {
5820 out << (*val.vertex_weights())[i];
5826 for (
int i = 0; i < val.m(); ++i) {
5827 auto [u, v] = val.edges()[i];
5828 out << (u + val.print_1_based_) <<
" "
5829 << (v + val.print_1_based_);
5832 if (val.edge_weights().has_value())
5833 out <<
" " << (*val.edge_weights())[i];
5845 return std_type(n_, m(), adj_);
5853 std::vector<std::set<
int>> adj(n_ + 1);
5854 for (
int u = 0; u < n_; ++u)
5855 for (
int v : adj_[u])
5856 adj[u + 1].insert(v + 1);
5857 return std_type(n_,
m(), adj);
5864 void rebuild_adj_from_edge_list() {
5865 adj_.assign(n_, {});
5866 for (
auto [u, v] : edges_) {
5876 void ensure_adj_built()
const {
5879 const_cast<
value *>(
this)->rebuild_adj_from_edge_list();
5887 "wgraph: graphs must have the same is_directed value");
5889 for (
auto [u, v] : rhs.edges())
5899 detail::tgen_ensure_against_bug(
static_cast<
int>(edges_.size()) <= m_,
5900 "wgraph: too many edges were added");
5903 if (
static_cast<
int>(edges_.size()) == m_)
5904 return value(n_, edges_, is_directed_);
5909 if (
auto indexed = try_gen_by_edge_index())
5913 return gen_remaining_edges(
5914 std::vector<std::pair<
int,
int>>(edges_.begin(), edges_.end()));
5924 "wgraph: get_connected is only for undirected graphs");
5926 "wgraph: connected graph needs at least n - 1 edges");
5928 std::vector<std::pair<
int,
int>> edges;
5931 if (edges_.empty()) {
5933 std::vector<
int> prufer(n_ - 2);
5934 for (
int i = 0; i < n_ - 2; ++i)
5935 prufer[i] = next<
int>(0, n_ - 1);
5936 for (
auto [u, v] : detail::edges_from_prufer(std::move(prufer)))
5937 edges.emplace_back(u, v);
5940 edges.assign(edges_.begin(), edges_.end());
5942 std::vector<std::vector<
int>> adj(n_);
5943 for (
auto [u, v] : edges_) {
5944 adj[u].push_back(v);
5945 adj[v].push_back(u);
5948 std::vector<
int> comp_size;
5949 std::vector<std::vector<
int>> component_ids;
5950 std::vector<
bool> vis(n_,
false);
5953 for (
int i = 0; i < n_; ++i) {
5959 comp_size.push_back(0);
5960 component_ids.emplace_back();
5965 component_ids.back().push_back(u);
5966 for (
int v : adj[u]) {
5975 if (component_ids.size() > 1) {
5976 std::vector<
int> prufer_values =
5977 many_by_distribution(component_ids.size() - 2, comp_size);
5979 detail::edges_from_prufer(std::move(prufer_values)))
5980 edges.emplace_back(pick(component_ids[u]),
5981 pick(component_ids[v]));
5985 return gen_remaining_edges(std::move(edges));
5998 "wgraph: get_acyclic is only for directed graphs");
6000 if (edges_.empty()) {
6001 std::vector<
int> order(n_);
6002 std::iota(order.begin(), order.end(), 0);
6003 for (
int i = n_ - 1; i > 0; --i)
6004 std::swap(order[i], order[next(0, i)]);
6006 const long long max_pairs =
6007 static_cast<
long long>(n_) * (n_ - 1) / 2;
6009 "wgraph: not enough edges to generate");
6011 std::vector<std::pair<
int,
int>> edges;
6013 for (
long long idx : distinct_range<
long long>(0, max_pairs - 1)
6016 auto [i, j] = detail::decode_undirected_simple_edge(n_, idx);
6017 edges.emplace_back(order[i], order[j]);
6019 return value(n_, edges,
true);
6022 std::vector<std::vector<
int>> adj(n_);
6023 std::vector<
int> indeg(n_, 0);
6024 for (
auto [u, v] : edges_) {
6025 adj[u].push_back(v);
6029 std::vector<
int> available;
6030 for (
int i = 0; i < n_; ++i)
6032 available.push_back(i);
6035 std::vector<
int> order;
6036 while (!available.empty()) {
6037 int idx = next(0,
static_cast<
int>(available.size()) - 1);
6038 int u = available[idx];
6039 std::swap(available[idx], available.back());
6040 available.pop_back();
6043 for (
int v : adj[u])
6044 if (--indeg[v] == 0)
6045 available.push_back(v);
6049 "wgraph: preset edges contain a directed cycle");
6051 value acyclic(n_, edges_,
true);
6055 detail::tgen_ensure_against_bug(acyclic.m() <= m_,
6056 "wgraph: too many edges were added");
6058 if (acyclic.m() < m_) {
6059 std::vector<
int> order_pos(n_);
6060 for (
int i = 0; i < n_; ++i)
6061 order_pos[order[i]] = i;
6063 std::unordered_set<uint64_t> seen;
6064 seen.reserve(m_ * 2);
6065 for (
auto [u, v] : acyclic.edges())
6067 detail::undirected_edge_key(order_pos[u], order_pos[v]));
6069 const long long max_pairs =
6070 static_cast<
long long>(n_) * (n_ - 1) / 2;
6071 while (acyclic.m() < m_) {
6072 std::pair<
int,
int> edge;
6073 if (!detail::try_generate_distinct(seen, [&] {
6074 long long idx = next<
long long>(0, max_pairs - 1);
6075 edge = detail::decode_undirected_simple_edge(n_, idx);
6076 return detail::undirected_edge_key(edge.first,
6079 throw detail::error(
"wgraph: not enough edges to generate");
6080 acyclic.add_edge(order[edge.first], order[edge.second]);
6100 bool is_directed =
false) {
6103 "wgraph: skewed graph needs at least n - 1 edges to be connected");
6105 "wgraph: gen_skewed spread must be at least 2");
6107 value skewed(n, {}, is_directed);
6109 std::vector<
int> parent(n), depth(n, 0);
6111 for (
int i = 1; i < n; ++i) {
6112 int p = wnext<
int>(i, elongation);
6114 depth[i] = depth[p] + 1;
6115 skewed.add_edge(p, i);
6118 const int extra = m - (n - 1);
6125 constexpr int naive_ancestor_spread = 20;
6127 if (spread <= naive_ancestor_spread) {
6128 std::vector<std::pair<
int,
int>> candidates;
6129 candidates.reserve(n * spread);
6130 for (
int u = 0; u < n; ++u) {
6131 int max_k = std::min(spread, depth[u]);
6135 for (
int k = 2; k <= max_k; ++k) {
6137 candidates.emplace_back(v, u);
6141 tgen_ensure(extra <=
static_cast<
int>(candidates.size()),
6142 "wgraph: not enough edges to generate");
6144 for (
auto [v, u] : choose(candidates, extra))
6145 skewed.add_edge(v, u);
6149 while ((1 << lg) <= n)
6152 std::vector<std::vector<
int>> up(lg, std::vector<
int>(n));
6153 for (
int v = 0; v < n; ++v)
6154 up[0][v] = parent[v];
6155 for (
int j = 1; j < lg; ++j)
6156 for (
int v = 0; v < n; ++v)
6157 up[j][v] = up[j - 1][up[j - 1][v]];
6163 std::vector<
int> distribution = depth;
6164 for (
int &d : distribution)
6165 d = std::max(0, std::min(spread - 1, d - 1));
6167 distinct extra_edges([&]() -> std::pair<
int,
int> {
6168 int u = vertex_choice.next();
6169 int k = next(2, spread);
6171 for (
int j = 0; j < lg; ++j)
6177 while (skewed.m() < m) {
6178 std::pair<
int,
int> edge;
6180 edge = extra_edges.gen();
6181 }
catch (
const std::runtime_error &e) {
6182 if (std::string(e.what()) ==
6183 "tgen: distinct: no more distinct values")
6184 throw detail::error(
6185 "wgraph: not enough edges to generate");
6189 skewed.add_edge(edge.first, edge.second);
6203 tgen_ensure(m >= 0,
"wgraph: number of edges must be nonnegative");
6204 long long num_edges = 1LL * n1 * n2;
6206 "wgraph: bipartite graph has at most n1 * n2 edges");
6210 "wgraph: connected bipartite graph needs at least n1 + n2 - 1 "
6214 std::vector<std::pair<
int,
int>> edges;
6216 for (
long long idx : distinct_range<
long long>(0, num_edges - 1)
6219 edges.emplace_back(
static_cast<
int>(idx / n2),
6220 n1 +
static_cast<
int>(idx % n2));
6221 return value(n1 + n2, std::move(edges),
false);
6224 std::unordered_set<uint64_t> used_edges;
6225 used_edges.reserve(m * 2);
6226 std::vector<std::pair<
int,
int>> edges;
6229 auto pack_edge = [](
int u,
int v) -> uint64_t {
6232 return (
static_cast<uint64_t>(u) << 32) |
static_cast<uint32_t>(v);
6235 if (n1 > 0
and n2 > 0) {
6236 std::vector<
int> prufer(n1 + n2 - 2);
6237 for (
int i = 0; i < n2 - 1; ++i)
6238 prufer[i] = next(0, n1 - 1);
6239 for (
int i = 0; i < n1 - 1; ++i)
6240 prufer[n2 - 1 + i] = next(n1, n1 + n2 - 1);
6241 shuffle(prufer.begin(), prufer.end());
6242 for (
auto [u, v] : detail::edges_from_prufer(std::move(prufer))) {
6245 if (used_edges.insert(pack_edge(u, v)).second)
6246 edges.emplace_back(u, v);
6248 detail::tgen_ensure_against_bug(
6249 used_edges.size() == size_t(n1 + n2 - 1),
6250 "wgraph: invalid bipartite spanning tree size");
6253 while (edges.size() < size_t(m)) {
6254 int u = next(0, n1 - 1);
6255 int v = next(n1, n1 + n2 - 1);
6256 if (used_edges.insert(pack_edge(u, v)).second)
6257 edges.emplace_back(u, v);
6260 return value(n1 + n2, std::move(edges),
false);
6269 bool has_self_loops =
false) {
6270 tgen_ensure(n > 0,
"wgraph: number of vertices must be positive");
6271 tgen_ensure(p >= 0
and p <= 1,
"wgraph: probability must be in [0, 1]");
6273 long long max_edges =
6274 detail::max_graph_edges(n, is_directed, has_self_loops);
6280 for (
long long i = 0; i < max_edges; ++i)
6281 if (next<
double>(0.0, 1.0) < p)
6285 "wgraph: too many edges to generate");
6286 return wgraph(n,
static_cast<
int>(m), is_directed, has_self_loops)
6296 std::optional<
value> try_gen_by_edge_index()
const {
6297 if (!edges_.empty())
6298 return std::nullopt;
6300 long long max_edges =
6301 detail::max_graph_edges(n_, is_directed_, has_self_loops_);
6303 throw detail::error(
"wgraph: not enough edges to generate");
6304 if (max_edges <= 0
or 2LL * m_ <= max_edges)
6305 return std::nullopt;
6307 std::vector<std::pair<
int,
int>> edges;
6309 for (
long long idx :
6310 distinct_range<
long long>(0, max_edges - 1).gen_list(m_).to_std())
6311 edges.push_back(detail::decode_graph_edge_index(
6312 n_, idx, is_directed_, has_self_loops_));
6314 return value(n_, edges, is_directed_);
6320 value gen_remaining_edges(std::vector<std::pair<
int,
int>> edges)
const {
6321 detail::tgen_ensure_against_bug(
static_cast<
int>(edges.size()) <= m_,
6322 "wgraph: too many edges were added");
6324 if (
static_cast<
int>(edges.size()) == m_)
6325 return value(n_, edges, is_directed_);
6329 std::unordered_set<uint64_t> seen;
6330 seen.reserve(m_ * 2);
6331 for (
auto [u, v] : edges) {
6332 if (!is_directed_
and u > v)
6334 seen.insert(is_directed_ ? detail::directed_edge_key(u, v)
6335 : detail::undirected_edge_key(u, v));
6338 while (
static_cast<
int>(edges.size()) < m_) {
6339 std::pair<
int,
int> edge;
6340 if (!detail::try_generate_distinct(seen, [&] {
6341 edge = detail::get_random_graph_edge(n_, is_directed_,
6343 if (!is_directed_
and edge.first > edge.second)
6344 std::swap(edge.first, edge.second);
6345 return is_directed_ ? detail::directed_edge_key(edge.first,
6347 : detail::undirected_edge_key(
6348 edge.first, edge.second);
6350 throw detail::error(
"wgraph: not enough edges to generate");
6351 edges.emplace_back(edge);
6354 return value(n_, edges, is_directed_);
6360template <
typename VWeight,
typename EWeight>
6362 const typename wgraph<VWeight, EWeight>::value &g)
6363 : n_(g.n()),
adj_(
g.
n()), print_1_based_(
false), print_n_(
false),
6365 tgen_ensure(g.n() > 0,
"wtree: value: graph must have at least one vertex");
6367 "wtree: value: graph must be undirected to form a tree");
6369 if (g.vertex_weights().has_value())
6370 vertex_weights_ = *g.vertex_weights();
6371 if (g.edge_weights().has_value())
6372 edge_weights_ = std::vector<EWeight>();
6377 std::vector<
int> order(g.m());
6378 std::iota(order.begin(), order.end(), 0);
6379 tgen::shuffle(order.begin(), order.end());
6381 std::vector<std::pair<
int,
int>> tree_edges;
6382 tree_edges.reserve(n_ - 1);
6384 for (
int i : order) {
6385 auto [u, v] = g.edges()[i];
6386 if (!dsu_.unite(u, v))
6391 tree_edges.emplace_back(u, v);
6394 if (edge_weights_.has_value())
6395 edge_weights_->push_back((*g.edge_weights())[i]);
6396 if (
static_cast<
int>(tree_edges.size()) == n_ - 1)
6400 tgen_ensure(
static_cast<
int>(tree_edges.size()) == n_ - 1,
6401 "wtree: value: graph must be connected to form a tree");
6403 edges_ = std::move(tree_edges);
6407
6408
6420
6421
6425inline graph::
value K(
int n) {
return graph(n, n * (n - 1) / 2).gen(); }
6432 graph g(n, n - 1, is_directed);
6433 for (
int i = 0; i + 1 < n; ++i)
6434 g.add_edge(i, i + 1);
6443 tgen_ensure(n >= 3,
"graph: cycle size must be at least 3");
6445 graph g(n, n, is_directed);
6446 for (
int i = 0; i < n; ++i)
6447 g.add_edge(i, (i + 1) % n);
6456 graph g(n1 + n2,
static_cast<
long long>(n1) * n2);
6457 for (
int i = 0; i < n1; ++i)
6458 for (
int j = 0; j < n2; ++j)
6459 g.add_edge(i, n1 + j);
6469
6470
6471
6472
6478 static_assert(std::is_arithmetic_v<T>,
6479 "point requires an arithmetic coordinate type");
6491 point(T x = 0, T y = 0) : x_(x), y_(y) {}
6494 T
x()
const {
return x_; }
6497 T
y()
const {
return y_; }
6501 static bool coord_eq(T a, T b) {
6502 if constexpr (std::is_integral_v<T>)
6504 constexpr T eps = T(1e-9);
6506 return d >= -eps
and d <= eps;
6511 if (!coord_eq(x_, p
.x()))
6518 return coord_eq(x_, p
.x())
and coord_eq(y_, p
.y());
6536 if constexpr (std::is_floating_point_v<T>)
6538 return product_t(x_) * p
.x() + product_t(y_) * p
.y();
6543 if constexpr (std::is_floating_point_v<T>)
6545 return product_t(x_) * p
.y() - product_t(y_) * p
.x();
6549 friend std::ostream &operator<<(std::ostream &out,
const point &p) {
6550 return out << p
.x() <<
' ' << p
.y();
6559 long long max_coord) {
6561 "geometry: random_points_general_position: n must be positive");
6563 "geometry: random_points_general_position: min_coord must be "
6564 "at most max_coord");
6566 static_cast<detail::i128>(max_coord) - min_coord <=
6567 std::numeric_limits<
long long>::max(),
6568 "geometry: random_points_general_position: coordinate range too large");
6569 uint64_t width = max_coord - min_coord;
6574 "geometry: random_points_general_position: coordinate range "
6583 std::vector<uint64_t> x_range(p - 1);
6584 std::iota(x_range.begin(), x_range.end(), 1);
6585 shuffle(x_range.begin(), x_range.end());
6586 std::vector<detail::i128> bx(n), by(n);
6587 for (
int i = 0; i < n; ++i) {
6588 uint64_t x = x_range[i];
6590 by[i] = math::modular_inverse(x, p);
6598 const int num_shears = 8;
6599 std::vector<detail::i128> lin_x = bx, lin_y = by;
6601 for (
int it = 0; it < num_shears; ++it) {
6602 bool vertical_shear = next(2) == 0;
6603 int shear_r = pick({-2, -1, 1, 2});
6605 for (
int i = 0; i < n; ++i) {
6607 lin_x[i] = (lin_x[i] + shear_r * lin_y[i]) % p;
6609 lin_y[i] = (lin_y[i] + shear_r * lin_x[i]) % p;
6618 detail::i128 min_x = lin_x[0], max_x = lin_x[0], min_y = lin_y[0],
6620 for (
int i = 1; i < n; ++i) {
6621 min_x = std::min(min_x, lin_x[i]);
6622 max_x = std::max(max_x, lin_x[i]);
6623 min_y = std::min(min_y, lin_y[i]);
6624 max_y = std::max(max_y, lin_y[i]);
6628 min_coord - min_x + next<
long long>(0, width - (max_x - min_x));
6630 min_coord - min_y + next<
long long>(0, width - (max_y - min_y));
6632 std::vector<point<
long long>> pts;
6633 for (
int i = 0; i < n; ++i)
6634 pts.emplace_back(lin_x[i] + x_shift, lin_y[i] + y_shift);
6640using i128 = tgen::detail::i128;
6644inline i128 ccw(
const point<
long long> &a,
const point<
long long> &b,
6645 const point<
long long> &p) {
6646 return (
static_cast<i128>(b.x()) - a.x()) *
6647 (
static_cast<i128>(p.y()) - a.y()) -
6648 (
static_cast<i128>(b.y()) - a.y()) *
6649 (
static_cast<i128>(p.x()) - a.x());
6653inline i128 proj_on_ab(
const point<
long long> &P,
const point<
long long> &A,
6654 const point<
long long> &B) {
6655 return (P - A) * (B - A);
6661inline void conquer(std::vector<point<
long long>> &points,
int left,
6663 if (right - left <= 3)
6666 point<
long long> A = points[left], B = points[right - 1];
6669 bool all_collinear =
true;
6670 for (
int k = left + 1; k < right - 1; ++k) {
6671 if (ccw(A, B, points[k]) != 0) {
6672 all_collinear =
false;
6676 if (all_collinear) {
6677 std::sort(points.begin() + left, points.begin() + right,
6678 [&](
const point<
long long> &P,
const point<
long long> &Q) {
6679 return proj_on_ab(P, A, B) < proj_on_ab(Q, A, B);
6685 std::vector<
int> candidates;
6686 for (
int k = left + 1; k < right - 1; ++k) {
6687 if (ccw(A, B, points[k]) != 0)
6688 candidates.push_back(k);
6690 int ci = candidates[next(0,
static_cast<
int>(candidates.size()) - 1)];
6691 point<
long long> C = points[ci];
6693 uint64_t wa = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6694 uint64_t wb = next<uint64_t>(1, std::numeric_limits<uint64_t>::max());
6695 bool a_on_positive = ccw(C, A, B) < 0;
6699 i128 proj_sum = proj_on_ab(A, A, B) + proj_on_ab(B, A, B);
6700 auto is_positive = [&](
const point<
long long> &P) ->
bool {
6701 i128 s = wa * ccw(C, A, P) + wb * ccw(C, B, P);
6706 return 2 * proj_on_ab(P, A, B) > proj_sum;
6711 if (ci != right - 2)
6712 std::swap(points[ci], points[right - 2]);
6717 if (is_positive(points[i]) == a_on_positive)
6719 else if (is_positive(points[j]) != a_on_positive)
6722 std::swap(points[i], points[j]);
6733 if (i == j
and is_positive(points[i]) == a_on_positive)
6735 std::swap(points[p], points[right - 2]);
6738 conquer(points, left, p + 1);
6740 conquer(points, p, right);
6747inline std::vector<
long long>
6748sample_sorted_distinct_in_range(
int k,
long long left,
long long right) {
6749 long long universe = right - left + 1;
6750 std::vector<
long long> res;
6755 constexpr long long pool_threshold = 8'000'000;
6756 constexpr long long pool_always_below = 500'000;
6758 if (universe <= pool_threshold
and
6759 (universe <= pool_always_below
or k >= universe / 4)) {
6760 size_t u = universe;
6762 std::vector<
long long> pool(u);
6763 std::iota(pool.begin(), pool.end(), left);
6764 size_t m = ks <= u / 2 ? ks : u - ks;
6765 for (size_t i = 0; i < m; ++i) {
6766 size_t j = next<size_t>(i, u - 1);
6767 std::swap(pool[i], pool[j]);
6770 res.assign(pool.begin(), pool.begin() + ks);
6771 std::sort(res.begin(), res.end());
6773 std::vector<
char> excluded(u, 0);
6774 for (size_t i = 0; i < m; ++i)
6775 excluded[pool[i] - left] = 1;
6776 for (
long long v = left; v <= right; ++v)
6777 if (!excluded[v - left])
6781 std::unordered_map<
long long,
long long> virtual_list;
6782 virtual_list.reserve(k * 2);
6783 for (
long long i = 0; i < k; ++i) {
6784 long long j = next<
long long>(i, universe - 1);
6785 long long vi = virtual_list.count(i) ? virtual_list[i] : i;
6786 long long vj = virtual_list.count(j) ? virtual_list[j] : j;
6787 virtual_list[j] = vi;
6788 virtual_list[i] = vj;
6789 res.push_back(virtual_list[i] + left);
6791 std::sort(res.begin(), res.end());
6798inline std::vector<
long long>
6799valtr_edge_components(
const std::vector<
long long> &sorted_coords) {
6800 int n = sorted_coords.size();
6801 std::vector<
long long> left, right;
6802 left.reserve(n / 2);
6803 right.reserve(n / 2);
6804 for (
int i = 1; i + 1 < n; ++i) {
6806 left.push_back(sorted_coords[i]);
6808 right.push_back(sorted_coords[i]);
6810 long long lo = sorted_coords.front(), hi = sorted_coords.back();
6811 std::vector<
long long> seq;
6814 for (
long long v : left)
6817 for (
auto it = right.rbegin(); it != right.rend(); ++it)
6820 std::vector<
long long> comps(n);
6821 for (
int i = 0; i < n; ++i)
6822 comps[i] = seq[i + 1] - seq[i];
6828inline std::vector<point<
long long>>
6829simplify_strict_boundary(std::vector<point<
long long>> points) {
6830 int n = points.size();
6834 std::vector<point<
long long>> strict_points;
6835 strict_points.reserve(n);
6836 for (
int i = 0; i < n; ++i) {
6837 if (ccw(points[(i + n - 1) % n], points[i], points[(i + 1) % n]) != 0)
6838 strict_points.push_back(points[i]);
6840 return strict_points;
6845inline std::vector<point<
long long>>
6846subsample_boundary(
const std::vector<point<
long long>> &points,
int k) {
6847 int n = points.size();
6851 std::vector<point<
long long>> sampled_points;
6852 sampled_points.reserve(k);
6853 for (
int i = 0; i < k; ++i)
6854 sampled_points.push_back(points[(
static_cast<i128>(i) * n) / k]);
6855 return sampled_points;
6860inline void place_inside_box(std::vector<point<
long long>> &points,
6861 long long min_coord,
long long max_coord) {
6862 long long width = max_coord - min_coord + 1;
6864 i128 min_x = points[0].x(), max_x = points[0].x();
6865 i128 min_y = points[0].y(), max_y = points[0].y();
6866 for (
const point<
long long> &p : points) {
6867 min_x = std::min(min_x,
static_cast<i128>(p.x()));
6868 max_x = std::max(max_x,
static_cast<i128>(p.x()));
6869 min_y = std::min(min_y,
static_cast<i128>(p.y()));
6870 max_y = std::max(max_y,
static_cast<i128>(p.y()));
6873 i128 span_x = max_x - min_x;
6874 i128 span_y = max_y - min_y;
6878 next<
long long>(0, width - 1 -
static_cast<
long long>(span_x));
6881 next<
long long>(0, width - 1 -
static_cast<
long long>(span_y));
6883 for (point<
long long> &p : points)
6884 p = point<
long long>(p.x() + shift_x, p.y() + shift_y);
6889inline void randomize_cyclic_shift(std::vector<point<
long long>> &points) {
6890 int rot = next(points.size());
6892 std::rotate(points.begin(), points.begin() + rot, points.end());
6897inline std::vector<point<
long long>>
6898valtr_vertices(
int m,
const std::vector<
long long> &x_comp,
6899 std::vector<
long long> y_comp) {
6900 shuffle(y_comp.begin(), y_comp.end());
6902 std::vector<point<
long long>> edges(m);
6904 auto upper = [](
const point<
long long> &p) {
6905 return p.y() > 0
or (p.y() == 0
and p.x() > 0);
6907 for (
int i = 0; i < m; ++i)
6908 edges[i] =
point<
long long>(x_comp[i], y_comp[i]);
6910 std::sort(edges.begin(), edges.end(),
6911 [&upper](
const point<
long long> &a,
const point<
long long> &b) {
6912 bool au = upper(a), bu = upper(b);
6918 return (a * a) < (b * b);
6922 i128 cur_x = 0, cur_y = 0;
6923 std::vector<i128> px(m), py(m);
6924 for (
int i = 0; i < m; ++i) {
6927 cur_x += edges[i].x();
6928 cur_y += edges[i].y();
6930 tgen::detail::tgen_ensure_against_bug(
6931 cur_x == 0
and cur_y == 0,
6932 "geometry: random_convex_polygon: walk did not close");
6934 i128 min_x = px[0], min_y = py[0];
6935 for (
int i = 1; i < m; ++i) {
6936 min_x = std::min(min_x, px[i]);
6937 min_y = std::min(min_y, py[i]);
6941 std::vector<point<
long long>> points;
6943 for (
int i = 0; i < m; ++i)
6944 points.emplace_back(px[i] - min_x, py[i] - min_y);
6957 bool strict =
false) {
6959 "geometry: random_convex_polygon: n must be at least 3");
6961 "geometry: random_convex_polygon: min_coord must be at most "
6963 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
6964 std::numeric_limits<
long long>::max(),
6965 "geometry: random_convex_polygon: coordinate range too large");
6966 long long width = max_coord - min_coord + 1;
6969 "geometry: random_convex_polygon: coordinate range too small for n");
6977 int extra = width <= n ? 0
6978 : std::min<
long long>(std::max(100, n / 1000),
6980 num_coords = n + extra;
6985 const int max_attempts = strict ? 32 : 1;
6986 for (
int i = 0; i < max_attempts; ++i) {
6988 std::vector<
long long> x_sorted =
6989 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6990 std::vector<
long long> y_sorted =
6991 detail::sample_sorted_distinct_in_range(num_coords, 0, width - 1);
6992 std::vector<
long long> x_comp = detail::valtr_edge_components(x_sorted);
6993 std::vector<
long long> y_comp = detail::valtr_edge_components(y_sorted);
6995 std::vector<point<
long long>> points =
6996 detail::valtr_vertices(num_coords, x_comp, std::move(y_comp));
6999 std::vector<point<
long long>> simplified =
7000 detail::simplify_strict_boundary(std::move(points));
7002 if (
static_cast<
int>(simplified.size()) < n)
7005 points = detail::subsample_boundary(simplified, n);
7008 detail::place_inside_box(points, min_coord, max_coord);
7009 detail::randomize_cyclic_shift(points);
7014 throw tgen::detail::error(
7015 "geometry: random_convex_polygon: generation failed: coordinate "
7016 "range too small for n");
7024 const std::vector<point<
long long>> &points) {
7025 int n = points.size();
7027 "geometry: random_simple_polygon_through_points: need at "
7031 std::set<point<
long long>>(points.begin(), points.end()).size()) ==
7033 "geometry: random_simple_polygon_through_points: points must "
7036 int idx_a = 0, idx_b = 0;
7037 for (
int i = 1; i < n; ++i) {
7038 if (points[i] < points[idx_a])
7040 if (points[idx_b] < points[i])
7043 point<
long long> A = points[idx_a], B = points[idx_b];
7045 bool all_collinear =
true;
7046 for (
int i = 0; i < n; ++i) {
7047 if (i == idx_a
or i == idx_b)
7049 if (detail::ccw(A, B, points[i]) != 0) {
7050 all_collinear =
false;
7055 "geometry: random_simple_polygon_through_points: all points "
7056 "are collinear; no simple polygon exists");
7061 int negative_count = 0;
7062 for (
int i = 0; i < n; ++i) {
7063 if (i == idx_a
or i == idx_b)
7065 if (detail::ccw(A, B, points[i]) < 0)
7069 std::vector<point<
long long>> chain;
7072 for (
int i = 0; i < n; ++i) {
7073 if (i == idx_a
or i == idx_b)
7075 detail::i128 side = detail::ccw(A, B, points[i]);
7076 if (side < 0
or (side == 0
and negative_count == 0)) {
7077 chain.push_back(points[i]);
7082 for (
int i = 0; i < n; ++i) {
7083 if (i == idx_a
or i == idx_b)
7085 detail::i128 side = detail::ccw(A, B, points[i]);
7086 if (side > 0
or (side == 0
and negative_count != 0))
7087 chain.push_back(points[i]);
7091 int n1 = 2 + left_count;
7093 detail::conquer(chain, 0, n1);
7095 detail::conquer(chain, n1 - 1, chain.size());
7099 std::vector<point<
long long>> poly;
7100 poly.insert(poly.end(), chain.begin() + 1, chain.begin() + n1);
7101 poly.insert(poly.end(), chain.begin() + n1, chain.end());
7109inline std::vector<point<
long long>>
7110random_distinct_points_in_box(
int n,
long long min_coord,
long long max_coord) {
7111 long long width = max_coord - min_coord;
7112 i128 side_128 = width + 1;
7113 i128 universe = side_128 * side_128;
7114 tgen_ensure(universe <= std::numeric_limits<
long long>::max(),
7115 "geometry: random_simple_polygon: coordinate range too large");
7116 long long side = side_128;
7118 "geometry: random_simple_polygon: coordinate range too small "
7119 "for n distinct points");
7122 auto decode = [&](
long long key) ->
point<
long long> {
7123 return point<
long long>(min_coord + key / side, min_coord + key % side);
7129 std::vector<
long long> keys =
7130 distinct_range<
long long>(0, universe - 1).gen_list(n).to_std();
7132 std::vector<point<
long long>> points;
7134 for (
long long key : keys)
7135 points.push_back(decode(key));
7138 for (
int i = 2; i < n; ++i) {
7139 if (ccw(points[0], points[1], points[i]) != 0)
7147struct ortho_poly_edge {
7157inline bool ortho_axis_collinear(
const point<
long long> &a,
7158 const point<
long long> &b,
7159 const point<
long long> &c) {
7160 return (a.x() == b.x()
and b.x() == c.x())
or
7161 (a.y() == b.y()
and b.y() == c.y());
7166inline ortho_poly_edge
7167ortho_analyze_edge(
const std::vector<point<
long long>> &poly,
int i) {
7168 int m = poly.size();
7169 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7170 ortho_poly_edge e{};
7171 if (a.y() == b.y()) {
7174 e.lo = std::min(a.x(), b.x());
7175 e.hi = std::max(a.x(), b.x());
7177 e.out_y = a.x() < b.x() ? -1 : 1;
7180 e.lo = std::min(a.y(), b.y());
7181 e.hi = std::max(a.y(), b.y());
7182 e.out_x = a.y() < b.y() ? 1 : -1;
7184 e.len = e.hi - e.lo;
7191inline bool ortho_open_seg_cross(
const point<
long long> &a,
7192 const point<
long long> &b,
7193 const point<
long long> &c,
7194 const point<
long long> &d) {
7195 if (a.y() == b.y()
and c.y() == d.y()) {
7198 long long lo1 = std::min(a.x(), b.x()), hi1 = std::max(a.x(), b.x());
7199 long long lo2 = std::min(c.x(), d.x()), hi2 = std::max(c.x(), d.x());
7200 return lo1 < hi2
and lo2 < hi1;
7202 if (a.x() == b.x()
and c.x() == d.x()) {
7205 long long lo1 = std::min(a.y(), b.y()), hi1 = std::max(a.y(), b.y());
7206 long long lo2 = std::min(c.y(), d.y()), hi2 = std::max(c.y(), d.y());
7207 return lo1 < hi2
and lo2 < hi1;
7209 if (a.y() == b.y()
and c.x() == d.x()) {
7210 long long hx = a.y(), vx = c.x();
7211 long long hlo = std::min(a.x(), b.x()), hhi = std::max(a.x(), b.x());
7212 long long vlo = std::min(c.y(), d.y()), vhi = std::max(c.y(), d.y());
7213 return hlo < vx
and vx < hhi
and vlo < hx
and hx < vhi;
7215 if (a.x() == b.x()
and c.y() == d.y()) {
7216 long long vx = a.x(), hy = c.y();
7217 long long vlo = std::min(a.y(), b.y()), vhi = std::max(a.y(), b.y());
7218 long long hlo = std::min(c.x(), d.x()), hhi = std::max(c.x(), d.x());
7219 return vlo < hy
and hy < vhi
and hlo < vx
and vx < hhi;
7226inline bool ortho_point_inside(
const std::vector<point<
long long>> &poly,
7227 point<
long long> p) {
7228 int m = poly.size();
7229 bool inside =
false;
7230 for (
int i = 0, j = m - 1; i < m; j = i++) {
7231 point<
long long> a = poly[i], b = poly[j];
7232 if ((a.y() > p.y()) != (b.y() > p.y())) {
7233 i128 x_cross = i128(b.x() - a.x()) * (p.y() - a.y()) -
7234 i128(p.x() - a.x()) * (b.y() - a.y());
7235 if ((a.y() < b.y()) ? x_cross > 0 : x_cross < 0)
7244inline bool ortho_point_strictly_interior(
point<
long long> p,
7246 point<
long long> b) {
7247 if (a.y() == b.y()) {
7250 long long lo = std::min(a.x(), b.x()), hi = std::max(a.x(), b.x());
7251 return lo < p.x()
and p.x() < hi;
7253 if (a.x() == b.x()) {
7256 long long lo = std::min(a.y(), b.y()), hi = std::max(a.y(), b.y());
7257 return lo < p.y()
and p.y() < hi;
7264inline bool ortho_point_on_segment(
point<
long long> p,
point<
long long> a,
7265 point<
long long> b) {
7266 return p == a
or p == b
or ortho_point_strictly_interior(p, a, b);
7274inline bool ortho_bump_valid(
const std::vector<point<
long long>> &poly,
7276 const std::vector<point<
long long>> &add,
7277 int edge_i,
bool inward) {
7278 int m = poly.size();
7280 for (point<
long long> v : add)
7281 for (point<
long long> q : poly)
7287 for (point<
long long> v : add) {
7288 for (
int j = 0; j < m; ++j) {
7289 point<
long long> c = poly[j], d = poly[(j + 1) % m];
7291 if (ortho_point_on_segment(v, c, d)
and
7292 !ortho_point_on_segment(v, A, B))
7294 }
else if (ortho_point_strictly_interior(v, c, d)) {
7300 auto seg_ok = [&](
point<
long long> s0,
point<
long long> s1) {
7301 for (
int j = 0; j < m; ++j) {
7304 point<
long long> c = poly[j], d = poly[(j + 1) % m];
7305 if (ortho_open_seg_cross(s0, s1, c, d))
7308 for (
int k = 0; k < m; ++k) {
7309 point<
long long> q = poly[k];
7310 if (q == s0
or q == s1
or q == A
or q == B)
7312 if (ortho_point_strictly_interior(q, s0, s1))
7318 point<
long long> prev = A;
7319 for (point<
long long> v : add) {
7320 if (!seg_ok(prev, v))
7324 if (!seg_ok(prev, B))
7328 for (point<
long long> v : add)
7329 if (!ortho_point_inside(poly, v))
7339inline bool ortho_bump_edge(std::vector<point<
long long>> &poly,
int edge_i,
7340 const ortho_poly_edge &e,
long long lo,
7341 long long hi,
long long depth,
bool inward,
7342 size_t max_vertices) {
7343 int m = poly.size();
7344 point<
long long> A = poly[edge_i], B = poly[(edge_i + 1) % m];
7346 int step_x = inward ? -e.out_x : e.out_x;
7347 int step_y = inward ? -e.out_y : e.out_y;
7349 std::vector<point<
long long>> add;
7351 long long y = e.fixed, y2 = y + step_y * depth;
7352 if (A.x() < B.x()) {
7354 add.emplace_back(lo, y);
7355 add.emplace_back(lo, y2);
7356 add.emplace_back(hi, y2);
7358 add.emplace_back(hi, y);
7361 add.emplace_back(hi, y);
7362 add.emplace_back(hi, y2);
7363 add.emplace_back(lo, y2);
7365 add.emplace_back(lo, y);
7368 long long x = e.fixed, x2 = x + step_x * depth;
7369 if (A.y() < B.y()) {
7371 add.emplace_back(x, lo);
7372 add.emplace_back(x2, lo);
7373 add.emplace_back(x2, hi);
7375 add.emplace_back(x, hi);
7378 add.emplace_back(x, hi);
7379 add.emplace_back(x2, hi);
7380 add.emplace_back(x2, lo);
7382 add.emplace_back(x, lo);
7385 if (poly.size() > max_vertices
or add.size() > max_vertices - poly.size())
7387 if (!ortho_bump_valid(poly, A, B, add, edge_i, inward))
7390 poly.insert(poly.begin() + edge_i + 1, add.begin(), add.end());
7397inline int ortho_pick_poly_edge(
const std::vector<point<
long long>> &poly,
7398 std::vector<
int> &last_used,
int &time_stamp) {
7399 int m = poly.size();
7400 if (last_used.size() !=
static_cast<size_t>(m)) {
7401 last_used.assign(m, 0);
7404 std::vector<
long long> weights(m);
7405 long long total = 0;
7406 for (
int i = 0; i < m; ++i) {
7407 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7408 weights[i] = e.len * (4 + std::min(time_stamp - last_used[i], 8));
7409 total += weights[i];
7411 long long pick = next<
long long>(0, total - 1);
7412 for (
int i = 0; i < m; ++i) {
7415 last_used[i] = ++time_stamp;
7419 last_used[m - 1] = ++time_stamp;
7426ortho_try_bump(std::vector<point<
long long>> &poly,
int n,
7427 std::vector<
int> &last_used,
int &time_stamp,
7428 bool outward_only =
false,
7429 size_t max_vertices = std::numeric_limits<size_t>::max()) {
7430 if (poly.size() < 3)
7433 int ei = ortho_pick_poly_edge(poly, last_used, time_stamp);
7434 ortho_poly_edge e = ortho_analyze_edge(poly, ei);
7441 long long span = next<
long long>(2, e.len);
7442 long long lo = next<
long long>(e.lo, e.hi - span);
7446 long long max_depth =
7447 std::clamp<
long long>(std::sqrt(n) / 2 + 2, 2LL, 12LL);
7449 next(10) == 0 ? next<
long long>(std::max(2LL, max_depth / 2), max_depth)
7450 : next<
long long>(1, std::max(2LL, max_depth / 3));
7452 bool inward = !outward_only
and next(4) == 0;
7453 return ortho_bump_edge(poly, ei, e, lo, lo + span, depth, inward,
7459inline std::vector<point<
long long>>
7460ortho_simplify_collinear(std::vector<point<
long long>> poly) {
7461 int n = poly.size();
7464 std::vector<point<
long long>> out;
7466 for (
int i = 0; i < n; ++i) {
7467 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7469 out.push_back(poly[i]);
7471 return out.size() >= 3 ? out : poly;
7476inline bool ortho_remove_one_collinear(std::vector<point<
long long>> &poly) {
7477 int n = poly.size();
7480 for (
int i = 0; i < n; ++i) {
7481 if (!ortho_axis_collinear(poly[(i + n - 1) % n], poly[i],
7484 poly.erase(poly.begin() + i);
7493inline void ortho_fill_collinear(std::vector<point<
long long>> &poly,
7495 int need = target - poly.size();
7499 std::vector<point<
long long>> out;
7500 int m = poly.size();
7501 out.reserve(poly.size() + need);
7503 for (
int i = 0; i < m; ++i) {
7504 point<
long long> a = poly[i], b = poly[(i + 1) % m];
7509 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7510 long long cap = e.len - 1;
7515 long long take = std::min<
long long>(need, cap);
7516 bool forward = e.horiz ? a.x() < b.x() : a.y() < b.y();
7517 for (
long long k = 0; k < take; ++k) {
7518 long long off = (k + 1) * (cap + 1) / (take + 1);
7519 long long coord = forward ? e.lo + off : e.hi - off;
7521 out.push_back({coord, e.fixed});
7523 out.push_back({e.fixed, coord});
7537inline void ortho_fill_corrugation(std::vector<point<
long long>> &poly,
7539 size_t n_sz = poly.size();
7543 size_t extra_left = target - n_sz;
7545 std::vector<point<
long long>> out;
7546 out.reserve(target);
7547 int n = poly.size();
7549 for (
int i = 0; i < n; ++i) {
7550 point<
long long> a = poly[i], b = poly[(i + 1) % n];
7556 ortho_poly_edge e = ortho_analyze_edge(poly, i);
7560 long long dir = (e.horiz ? a.x() < b.x() : a.y() < b.y()) ? 1 : -1;
7561 long long start = e.horiz ? a.x() : a.y();
7562 long long end = e.horiz ? b.x() : b.y();
7564 for (
long long pos = start + 2 * dir;
7565 extra_left >= 4
and (pos - end) * dir <= -3; pos += 2 * dir) {
7567 long long y2 = e.fixed + e.out_y;
7568 out.push_back({pos, e.fixed});
7569 out.push_back({pos, y2});
7570 out.push_back({pos + dir, y2});
7571 out.push_back({pos + dir, e.fixed});
7573 long long x2 = e.fixed + e.out_x;
7574 out.push_back({e.fixed, pos});
7575 out.push_back({x2, pos});
7576 out.push_back({x2, pos + dir});
7577 out.push_back({e.fixed, pos + dir});
7588inline std::vector<point<
long long>> build_orthogonal_polygon(
int n,
7590 bool scale_up = n > 1000;
7592 long long side = std::max<
long long>(3, std::sqrt(n));
7594 side = std::clamp(
static_cast<
long long>(2 * std::sqrt(std::sqrt(n))),
7596 std::vector<point<
long long>> poly = {
7597 {0, 0}, {side, 0}, {side, side}, {0, side}};
7599 int target_ops = scale_up ? std::max(1,
static_cast<
int>(4 * side - 4) / 2)
7600 : std::max(1, (n - 4) / 2);
7603 target_ops = std::min(
7605 400 +
static_cast<
int>(4 * std::sqrt(
static_cast<
double>(side))));
7607 int failure_limit = std::min(target_ops * 8, 2000);
7609 std::vector<
int> last_used;
7610 int time_stamp = 0, consecutive_failures = 0;
7611 size_t max_vertices =
7612 scale_up ? std::numeric_limits<size_t>::max() :
static_cast<size_t>(n);
7613 for (
int ops = 0; ops < target_ops;) {
7614 if (!scale_up
and poly.size() + 2 >
static_cast<size_t>(n))
7617 if (ortho_try_bump(poly, n, last_used, time_stamp, scale_up,
7620 consecutive_failures = 0;
7621 }
else if (++consecutive_failures >= failure_limit) {
7626 poly = ortho_simplify_collinear(std::move(poly));
7629 while (poly.size() >
static_cast<size_t>(n)
and
7630 ortho_remove_one_collinear(poly))
7632 long long upscale = std::max(4LL, ((n + 3) / 4 + side - 1) / side);
7633 for (point<
long long> &p : poly)
7634 p = {p.x() * upscale, p.y() * upscale};
7636 ortho_fill_corrugation(poly, n);
7638 ortho_fill_collinear(poly, n);
7640 ortho_fill_collinear(poly, n);
7656 bool strict =
false) {
7658 "geometry: random_simple_polygon: n must be at least 3");
7660 "geometry: random_simple_polygon: min_coord must be at most "
7662 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord <=
7663 std::numeric_limits<
long long>::max(),
7664 "geometry: random_simple_polygon: coordinate range too large");
7666 std::vector<point<
long long>> points =
7667 strict ? random_points_general_position(n, min_coord, max_coord)
7668 : detail::random_distinct_points_in_box(n, min_coord, max_coord);
7669 return random_simple_polygon_through_points(points);
7678 bool strict =
false) {
7680 "geometry: random_orthogonal_polygon: n must be at least 4");
7682 "geometry: random_orthogonal_polygon: min_coord must be at "
7684 tgen_ensure(
static_cast<detail::i128>(max_coord) - min_coord + 1 <=
7685 std::numeric_limits<
long long>::max(),
7686 "geometry: random_orthogonal_polygon: coordinate range too "
7688 long long width = max_coord - min_coord + 1;
7690 "geometry: random_orthogonal_polygon: coordinate range too "
7693 long long min_side = std::max<
long long>(3, std::sqrt(n));
7695 min_side = std::max<
long long>(min_side, (n + 3) / 4);
7697 "geometry: random_orthogonal_polygon: coordinate range too "
7700 for (
int attempt = 0; attempt < 8; ++attempt) {
7701 std::vector<point<
long long>> poly =
7702 detail::build_orthogonal_polygon(n, strict);
7704 if (!strict
and poly.size() !=
static_cast<size_t>(n))
7707 detail::i128 min_x = poly[0].x(), max_x = poly[0].x();
7708 detail::i128 min_y = poly[0].y(), max_y = poly[0].y();
7709 for (point<
long long> p : poly) {
7710 min_x = std::min(min_x, detail::i128(p.x()));
7711 max_x = std::max(max_x, detail::i128(p.x()));
7712 min_y = std::min(min_y, detail::i128(p.y()));
7713 max_y = std::max(max_y, detail::i128(p.y()));
7715 if (max_x - min_x >= width
or max_y - min_y >= width)
7718 detail::place_inside_box(poly, min_coord, max_coord);
7719 detail::randomize_cyclic_shift(poly);
7723 throw tgen::detail::error(
7724 "geometry: random_orthogonal_polygon: generation failed");
7730
7731
7732
7733
7739using namespace tgen::detail;
7743inline int hash_string(
const std::string &s,
int base,
int mod) {
7746 h = (h * base + c -
'a' + 1) % mod;
7751inline int estimate_length(
int alphabet_size,
int mod) {
7753 double base_len = 2.5 * std::log(std::sqrt(mod));
7754 double scale = std::log(alphabet_size) / std::log(2.0);
7755 double adjusted = base_len / std::max(1.0, scale * 0.7);
7757 return static_cast<
int>(std::ceil(adjusted));
7762inline std::pair<std::string, std::string>
7763birthday_attack(
const std::vector<std::string> &alphabet,
int base,
int mod) {
7765 "birthday_attack: base must be in (0, mod)");
7766 std::map<uint64_t, std::vector<
int>> seen;
7767 int length = estimate_length(alphabet.size(), mod);
7770 std::vector<
int> seq(length);
7774 for (
int i = 0; i < length; ++i) {
7775 seq[i] = next<
int>(0, alphabet.size() - 1);
7776 s += alphabet[seq[i]];
7779 int h = hash_string(s, base, mod);
7781 auto it = seen.find(h);
7782 if (it != seen.end()
and it->second != seq) {
7785 for (
int x : it->second)
7800inline std::set<
long long> std_hash_multipliers() {
7801 std::set<
long long> multipliers = {85229};
7804 bool codeforces_gcc_case =
true;
7805 if (cpp.version_ != 0
and cpp.version_ != 17)
7806 codeforces_gcc_case =
false;
7807 if (compiler.kind_ != compiler_kind::unknown
and
7808 compiler.kind_ != compiler_kind::gcc)
7809 codeforces_gcc_case =
false;
7810 if (compiler.major_ > 7)
7811 codeforces_gcc_case =
false;
7813 if (codeforces_gcc_case)
7814 multipliers.insert(107897);
7825 std::string str =
"a";
7827 while (
static_cast<
int>(str.size()) < n) {
7828 int prev_size = str.size();
7830 for (
int j = 0; j < prev_size
and static_cast<
int>(str.size()) < n; ++j)
7843 for (
int i = 0; i < size; ++i) {
7844 a +=
'a' + math::detail::popcount(i) % 2;
7845 b +=
'a' + (
'b' - a[i]);
7854 int base,
int mod) {
7856 "hack: polynomial_hash: alphabet size must be greater "
7859 "hack: polynomial_hash: base must be in (0, mod)");
7861 std::vector<std::string> alphabet(alphabet_size);
7862 for (
int i = 0; i < alphabet_size; ++i)
7863 alphabet[i] = std::string(1,
'a' + i);
7864 std::iota(alphabet.begin(), alphabet.end(),
'a');
7865 return detail::birthday_attack(alphabet, base, mod);
7872inline std::pair<std::string, std::string>
7874 std::vector<
int> mods) {
7876 "hack: polynomial_hash: bases and mods must have the same "
7879 "hack: polynomial_hash: must have at least one (base, mod) "
7882 "hack: polynomial_hash: multi-hash hack only supported "
7883 "for up to 2 (base, mod) pairs");
7885 std::vector<std::string> alphabet(alphabet_size);
7886 for (
int i = 0; i < alphabet_size; ++i)
7887 alphabet[i] = std::string(1,
'a' + i);
7888 auto [S1, T1] = detail::birthday_attack(alphabet, bases[0], mods[0]);
7889 if (bases.size() == 1)
7891 return detail::birthday_attack({S1, T1}, bases[1], mods[1]);
7897 tgen_ensure(size > 0,
"hack: std_unordered: size must be positive");
7898 std::set<
long long> multipliers = detail::std_hash_multipliers();
7900 std::set<
long long>::iterator it = multipliers.begin();
7902 std::vector<
long long> list;
7903 while (
static_cast<
int>(list.size()) < size) {
7904 list.push_back(mult * (*it));
7906 if (it == multipliers.end()) {
7907 it = multipliers.begin();
7919 std::set<std::pair<
int,
int>> queries;
7922 int sq = std::sqrt(n);
7923 for (
int i = 0; i < sq; ++i) {
7924 for (
int j = i; j < sq; ++j) {
7925 if (i * sq < n
and j * sq < n)
7926 queries.emplace(i * sq, j * sq);
7931 for (
int i = 0; i < n; ++i)
7932 if (queries.size() < size_t(q)) {
7933 queries.emplace(0, i);
7934 queries.emplace(i, i);
7935 queries.emplace(i, n - 1);
7938 std::vector<std::pair<
int,
int>> pool(queries.begin(), queries.end());
7939 while (pool.size() < size_t(q)) {
7940 int l = next(0, n - 1);
7941 pool.emplace_back(l, next(l, n - 1));
7944 return choose(shuffled(pool), q);
7952 std::vector<std::string> list;
7953 int k = 0, left = size;
7955 int cur_size = std::min(left, k + 1);
7958 char right_char = cur_size == k + 1 ?
'b' :
'c';
7959 list.push_back(std::string(cur_size - 1,
'a') + right_char);
7963 return tgen::shuffled(list);
7975 "hack: non_strict_relaxation_dijkstra_bug: needs at least 3 vertices");
7977 egraph<
int>::value g(n, {},
true);
7979 g.add_edge(0, 1, 1);
7980 g.add_edge(0, 2, 1);
7981 for (
int i = 1; i + 2 < n; i += 2) {
7982 g.add_edge(i, i + 2, 1);
7984 g.add_edge(i, i + 3, 1);
7986 g.add_edge(i + 1, i + 2, 1);
7988 g.add_edge(i + 1, i + 3, 1);
7991 return g.shuffle_except({0});
8004 "hack: stale_heap_dijkstra_bug: needs at least 4 vertices");
8007 egraph<
int>::value g(n, {},
true);
8009 for (
int i = 1; i < mid; ++i)
8010 g.add_edge(0, i, i);
8011 for (
int i = 1; i < mid; ++i)
8012 g.add_edge(i, mid, 2 * (mid - i) - 1);
8013 for (
int i = mid + 1; i < n; ++i)
8014 g.add_edge(mid, i, 1);
8016 return g.shuffle_except({0});
8027 tgen_ensure(n >= 2,
"hack: spfa: n must be at least 2");
8028 tgen_ensure(n % 2 == 0,
"hack: spfa: n must be even");
8030 egraph<
int>::value g(n, {},
true);
8033 const int k = n / 2;
8034 for (
int i = 0; i + 1 < k; ++i)
8035 g.add_edge(i, i + 1, 1);
8036 for (
int i = 0; i + 1 < k; ++i)
8037 g.add_edge(k + i, k + i + 1, 0);
8038 for (
int i = 0; i < k; ++i)
8039 g.add_edge(i, k + i, 0);
8040 for (
int i = 0; i + 1 < k; ++i)
8041 g.add_edge(k + i, i + 1, 1);
8043 return g.shuffle_except({0});
8051 tgen_ensure(k >= 1,
"hack: dinitz_worst_case: k must be at least 1");
8052 tgen_ensure(l >= 1,
"hack: dinitz_worst_case: l must be at least 1");
8054 const int p1 = 2 * l - 1;
8055 const int p2 = 2 * l;
8056 const int q1 = 2 * l + 1;
8057 const int q2 = 2 * l + 2;
8058 const int n = 4 * l + 2 * k + 2;
8060 const int flow_cap = k * k * l;
8061 const int layer_cap = k * k;
8063 auto a = [&](
int i) {
return 2 * l + 3 + 2 * i; };
8064 auto b = [&](
int i) {
return 2 * l + 4 + 2 * i; };
8065 auto t = [&](
int i) {
return 4 * l + 2 * k + 1 - i; };
8067 egraph<
int>::value g(n, {},
true);
8070 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
8071 g.add_edge(i, i + 1, flow_cap);
8072 for (
int i = 0; i + 1 < 2 * l - 1; ++i)
8073 g.add_edge(t(i + 1), t(i), flow_cap);
8075 for (
int i = 0; i < 2 * l - 1; i += 2) {
8076 g.add_edge(i, i % 4 == 0 ? p1 : p2, layer_cap);
8077 g.add_edge(i % 4 == 0 ? q1 : q2, t(i), layer_cap);
8080 for (
int i = 0; i < k; ++i) {
8081 g.add_edge(p1, a(i), flow_cap);
8082 g.add_edge(p2, b(i), flow_cap);
8083 g.add_edge(a(i), q2, flow_cap);
8084 g.add_edge(b(i), q1, flow_cap);
8087 for (
int i = 0; i < k; ++i)
8088 for (
int j = 0; j < k; ++j)
8089 g.add_edge(a(i), b(j), 1);
8098 static_assert(std::is_same_v<T,
int>
or std::is_same_v<T,
long long>,
8099 "hack: mt19937_xor_hash: T must be int or long long");
8101 constexpr std::size_t deg = 19937;
8103 std::bitset<deg + 1> a, b, c;
8104 b[deg] = c[deg] = 1;
8105 std::size_t l = 0, shift = 1;
8107 std::mt19937_64 rng64;
8108 for (std::size_t n = 0; n < deg * 2; ++n) {
8110 if constexpr (std::is_same_v<T,
int>)
8111 a[deg] = rng32() & 1;
8113 a[deg] = rng64() & 1;
8115 if ((c & a).count() % 2 == 0) {
8120 std::bitset<deg + 1> oc = c;
8131 std::vector<
bool> mask(deg + 1);
8132 for (std::size_t i = 0; i <= deg; ++i)
8144 {-0.9846, -1.53251}, {0.49946, 1.19525}, {0.79916, 0.98291},
8145 {4.02136, -1.57843}, {3.92734, -2.37856}, {3.88558, -2.37188},
8153inline std::vector<
int> segment_tree_beats_worst_case_block(
int k) {
8155 "hack: segment_tree_beats_worst_case: k must be at least 1");
8157 std::vector<
int> a(k + 1), b(k + 1);
8158 std::vector<std::vector<
int>> vf(k + 1), vg(k + 1);
8164 for (
int i = 2; i <= k; ++i) {
8165 b[i] = b[i - 1] + a[i - 1];
8166 a[i] = b[i] + a[i - 1];
8167 for (
int x : vf[i - 1])
8168 vf[i].push_back(x + a[i] + b[i]);
8169 vf[i].push_back(a[i]);
8170 for (
int x : vg[i - 1])
8171 vf[i].push_back(x + a[i]);
8174 for (
int x : vg[i - 1])
8185segment_tree_beats_append_round(std::vector<std::vector<
int>> &updates,
8186 int block_len,
int an,
int bn,
int n,
8188 const int off = (round * an) % block_len;
8189 const int add_off = (off + block_len - bn) % block_len;
8190 for (
int k = 0; k < block_len; ++k) {
8191 const int s = k * block_len * block_len;
8192 const int sub_end = off + an;
8193 if (sub_end <= block_len)
8194 updates.push_back({1, s + off, s + sub_end, bn});
8196 updates.push_back({1, s + off, s + block_len, bn});
8197 updates.push_back({1, s, s + (sub_end - block_len), bn});
8199 const int add_end = add_off + bn;
8200 if (add_end <= block_len)
8201 updates.push_back({0, s + add_off, s + add_end, an});
8203 updates.push_back({0, s + add_off, s + block_len, an});
8204 updates.push_back({0, s, s + (add_end - block_len), an});
8207 updates.push_back({2, 0, n, an});
8208 for (
int k = 0; k < block_len; ++k) {
8209 const int s = k * block_len * block_len;
8210 updates.push_back({3, s + (off + an - 1) % block_len, 0});
8218inline std::pair<std::vector<
int>, std::vector<std::vector<
int>>>
8219segment_tree_beats_worst_case(
int k,
int q) {
8221 "hack: segment_tree_beats_worst_case: k must be at least 1");
8222 tgen_ensure(k <= 7,
"hack: segment_tree_beats_worst_case: k too large");
8224 "hack: segment_tree_beats_worst_case: q must be positive");
8226 const auto &fib = math::fibonacci();
8227 const int block_len = fib[k * 2 + 1];
8228 const int an = fib[k * 2];
8229 const int bn = fib[k * 2 - 1];
8231 const int len = block_len;
8232 const int total = len * len * len;
8234 std::vector<
int> block = detail::segment_tree_beats_worst_case_block(k);
8235 std::vector<
int> arr(total, 0);
8236 for (
int x = 0; x < block_len; ++x) {
8237 const int s = x * len * len;
8238 for (
int i = 0; i < block_len; ++i)
8239 arr[s + i] = block[i];
8242 std::vector<std::vector<
int>> updates;
8244 const int n = total;
8245 for (
int round = 0; updates.size() <
static_cast<std::size_t>(q); ++round) {
8246 detail::segment_tree_beats_append_round(updates, block_len, an, bn, n,
8248 if (updates.size() >
static_cast<std::size_t>(q))
8251 return {arr, updates};
8259inline tree::value binary_heap_tree(
int n) {
8260 std::vector<std::pair<
int,
int>> edges;
8261 for (
int i = 0; i < n; ++i) {
8263 edges.emplace_back(i, 2 * i + 1);
8265 edges.emplace_back(i, 2 * i + 2);
8267 return tree::value(n, edges);
8272inline void heap_subtree_leaves(
int n,
int u, std::vector<
int> &out) {
8273 if (2 * u + 1 >= n) {
8277 heap_subtree_leaves(n, 2 * u + 1, out);
8279 heap_subtree_leaves(n, 2 * u + 2, out);
8286inline std::vector<std::pair<
int,
int>> tree_path_worst_queries(
int n,
int q) {
8287 std::vector<
int> left, right;
8289 heap_subtree_leaves(n, 1, left);
8291 heap_subtree_leaves(n, 2, right);
8293 std::vector<std::pair<
int,
int>> queries;
8294 for (
int i = 0; i < q; ++i)
8295 queries.emplace_back(pick(left), pick(right));
8301inline int reverse_bits(
int x,
int bits) {
8303 for (
int i = 0; i < bits; ++i) {
8304 r = (r << 1) | (x & 1);
8314inline std::vector<
int> lct_worst_access(
int n,
int q) {
8315 int first_leaf = n / 2;
8316 int m = n - first_leaf;
8319 while ((1u << bits) <
static_cast<
unsigned>(m))
8322 std::vector<
int> order;
8323 int span = 1 << bits;
8324 for (
int i = 0; i < span; ++i) {
8325 int r = reverse_bits(i, bits);
8327 order.push_back(first_leaf + r);
8330 std::vector<
int> access;
8331 for (
int i = 0; i < q; ++i)
8332 access.push_back(order[i % m]);
8341inline std::pair<tree::value, std::vector<std::pair<
int,
int>>>
8342centroid_decomposition_worst_case(
int n,
int q) {
8345 "hack: centroid_decomposition_worst_case: n must be at least 3");
8348 "hack: centroid_decomposition_worst_case: q must be at least 1");
8350 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8356inline std::pair<tree::value, std::vector<std::pair<
int,
int>>>
8357heavy_light_decomposition_worst_case(
int n,
int q) {
8360 "hack: heavy_light_decomposition_worst_case: n must be at least "
8364 "hack: heavy_light_decomposition_worst_case: q must be at least 1");
8366 return {detail::binary_heap_tree(n), detail::tree_path_worst_queries(n, q)};
8371inline std::pair<tree::value, std::vector<
int>>
8372link_cut_tree_worst_case(
int n,
int q) {
8373 tgen_ensure(n >= 2,
"hack: link_cut_tree_worst_case: n must be at least 2");
8374 tgen_ensure(q >= 1,
"hack: link_cut_tree_worst_case: q must be at least 1");
8376 return {detail::binary_heap_tree(n), detail::lct_worst_access(n, q)};
8382
8383
8384
8385
8394 "misc: parenthesis: size must be a positive even number");
8398 int open = 0, close = 0;
8400 for (
int i = 0; i < size; ++i) {
8406 if (open == close) {
8412 long long a = k - open, b = k - close, h = open - close;
8417 long long num = a * (h + 2);
8418 long long den = (a + b) * (h + 1);
8420 if (next<
long long>(1, den) <= num) {
std::vector< int > many_by_distribution(int k, const std::vector< T > &distribution)
Returns many random indices with given probabilities.
auto shuffled(const C &container)
Shuffles a container.
C::value_type pick(const C &container)
Chooses a random element from container.
void shuffle(It first, It last)
Shuffles range inplace, for random_access_iterator.
T wnext(T left, T right, int w)
Returns a skewed random number in range.
It::value_type pick(It first, It last)
Chooses a random element from an iterator range.
T next(T right)
Returns a random number smaller than value.
size_t next_by_distribution(const std::vector< T > &distribution)
Returns random index with given probabilities.
C::value_type pick_by_distribution(const C &container, std::vector< T > distribution)
Chooses a random element with given probabilities.
#define tgen_ensure(cond,...)
Ensures condition is true.
T next(T left, T right)
Returns a random number in range.
T wnext(T right, int w)
Returns a skewed random number smaller than value.
C choose(const C &container, int k)
Chooses elements from container, as in a subsequence fixed length.
std::vector< point< long long > > random_simple_polygon_through_points(const std::vector< point< long long > > &points)
Generates a random simple polygon through given points.
std::vector< point< long long > > random_points_general_position(int n, long long min_coord, long long max_coord)
Generates random points in general position inside a coordinate box.
std::vector< point< long long > > random_convex_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random convex polygon with given coordinate range.
std::vector< point< long long > > random_simple_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random simple polygon given coordinate range.
std::vector< point< long long > > random_orthogonal_polygon(int n, long long min_coord, long long max_coord, bool strict=false)
Generates a random orthogonal simple polygon.
wgraph< VWeight, int > vgraph
Vertex-weighted labeled graphs.
graph::value C(int n, bool is_directed=false)
Cycle graph.
wgraph< int, EWeight > egraph
Edge-weighted labeled graphs.
graph::value S(int n)
Star undirected graph.
graph::value K(int n1, int n2)
Complete bipartite undirected graph.
graph::value K(int n)
Complete undirected graph.
wgraph< int, int > graph
Unweighted labeled graphs.
graph::value P(int n, bool is_directed=false)
Path graph.
std::vector< std::pair< int, int > > mo_worst_case(int n, int q)
Query list that forces asymptotic worst-case for Mo's algorithm.
std::vector< bool > mt19937_xor_hash()
Mask that forces a zero XOR hash from std::mt19937 or std::mt19937_64.
egraph< int >::value spfa(int n)
Worst-case for FIFO-SPFA.
egraph< int >::value non_strict_relaxation_dijkstra_bug(int n)
Directed weighted graph for Dijkstra with non-strict relaxation.
std::string abacaba(int n)
Returns the prefix of the infinite word "abacabad...".
std::vector< geometry::point< double > > naive_rotating_calipers_max_dist_bug()
Convex polygon that breaks naive rotating calipers for maximum distance.
std::vector< long long > std_unordered(int size)
List of integers that tries to force collision on std::unordered_set.
std::vector< std::string > string_set_worst_case(int size)
List of strings that have high cost to insert in a std::set.
std::pair< std::string, std::string > unsigned_polynomial_hash()
Returns two strings that force polynomial hash collision for power-of-two mod.
std::pair< std::string, std::string > polynomial_hash(int alphabet_size, int base, int mod)
Returns two strings that force polynomial hash collision given base and mod.
egraph< int >::value dinitz_worst_case(int k, int l)
Flow network for Edmonds-Karp and Dinitz worst-case.
egraph< int >::value stale_heap_dijkstra_bug(int n)
Directed weighted graph for Dijkstra without a stale-heap check.
uint64_t prime_from(uint64_t left)
Computes smallest prime from given value.
uint64_t gen_divisor_count(uint64_t left, uint64_t right, int divisor_count)
Generates random number in range with a given prime number of divisors.
std::vector< int > gen_partition_fixed_size(int n, int k, int part_left=0, std::optional< int > part_right=std::nullopt)
Generates a random partition with fixed size of a number.
uint64_t totient(uint64_t n)
Euler's totient function.
uint64_t congruent_from(uint64_t left, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes smallest congruent from given value.
uint64_t congruent_upto(uint64_t right, uint64_t rem, uint64_t mod)
Computes largest congruent up to given value.
uint64_t gen_prime(uint64_t left, uint64_t right)
Generates a random prime in given range.
std::vector< uint64_t > factor(uint64_t n)
Factors a number into primes.
int num_divisors(uint64_t n)
Computes the number of divisors of a given number.
bool is_prime(uint64_t n)
Checks if a number is prime.
std::vector< int > gen_partition(int n, int part_left=1, std::optional< int > part_right=std::nullopt)
Generates a random partition of a number.
constexpr int FFT_MOD
FFT/NTT mod.
uint64_t gen_congruent(uint64_t left, uint64_t right, uint64_t rem, uint64_t mod)
Generates random number in range given a modular congruence.
uint64_t prime_upto(uint64_t right)
Computes largest prime up to given value.
uint64_t highly_composite_upto(uint64_t right)
Largest highly composite number up to given number.
uint64_t congruent_upto(uint64_t right, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Computes largest congruent up to given value.
std::vector< std::pair< uint64_t, int > > factor_by_prime(uint64_t n)
Factors a number into primes and its powers.
const std::vector< uint64_t > & fibonacci()
Fetches Fibonacci numbers.
uint64_t modular_inverse(uint64_t a, uint64_t mod)
Computes modular inverse.
uint64_t congruent_from(uint64_t left, uint64_t rem, uint64_t mod)
Computes smallest congruent from given value.
const std::vector< uint64_t > & highly_composites()
Fetches highly composite numbers.
std::vector< std::vector< T > > partition_elements(std::vector< T > elements, int k, int min_size=0, std::optional< uint64_t > max_size=std::nullopt)
Partitions a vector into k ordered groups.
std::vector< uint64_t > gen_partition_fixed_size_fast(uint64_t n, int k, uint64_t part_left=0, std::optional< uint64_t > part_right=std::nullopt)
Generates a fast non-uniform partition with fixed size.
uint64_t gen_congruent(uint64_t left, uint64_t right, std::vector< uint64_t > rems, std::vector< uint64_t > mods)
Generates random number in range given modular congruences.
std::pair< uint64_t, uint64_t > prime_gap_upto(uint64_t right)
Largest prime gap up to given number.
std::string gen_parenthesis(int size)
Generates a random valid parenthesis sequence.
T opt(const std::string &key, std::optional< T > default_value=std::nullopt)
Gets opt by key.
void set_compiler(compiler_value compiler)
Sets compiler.
T opt(size_t index, std::optional< T > default_value=std::nullopt)
Gets opt by key.
bool has_opt(std::size_t index)
Checks if opt at some index exists.
bool has_opt(const std::string &key)
Checks if opt with some key exists.
void set_cpp_version(int version)
Sets C++ version.
void register_gen(std::optional< long long > seed=std::nullopt)
Sets up the generator without arguments.
void register_gen(int argc, char **argv)
Sets up the generator.
wtree< VWeight, int > vtree
Vertex-weighted labeled trees.
wtree< int, EWeight > etree
Edge-weighted labeled trees.
wtree< int, int > tree
Unweighted labeled trees.
Compiler identity and version.
Distinct generator for containers.
auto gen_list(int size)
Generates a list of several distinct elements.
T gen()
Generates a distinct random element from the container.
distinct_container(const C &container)
Creates distinct generator for elements of the given container.
auto gen_all()
Generates all distinct elements left to generate.
size_t size() const
Returns the number of elements left to generate.
Distinct generator for integral ranges.
auto gen_list(int count)
Generates a list of several distinct values.
distinct_range(T left, T right)
Creates distinct generator for values in given range.
auto gen_all()
Generates all distinct values left to generate.
T gen()
Generates a distinct random value in the defined range.
T size() const
Returns the number of values left to generate.
Distinct generator for discrete uniform functions.
distinct(Func func, Args... args)
Generates a distinct generator of a discrete uniform function.
auto gen_list(int size)
Generates a list of several distinct values.
bool empty()
Checks if there is nothing left to generate.
auto gen_all()
Generates all distinct values left to generate.
auto gen()
Generates a distinct value.
Base class for generators (should not be instantiated).
auto gen_list(int size, Args &&...args) const
Generates a list of several generation calls.
auto gen_until(Pred predicate, int max_tries, Args &&...args) const
Generates a random value from the valid set until a condition is met.
auto distinct(Args &&...args) const
Creates distinct generator for current generator.
Base class for generator values (should not be instantiated).
bool operator<(const Val &rhs) const
bool operator==(const point &p) const
Coordinate-wise equality.
product_t operator*(const point &p) const
Dot product.
product_t operator^(const point &p) const
Cross product.
point operator*(T c) const
Scalar multiplication.
point operator-(const point &p) const
Vector subtraction.
point(T x=0, T y=0)
Constructs a point.
bool operator<(const point &p) const
Lexicographic order.
point operator+(const point &p) const
Vector addition.
int size() const
Returns the size of the list value.
value(const std::vector< T > &vec)
Creates a list value from a std::vector.
value & sort()
Sorts the list in non-decreasing order.
auto to_std() const
Converts the list to a std::vector.
value & separator(char sep)
Sets separator for printing.
value choose(int k) const
Chooses a uniformly random subsequence of given length.
value operator+(const value &rhs) const
Concatenates two lists.
T & operator[](int idx)
Accesses the element at some position of the list.
value & reverse()
Reverses the list.
T pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the list with given probabilities.
value & shuffle()
Shuffles the list in place.
T pick() const
Returns a uniformly random element.
list & different(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are different.
list & equal(int idx_1, int idx_2)
Restricts generator s.t. values at two indices are equal.
list & adjacent_different()
Restricts generator s.t. adjacent values are different.
list & all_different()
Restricts generator s.t. all values are different.
list & equal_range(int left, int right)
Restricts generator s.t. all values at index range are equal.
list(int size, std::set< T > values)
Creates list generator defined by value set.
value gen() const
Generates a uniformly random value from the set of valid lists.
list & all_equal()
Restricts generator s.t. all values are equal.
list & different(std::set< int > indices)
Restricts generator s.t. all values in index set are different.
list & different_range(int left, int right)
Restricts generator s.t. all values at index range are different.
list(int size, T value_left, T value_right)
Creates list generator defined by size and range of values.
list & fix(int idx, T val)
Restricts generator s.t. value at index is fixed.
list & equal(std::set< int > indices)
Restricts generator s.t. all values in index set are equal.
T second() const
Returns the second element of a pair value.
value(const T &first, const T &second)
Creates a pair value from first and second values.
value(const std::pair< T, T > &pair)
Creates a pair value from a std::pair.
auto to_std() const
Converts the pair to a std::pair.
T first() const
Returns the first element of a pair value.
value & separator(char sep)
Sets separator for printing.
value gen() const
Generates a uniformly random value from the set of valid pairs.
pair & neq()
Restricts generator s.t. first is not equal to second.
pair & leq()
Restricts generator s.t. first is less than or equal to second.
pair & lt()
Restricts generator s.t. first is less than second.
pair & gt()
Restricts generator s.t. first is greater than second.
pair(T both_left, T both_right)
Creates pair generator defined by range of values for both first and second.
pair & eq()
Restricts generator s.t. first is equal to second.
pair(T first_left, T first_right, T second_left, T second_right)
Creates pair generator defined by range of values for first and second.
pair & geq()
Restricts generator s.t. first is greater than or equal to second.
value & print_1_based()
Sets that printed values are 1-based.
std::vector< int > to_std() const
Converts the permutation to a std::vector.
const int & operator[](int idx) const
Returns the image at some position of the permutation.
std::vector< int > to_std_1_based() const
Converts the permutation to a 1-based std::vector.
value & sort()
Sorts the permutation in non-decreasing order.
int parity() const
Parity of the permutation.
int pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the permutation with given probabilities.
int pick() const
Returns a uniformly random element.
value & reverse()
Reverses the permutation.
value(const std::vector< int > &vec)
Creates a permutation value from a std::vector.
int size() const
Returns the size of the permutation value.
value & shuffle()
Shuffles the permutation.
value & inverse()
Inverse of the permutation.
value & separator(char sep)
Sets separator for printing.
value gen() const
Generates a uniformly random value from the set of valid permutations.
permutation & cycles(const std::vector< int > &cycle_sizes)
Restricts generator s.t. cycle sizes are fixed.
permutation(int size)
Creates permutation generator defined by size.
permutation & fix(int idx, int val)
Restricts generator s.t. value at index is fixed.
Printer helper for printing containers or sequential generator elements as columns.
print_cols(const Args &...args)
Creates a printer object that prints as columns.
Printer helper for standard types.
print(const T &val, char sep=' ')
Creates a printer object.
Printer helper for standard types, printing on a new line.
println(const T &val, char sep=' ')
Creates a printer object that prints on a new line.
char pick() const
Returns a uniformly random element.
char pick_by_distribution(const std::vector< Dist > &distribution) const
Returns a random element from the string with given probabilities.
value choose(int k) const
Chooses a uniformly random subsequence of given length.
value & lowercase()
Sets all characters to lowercase.
value & reverse()
Reverses the string.
int size() const
Returns the size of the string value.
value(const std::string &str)
Creates a string value from a std::string.
value & shuffle()
Shuffles the string.
char & operator[](int idx)
Accesses the character at some position of the string.
value & uppercase()
Sets all characters to uppercase.
value operator+(const value &rhs) const
Concatenates two strings.
std::string to_std() const
Converts the string to a std::string.
value & sort()
Sorts the characters in non-decreasing order.
str & different(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are different.
str & palindrome(int left, int right)
Restricts generator s.t. range is a palindrome.
value gen() const
Generates a uniformly random value from the set of valid strings.
str(int size, char value_left='a', char value_right='z')
Creates string generator defined by size and range of characters.
str & different(std::set< int > indices)
Restricts generator s.t. all characters in index set are different.
str(const std::string ®ex, Args &&...args)
Creates string generator defined by regex.
str & equal(int idx_1, int idx_2)
Restricts generator s.t. characters at two indices are equal.
str & equal(std::set< int > indices)
Restricts generator s.t. all characters in index set are equal.
str & equal_range(int left, int right)
Restricts generator s.t. all characters at index range are equal.
str & fix(int idx, char character)
Restricts generator s.t. character at index is fixed.
str & all_equal()
Restricts generator s.t. all values are equal.
str & different_range(int left, int right)
Restricts generator s.t. all characters at index range are different.
str & palindrome()
Restricts generator s.t. string is a palindrome.
str & all_different()
Restricts generator s.t. all characters are different.
str(int size, std::set< char > chars)
Creates string generator defined by character set.
str & adjacent_different()
Restricts generator s.t. adjacent values are different.
Sampler for repeated draws from a fixed weighted distribution.
size_t next() const
Generates a random index with probability proportional to the distribution.
weighted_sampler(const std::vector< T > &distribution)
Creates a weighted sampler from a probability distribution.
value & print_nm()
Prints number of vertices and edges before edge list.
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
value operator!() const
Graph complement of unweighted graph.
std::tuple< int, int, std::vector< std::set< int > > > to_std() const
Converts the graph to std types.
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
int n() const
Number of vertices.
value operator+(const value &rhs) const
Concatenates two graphs (disjoint union).
value & disjoint_union(const value &rhs)
Disjoint union with another graph.
int m() const
Number of edges.
std::tuple< int, int, std::vector< std::set< int > > > to_std_1_based() const
Converts the graph to 1-based std types.
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another graph at given vertex pairs.
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
value(const std::vector< std::set< int > > &adj, bool is_directed=false)
Builds a graph from an adjacency list.
value(int n, const std::vector< std::pair< int, int > > &edges={}, bool is_directed=false)
Builds a graph from number of vertices and edge list.
wgraph< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
const std::vector< std::set< int > > & adj() const
Adjacency list.
value & add_vertices(int k, std::optional< std::vector< VWeight > > new_vertex_weights=std::nullopt)
Adds new isolated vertices.
value & print_1_based()
Sets that printed vertex ids are 1-based.
value & random_connected_subgraph(int num_edges)
Random subgraph with a fixed number of edges that keeps components connected.
value(const typename wtree< VWeight, EWeight >::value &t)
Builds an undirected graph from a tree.
value & random_subgraph(int num_edges)
Random subgraph with a fixed number of edges.
value & edge_weighted()
Enables edge-weighted mode on an edgeless graph.
value & link(const value &rhs, int new_u, int new_v, std::optional< EWeight > new_w=std::nullopt)
Links two graphs by an new edge.
bool is_directed() const
If the graph is directed.
value & add_edge(int u, int v, std::optional< EWeight > w=std::nullopt)
Adds an edge between two vertices.
value & shuffle()
Shuffles all vertices and edge order.
wgraph< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
const std::vector< std::pair< int, int > > & edges() const
Edge list.
Labeled weighted graph generator.
wgraph(int n, int m, bool is_directed=false, bool has_self_loops=false)
Creates a graph generator for a fixed number of vertices and edges.
static value gen_bipartite(int n1, int n2, int m, bool connected=false)
Generates a random bipartite graph.
value get_connected() const
Random connected undirected graph extending preset edges.
static value gen_np(int n, double p, bool is_directed=false, bool has_self_loops=false)
Generates a random graph where each edge is included independently.
value gen() const
Generates a uniformly random graph satisfying the constraints.
wgraph & add_edge(int u, int v)
Adds a preset edge that must appear in the generated graph.
value get_acyclic() const
Random directed acyclic graph extending preset edges.
static value gen_skewed(int n, int m, int elongation, int spread, bool is_directed=false)
Random skewed connected graph (large diameter).
wgraph & add_edges_from(const value &rhs)
Adds all edges from another graph as preset edges.
value & glue(const value &rhs, std::set< std::pair< int, int > > index_pairs)
Glues another tree at given vertex pairs.
const std::vector< std::pair< int, int > > & edges() const
Edge list.
value(int n, const std::vector< std::pair< int, int > > &edges)
Builds a tree from a vertex count and an edge list.
value(const typename wgraph< VWeight, EWeight >::value &g)
Builds a tree from a graph via a Kruskal-like random spanning tree.
value & print_parents(int root=-1)
Prints in parent format instead of edge list.
const std::optional< std::vector< VWeight > > & vertex_weights() const
Optional vertex weights.
value & edge_weighted()
Enables edge-weighted mode on an edgeless tree.
int n() const
Returns the number of vertices.
value & shuffle_except(std::set< int > indices)
Shuffles vertices except given vertices, and edge order.
const std::vector< std::set< int > > & adj() const
Adjacency list.
value(const std::vector< std::set< int > > &adj)
Builds a tree from an adjacency list.
const std::optional< std::vector< EWeight > > & edge_weights() const
Optional edge weights.
value & shuffle()
Shuffles vertices and edge order.
std::pair< int, std::vector< std::set< int > > > to_std() const
Converts the tree to a std types.
wtree< NewVWeight, EWeight >::value set_vertex_weights(const std::vector< NewVWeight > &vertex_weights) const
Attaches vertex weights.
value & print_n()
Prints the number of vertices before the tree.
std::pair< int, std::vector< std::set< int > > > to_std_1_based() const
Converts the tree to 1-based std types.
value & link(const value &rhs, int new_u, int new_v, std::optional< EWeight > new_w=std::nullopt)
Links two trees by an edge.
value & print_1_based()
Sets that printed vertex ids are 1-based.
wtree< VWeight, NewEWeight >::value set_edge_weights(const std::vector< NewEWeight > &edge_weights) const
Attaches edge weights.
Labeled weighted tree generator.
wtree & add_edge(int u, int v)
Restricts generator s.t. some edge is present.
static value gen_skewed(int n, int elongation)
Random skewed tree (large diameter).
value gen() const
Generates a uniformly random value from the set of valid trees.
wtree(int n)
Creates a tree generator with specified number of vertices.
static value gen_kruskal(int n)
Kruskal-like random labeled tree.